org.semanticweb.elk.reasoner.taxonomy.ConcurrentTaxonomy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elk-reasoner Show documentation
Show all versions of elk-reasoner Show documentation
ELK consequence-based reasoning engine
/*
* #%L
* elk-reasoner
*
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2011 Oxford University Computing Laboratory
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
/**
* @author Yevgeny Kazakov, May 15, 2011
*/
package org.semanticweb.elk.reasoner.taxonomy;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import org.semanticweb.elk.owl.interfaces.ElkClass;
import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.owl.interfaces.ElkNamedIndividual;
import org.semanticweb.elk.owl.iris.ElkIri;
import org.semanticweb.elk.owl.predefined.PredefinedElkClass;
import org.semanticweb.elk.owl.printers.OwlFunctionalStylePrinter;
import org.semanticweb.elk.owl.util.Comparators;
import org.semanticweb.elk.reasoner.taxonomy.model.InstanceNode;
import org.semanticweb.elk.reasoner.taxonomy.model.InstanceTaxonomy;
import org.semanticweb.elk.reasoner.taxonomy.model.TaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.TypeNode;
import org.semanticweb.elk.util.collections.Operations;
import org.semanticweb.elk.util.collections.Operations.Condition;
/**
* Class taxonomy that is suitable for concurrent processing. Taxonomy objects
* are only constructed for consistent ontologies, and some consequences of this
* are hardcoded here.
*
* @author Yevgeny Kazakov
* @author Frantisek Simancik
* @author Markus Kroetzsch
*/
class ConcurrentTaxonomy extends IndividualClassTaxonomy {
// logger for events
private static final Logger LOGGER_ = Logger
.getLogger(ConcurrentTaxonomy.class);
/** thread safe map from class IRIs to class nodes */
private final ConcurrentMap classNodeLookup_;
/** thread safe set of all class nodes */
private final Set> allClassNodes_;
/** thread safe map from class IRIs to individual nodes */
private final ConcurrentMap individualNodeLookup_;
/** thread safe set of all individual nodes */
private final Set> allIndividualNodes_;
/** counts the number of nodes which have non-bottom sub-classes */
final AtomicInteger countNodesWithSubClasses;
/** thread safe set of unsatisfiable classes */
final Set unsatisfiableClasses;
/**
* The bottom node.
*/
final BottomClassNode bottomClassNode;
ConcurrentTaxonomy() {
this.classNodeLookup_ = new ConcurrentHashMap();
this.allClassNodes_ = Collections
.newSetFromMap(new ConcurrentHashMap, Boolean>());
this.individualNodeLookup_ = new ConcurrentHashMap();
this.allIndividualNodes_ = Collections
.newSetFromMap(new ConcurrentHashMap, Boolean>());
this.bottomClassNode = new BottomClassNode();
allClassNodes_.add(this.bottomClassNode);
this.countNodesWithSubClasses = new AtomicInteger(0);
this.unsatisfiableClasses = Collections
.synchronizedSet(new TreeSet(
Comparators.ELK_CLASS_COMPARATOR));
this.unsatisfiableClasses.add(PredefinedElkClass.OWL_NOTHING);
}
/**
* Returns the IRI of the given ELK entity.
*
* @return the IRI of the given ELK entity
*/
static ElkIri getKey(ElkEntity elkEntity) {
return elkEntity.getIri();
}
/**
* Obtain a {@link TypeNode} object for a given {@link ElkClass}, or
* {@code null} if none assigned.
*
* @param elkClass
* @return type node object for elkClass, possibly still incomplete
*/
@Override
public TypeNode getTypeNode(ElkClass elkClass) {
TypeNode result = classNodeLookup_
.get(getKey(elkClass));
if (result == null && unsatisfiableClasses.contains(elkClass))
result = bottomClassNode;
return result;
}
/**
* Obtain a {@link TypeNode} object for a given {@link ElkClass}, or
* {@code null} if none assigned.
*
* @param individual
* @return instance node object for elkClass, possibly still incomplete
*/
@Override
public InstanceNode getInstanceNode(
ElkNamedIndividual individual) {
return individualNodeLookup_.get(getKey(individual));
}
@Override
public TaxonomyNode getNode(ElkClass elkClass) {
return getTypeNode(elkClass);
}
@Override
public Set extends TypeNode> getTypeNodes() {
return Collections.unmodifiableSet(allClassNodes_);
}
@Override
public Set extends InstanceNode> getInstanceNodes() {
return Collections.unmodifiableSet(allIndividualNodes_);
}
@Override
public Set extends TaxonomyNode> getNodes() {
return getTypeNodes();
}
@Override
public TypeNode getTopNode() {
return getTypeNode(PredefinedElkClass.OWL_THING);
}
@Override
public TypeNode getBottomNode() {
return bottomClassNode;
}
@Override
NonBottomClassNode getCreateClassNode(Collection members) {
ElkClass someMember = members.iterator().next();
NonBottomClassNode previous = classNodeLookup_.get(getKey(someMember));
if (previous != null)
return previous;
NonBottomClassNode node = new NonBottomClassNode(this, members);
// we first assign the node to the canonical member to avoid
// concurrency problems
ElkClass canonical = node.getCanonicalMember();
previous = classNodeLookup_.putIfAbsent(getKey(canonical), node);
if (previous != null)
return previous;
allClassNodes_.add(node);
if (LOGGER_.isTraceEnabled()) {
LOGGER_.trace(OwlFunctionalStylePrinter.toString(canonical)
+ ": node created");
}
for (ElkClass member : members) {
if (member != canonical)
classNodeLookup_.put(getKey(member), node);
}
return node;
}
@Override
IndividualNode getCreateIndividualNode(
Collection members) {
IndividualNode node = new IndividualNode(this, members);
// we first assign the node to the canonical member to avoid
// concurrency problems
ElkNamedIndividual canonical = node.getCanonicalMember();
IndividualNode previous = individualNodeLookup_.putIfAbsent(
getKey(canonical), node);
if (previous != null)
return previous;
allIndividualNodes_.add(node);
if (LOGGER_.isTraceEnabled()) {
LOGGER_.trace(OwlFunctionalStylePrinter.toString(canonical)
+ ": node created");
}
for (ElkNamedIndividual member : members) {
if (member != canonical)
individualNodeLookup_.put(getKey(member), node);
}
return node;
}
@Override
void addUnsatisfiableClass(ElkClass elkClass) {
unsatisfiableClasses.add(elkClass);
}
/**
* Special implementation for the bottom node in the taxonomy. Instead of
* storing its sub- and super-classes, the respective answers are computed
* or taken from the taxonomy object directly. This saves memory at the cost
* of some performance if somebody should wish to traverse an ontology
* bottom-up starting from this node.
*/
protected class BottomClassNode implements
TypeNode {
@Override
public Set getMembers() {
return unsatisfiableClasses;
}
@Override
public ElkClass getCanonicalMember() {
return PredefinedElkClass.OWL_NOTHING;
}
@Override
public Set> getDirectSuperNodes() {
return Operations.filter(allClassNodes_,
new Condition>() {
@Override
public boolean holds(TaxonomyNode element) {
return element.getDirectSubNodes().contains(
bottomClassNode);
}
/*
* the direct super nodes of the bottom node are all
* nodes except the nodes that have no non-bottom
* sub-classes and the bottom node
*/
}, allClassNodes_.size() - countNodesWithSubClasses.get()
- 1);
}
@Override
public Set> getAllSuperNodes() {
/* all nodes except this one */
return Operations.filter(allClassNodes_, new Condition
© 2015 - 2025 Weber Informatics LLC | Privacy Policy