org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedClassExpression Maven / Gradle / Ivy
/*
* #%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%
*/
package org.semanticweb.elk.reasoner.indexing.hierarchy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.semanticweb.elk.reasoner.indexing.visitors.IndexedClassExpressionVisitor;
import org.semanticweb.elk.reasoner.saturation.rulesystem.Context;
import org.semanticweb.elk.util.collections.ArrayHashMap;
import org.semanticweb.elk.util.collections.ArrayHashSet;
import org.semanticweb.elk.util.hashing.HashGenerator;
/**
* Represents all occurrences of an ElkClassExpression in an ontology. To this
* end, objects of this class keeps a number of lists to describe the
* relationships to other (indexed) class expressions. The data structures are
* optimized for quickly retrieving the relevant relationships during
* inferencing.
*
* This class is mainly a data container that provides direct public access to
* its content. The task of updating index structures consistently in a global
* sense is left to callers.
*
* @author "Frantisek Simancik"
* @author "Markus Kroetzsch"
* @author "Yevgeny Kazakov"
*/
abstract public class IndexedClassExpression {
/**
* Correctness of axioms deletions requires that toldSuperClassExpressions
* is a List.
*/
private List toldSuperClassExpressions_;
private Map negConjunctionsByConjunct_;
private Collection negExistentials_;
/**
* {@link IndexedClassExpression} that appear in binary disjointess axioms
* with this object.
*/
private Set disjointClasses_;
/**
* List of all larger (non-binary) disjointness axioms in which this object
* appears.
*
*/
protected List disjointnessAxioms;
/**
* This counts how often this object occurred positively. Some indexing
* operations are only needed when encountering objects positively for the
* first time.
*/
int positiveOccurrenceNo = 0;
/**
* This counts how often this object occurred negatively. Some indexing
* operations are only needed when encountering objects negatively for the
* first time.
*/
int negativeOccurrenceNo = 0;
/**
* This method should always return true apart from intermediate steps
* during the indexing.
*
* @return true if the represented class expression occurs in the ontology
*/
public boolean occurs() {
return positiveOccurrenceNo > 0 || negativeOccurrenceNo > 0;
}
/**
* @return {@code true} if the represented class expression occurs
* negatively in the ontology
*/
public boolean occursNegatively() {
return negativeOccurrenceNo > 0;
}
/**
* @return {@code true} if the represented class expression occurs
* positively in the ontology
*/
public boolean occursPositively() {
return positiveOccurrenceNo > 0;
}
/**
* Non-recursively. The recursion is implemented in indexing visitors.
*/
abstract void updateOccurrenceNumbers(int increment, int positiveIncrement,
int negativeIncrement);
/**
* @return All told super class expressions of this class expression,
* possibly null.
*/
public List getToldSuperClassExpressions() {
return toldSuperClassExpressions_;
}
/**
* @return the {@link IndexedObjectIntersectionOf} objects that occur
* negatively and contain this {@link IndexedClassExpression},
* indexed by the other {@link IndexedClassExpression} in the
* conjunction, or {@code null} if none is assigned
*/
public Map getNegConjunctionsByConjunct() {
return negConjunctionsByConjunct_;
}
/**
* @return the {@link IndexedObjectSomeValuesFrom} objects that occur
* negatively and have this {@link IndexedClassExpression} as the
* filler, or {@code null} if none is assigned
*/
public Collection getNegExistentials() {
return negExistentials_;
}
/**
* @return the {@link IndexedClassExpression} objects that occur with this
* object in binary disjointness axioms, or {@code null} if none is
* assigned
*/
public Set getDisjointClasses() {
return disjointClasses_;
}
/**
* @return Collection of all (non-binary) {@link IndexedDisjointnessAxiom}s
* in which this object appears, or {@code null} if none is assigned
*/
public List getDisjointnessAxioms() {
return disjointnessAxioms;
}
protected void addToldSuperClassExpression(
IndexedClassExpression superClassExpression) {
if (toldSuperClassExpressions_ == null)
toldSuperClassExpressions_ = new ArrayList(
1);
toldSuperClassExpressions_.add(superClassExpression);
}
/**
* @param superClassExpression
* @return true if successfully removed
*/
protected boolean removeToldSuperClassExpression(
IndexedClassExpression superClassExpression) {
boolean success = false;
if (toldSuperClassExpressions_ != null) {
success = toldSuperClassExpressions_.remove(superClassExpression);
if (toldSuperClassExpressions_.isEmpty())
toldSuperClassExpressions_ = null;
}
return success;
}
protected void addNegConjunctionByConjunct(
IndexedObjectIntersectionOf conjunction,
IndexedClassExpression conjunct) {
if (negConjunctionsByConjunct_ == null) {
negConjunctionsByConjunct_ = new ArrayHashMap(
4);
}
if (negConjunctionsByConjunct_.put(conjunct, conjunction) != null) {
// Can be caused e.g. when ElkObjectIndexerVisitor indexed conjuncts
// with equals hashCodes.
throw new RuntimeException(
"Internal error: duplicate indexing in IndexedClassExpression.addNegConjunctionByConjunct.");
}
}
/**
* @param conjunction
* @param conjunct
* @return true if successfully removed
*/
protected boolean removeNegConjunctionByConjunct(
IndexedObjectIntersectionOf conjunction,
IndexedClassExpression conjunct) {
boolean success = false;
if (negConjunctionsByConjunct_ != null) {
success = (negConjunctionsByConjunct_.remove(conjunct) != null);
if (negConjunctionsByConjunct_.isEmpty())
negConjunctionsByConjunct_ = null;
}
return success;
}
protected void addNegExistential(IndexedObjectSomeValuesFrom existential) {
if (negExistentials_ == null)
negExistentials_ = new ArrayList(1);
negExistentials_.add(existential);
}
/**
* @param existential
* @return true if successfully removed
*/
protected boolean removeNegExistential(
IndexedObjectSomeValuesFrom existential) {
boolean success = false;
if (negExistentials_ != null) {
success = negExistentials_.remove(existential);
if (negExistentials_.isEmpty())
negExistentials_ = null;
}
return success;
}
protected void addDisjointClass(IndexedClassExpression disjointClass) {
if (disjointClasses_ == null)
disjointClasses_ = new ArrayHashSet();
disjointClasses_.add(disjointClass);
}
/**
* @param disjointClass
* @return true if successfully removed
*/
protected boolean removeDisjointClass(IndexedClassExpression disjointClass) {
boolean success = false;
if (disjointClasses_ != null) {
success = disjointClasses_.remove(disjointClass);
if (disjointClasses_.isEmpty())
disjointClasses_ = null;
}
return success;
}
protected void addDisjointnessAxiom(
IndexedDisjointnessAxiom disjointnessAxiom) {
if (disjointnessAxioms == null)
disjointnessAxioms = new LinkedList();
disjointnessAxioms.add(disjointnessAxiom);
}
/**
* @param disjointnessAxiom
* @return true if successfully removed
*/
protected boolean removeDisjointnessAxiom(
IndexedDisjointnessAxiom disjointnessAxiom) {
boolean success = false;
if (disjointnessAxioms != null) {
Iterator i = disjointnessAxioms
.iterator();
while (i.hasNext())
if (i.next().getMembers()
.equals(disjointnessAxiom.getMembers())) {
i.remove();
break;
}
if (disjointnessAxioms.isEmpty())
disjointnessAxioms = null;
}
return success;
}
// TODO: replace pointers to contexts by a mapping
/**
* Used for efficient retrieval of the Context corresponding to this class
* expression.
*/
protected final AtomicReference context = new AtomicReference();
/**
* @return The corresponding context, null if none was assigned.
*/
public Context getContext() {
return context.get();
}
/**
* Sets the corresponding context if none was yet assigned.
*
* @param context
* the {@link Context} which will be assigned to this
* {@link IndexedClassExpression}
*
* @return {@code true} if the operation succeeded.
*/
public boolean setContext(Context context) {
return this.context.compareAndSet(null, context);
}
/**
* Resets the corresponding context to null.
*/
public void resetContext() {
context.set(null);
}
/** Hash code for this object. */
private final int hashCode_ = HashGenerator.generateNextHashCode();
/**
* Get an integer hash code to be used for this object.
*
* @return Hash code.
*/
@Override
public final int hashCode() {
return hashCode_;
}
public abstract O accept(IndexedClassExpressionVisitor visitor);
@Override
public abstract String toString();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy