All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.semanticweb.elk.reasoner.indexing.conversion.ElkAxiomConverterImpl Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2014 Department of Computer Science, University of Oxford
 * %%
 * 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.conversion;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import org.semanticweb.elk.owl.interfaces.ElkAsymmetricObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkAxiom;
import org.semanticweb.elk.owl.interfaces.ElkClassAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkClassExpression;
import org.semanticweb.elk.owl.interfaces.ElkDataPropertyAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDataPropertyDomainAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDataPropertyRangeAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDatatypeDefinitionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDeclarationAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDifferentIndividualsAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDisjointClassesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDisjointDataPropertiesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDisjointObjectPropertiesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDisjointUnionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkEquivalentClassesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkEquivalentDataPropertiesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkEquivalentObjectPropertiesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkFunctionalDataPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkFunctionalObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkHasKeyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkIndividual;
import org.semanticweb.elk.owl.interfaces.ElkInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkInverseObjectPropertiesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkIrreflexiveObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkNegativeDataPropertyAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkNegativeObjectPropertyAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkObject;
import org.semanticweb.elk.owl.interfaces.ElkObjectInverseOf;
import org.semanticweb.elk.owl.interfaces.ElkObjectProperty;
import org.semanticweb.elk.owl.interfaces.ElkObjectPropertyAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkObjectPropertyChain;
import org.semanticweb.elk.owl.interfaces.ElkObjectPropertyDomainAxiom;
import org.semanticweb.elk.owl.interfaces.ElkObjectPropertyExpression;
import org.semanticweb.elk.owl.interfaces.ElkObjectPropertyRangeAxiom;
import org.semanticweb.elk.owl.interfaces.ElkReflexiveObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSWRLRule;
import org.semanticweb.elk.owl.interfaces.ElkSameIndividualAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSubClassOfAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSubDataPropertyOfAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSubObjectPropertyOfAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSymmetricObjectPropertyAxiom;
import org.semanticweb.elk.owl.interfaces.ElkTransitiveObjectPropertyAxiom;
import org.semanticweb.elk.owl.predefined.ElkPolarity;
import org.semanticweb.elk.owl.predefined.PredefinedElkClassFactory;
import org.semanticweb.elk.owl.visitors.ElkSubObjectPropertyExpressionVisitor;
import org.semanticweb.elk.reasoner.completeness.Feature;
import org.semanticweb.elk.reasoner.completeness.OccurrenceListener;
import org.semanticweb.elk.reasoner.indexing.classes.ResolvingModifiableIndexedObjectFactory;
import org.semanticweb.elk.reasoner.indexing.classes.UpdatingModifiableIndexedObjectFactory;
import org.semanticweb.elk.reasoner.indexing.model.IndexedAxiom;
import org.semanticweb.elk.reasoner.indexing.model.IndexedAxiomInference;
import org.semanticweb.elk.reasoner.indexing.model.IndexedClass;
import org.semanticweb.elk.reasoner.indexing.model.IndexedClassExpression;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObject;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedAxiom;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedAxiomInference;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedClass;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedClassExpression;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedClassExpressionList;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedIndividual;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedObject;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedObjectIntersectionOf;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedObjectProperty;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableIndexedPropertyChain;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableOntologyIndex;
import org.semanticweb.elk.reasoner.indexing.model.OccurrenceIncrement;
import org.semanticweb.elk.reasoner.proof.ReasonerProducer;

/**
 * An implementation of {@link ElkAxiomConverter} that converts {@link ElkAxiom}
 * s to {@link ModifiableIndexedAxiom}s using a
 * {@link ModifiableIndexedAxiomInference.Factory} in addition to converters and
 * factories for other types of {@link IndexedObject}s.
 * 
 * @author Frantisek Simancik
 * @author "Yevgeny Kazakov"
 * @author Peter Skocovsky
 */
public class ElkAxiomConverterImpl extends NoOpElkAnnotationAxiomConverter
		implements ElkAxiomConverter,
		ElkSubObjectPropertyExpressionVisitor {

	private interface DisjointnessIndexer {

		ModifiableIndexedClassExpression convert(M member);

		void indexBinary(A axiom, int firstMemberPosition,
				int secondMemberPosition,
				ModifiableIndexedObjectIntersectionOf memberConunction,
				ModifiableIndexedClass bottom);

		void indexNary(A axiom, ModifiableIndexedClassExpressionList members);
	}

	private class ElkDifferentIndividualsAxiomDisjointnessIndexer implements
			DisjointnessIndexer {

		@Override
		public ModifiableIndexedClassExpression convert(ElkIndividual member) {
			return member.accept(negativeConverter_);
		}

		@Override
		public void indexBinary(ElkDifferentIndividualsAxiom axiom,
				int firstMemberPosition, int secondMemberPosition,
				ModifiableIndexedObjectIntersectionOf memberConunction,
				ModifiableIndexedClass bottom) {
			axiomInferenceFactory_
					.getElkDifferentIndividualsAxiomBinaryConversion(axiom,
							firstMemberPosition, secondMemberPosition,
							memberConunction, bottom);
		}

		@Override
		public void indexNary(ElkDifferentIndividualsAxiom axiom,
				ModifiableIndexedClassExpressionList members) {
			axiomInferenceFactory_
					.getElkDifferentIndividualsAxiomNaryConversion(axiom,
							members);
		}
	}

	private class ElkDisjointClassesAxiomDisjointnessIndexer implements
			DisjointnessIndexer {

		@Override
		public ModifiableIndexedClassExpression convert(
				ElkClassExpression member) {
			return member.accept(negativeConverter_);
		}

		@Override
		public void indexBinary(ElkDisjointClassesAxiom axiom,
				int firstMemberPosition, int secondMemberPosition,
				ModifiableIndexedObjectIntersectionOf memberConunction,
				ModifiableIndexedClass bottom) {
			axiomInferenceFactory_.getElkDisjointClassesAxiomBinaryConversion(
					axiom, firstMemberPosition, secondMemberPosition,
					memberConunction, bottom);
		}

		@Override
		public void indexNary(ElkDisjointClassesAxiom axiom,
				ModifiableIndexedClassExpressionList members) {
			axiomInferenceFactory_
					.getElkDisjointClassesAxiomNaryConversion(axiom, members);
		}
	}

	private class ElkDisjointUnionAxiomDisjointnessIndexer implements
			DisjointnessIndexer {

		@Override
		public ModifiableIndexedClassExpression convert(
				ElkClassExpression member) {
			return member.accept(negativeConverter_);
		}

		@Override
		public void indexBinary(ElkDisjointUnionAxiom axiom,
				int firstMemberPosition, int secondMemberPosition,
				ModifiableIndexedObjectIntersectionOf memberConunction,
				ModifiableIndexedClass bottom) {
			axiomInferenceFactory_.getElkDisjointUnionAxiomBinaryConversion(
					axiom, firstMemberPosition, secondMemberPosition,
					memberConunction, bottom);
		}

		@Override
		public void indexNary(ElkDisjointUnionAxiom axiom,
				ModifiableIndexedClassExpressionList members) {
			axiomInferenceFactory_.getElkDisjointUnionAxiomNaryConversion(axiom,
					members);
		}

	}

	/**
	 * With at most how many disjoint classes transform to binary disjointness
	 * axioms
	 */
	private final static int DISJOINT_AXIOM_BINARIZATION_THRESHOLD = 2;

	/**
	 * The factory to convert axioms
	 */
	private final ModifiableIndexedAxiomInference.Factory axiomInferenceFactory_;
	
	private final ElkDifferentIndividualsAxiomDisjointnessIndexer elkDifferentIndividualsAxiomDisjointnessIndexer = new ElkDifferentIndividualsAxiomDisjointnessIndexer();

	private final ElkDisjointClassesAxiomDisjointnessIndexer elkDisjointClassesAxiomDisjointnessIndexer = new ElkDisjointClassesAxiomDisjointnessIndexer();

	private final ElkDisjointUnionAxiomDisjointnessIndexer elkDisjointUnionAxiomDisjointnessIndexer = new ElkDisjointUnionAxiomDisjointnessIndexer();

	/**
	 * The factory for creating entities
	 */
	private final PredefinedElkClassFactory elkFactory_;

	private final ElkEntityConverter entityConverter_;

	private final int increment_;

	private final OccurrenceListener occurrenceListener_;

	private final ElkPolarityExpressionConverter positiveConverter_,
			negativeConverter_, dualConverter_;

	/**
	 * The factories to create objects of respectively positive and negative
	 * polarities of occurrences.
	 */
	private final ModifiableIndexedObject.Factory positiveFactory_,
			negativeFactory_;

	/**
	 * Creates an {@link ElkAxiomConverter} that uses four
	 * {@link ModifiableIndexedObject.Factory}s to create all
	 * {@link ModifiableIndexedObject} sub-expression of the resulting
	 * {@link ModifiableIndexedAxiom}s depending on (logical) polarity of their
	 * occurrence.
	 * 
	 * @param elkFactory
	 *            used to create auxiliary {@link ElkObject}s
	 * 
	 * @param neutralFactory
	 *            this {@link ModifiableIndexedAxiomInference.Factory} is used
	 *            to create {@link IndexedAxiom}s as well as
	 *            {@link ModifiableIndexedObject}s that do not occur (logically)
	 *            positively or negatively in the ontology, such as entities in
	 *            declaration axioms
	 * @param positiveFactory
	 *            this {@link ModifiableIndexedObject.Factory} is used to create
	 *            positive occurrences of {@link ModifiableIndexedObject}s, such
	 *            as {@link IndexedClassExpression}s on the right-hand-side of
	 *            {@code SubClassOf} axioms.
	 * 
	 * @param negativeFactory
	 *            this {@link ModifiableIndexedObject.Factory} is used to create
	 *            negative occurrences of {@link ModifiableIndexedObject}s, such
	 *            as {@link IndexedClassExpression}s on the right-hand-side of
	 *            {@code SubClassOf} axioms.
	 * @param dualFactory
	 *            this {@link ModifiableIndexedObject.Factory} is used to create
	 *            simultaneously positive and negative occurrences of
	 *            {@link ModifiableIndexedObject}s, such as
	 *            {@link IndexedClassExpression}s in {@code EquivalentClasses}
	 *            axioms.
	 * @param occurrenceTracker
	 *            the {@link OccurrenceListener} used to keep track of
	 *            problematic occurrences of constructors
	 * @param increment
	 *            indicates whether the converted axioms must be inserted {@code (> 0)}
	 *            or deleted {@code (< 0)} and with which multiplicity          
	 * @param producer
	 *            a {@link ReasonerProducer} used to record the conversion inferences
	 */
	public ElkAxiomConverterImpl(PredefinedElkClassFactory elkFactory,
			ModifiableIndexedObject.Factory neutralFactory,
			ModifiableIndexedObject.Factory positiveFactory,
			ModifiableIndexedObject.Factory negativeFactory,
			ModifiableIndexedObject.Factory dualFactory,
			OccurrenceListener occurrenceTracker,
			int increment,
			ReasonerProducer producer) {
		this.elkFactory_ = elkFactory;
		this.axiomInferenceFactory_ = new ModifiableIndexedAxiomInferenceConclusionVisitingFactory(
				producer, neutralFactory);
		this.positiveFactory_ = positiveFactory;
		this.negativeFactory_ = negativeFactory;
		this.positiveConverter_ = new ElkPolarityExpressionConverterImpl(
				ElkPolarity.POSITIVE, elkFactory, positiveFactory,
				negativeFactory, occurrenceTracker, increment);
		this.negativeConverter_ = positiveConverter_
				.getComplementaryConverter();
		this.dualConverter_ = new ElkPolarityExpressionConverterImpl(elkFactory,
				dualFactory, occurrenceTracker, increment);
		this.entityConverter_ = new ElkEntityConverterImpl(neutralFactory);
		this.occurrenceListener_ = occurrenceTracker;
		this.increment_ = increment;
	}

	/**
	 * Creates an {@link ElkAxiomConverter} that uses the given
	 * {@link ModifiableIndexedObject.Factory} to create all
	 * {@link ModifiableIndexedObject} sub-expression of the resulting
	 * {@link ModifiableIndexedAxiom}s.
	 * 
	 * @param elkFactory
	 *            used to create auxiliary {@link ElkObject}s
	 * 
	 * @param factory
	 *            the {@link ModifiableIndexedObject.Factory} that is used to
	 *            create all {@link ModifiableIndexedObject}s necessary for
	 *            conversion of {@link ElkAxiom}s.
	 * @param occurrenceTracker
	 *            the {@link OccurrenceListener} used to keep track of
	 *            problematic occurrences of constructors
	 * @param increment
	 *            indicates whether the converted axioms must be inserted
	 *            {@code (> 0)} or deleted {@code (< 0)} and with which
	 *            multiplicity
	 * @param producer
	 *            a {@link ReasonerProducer} used to record the conversion
	 *            inferences
	 */
	public ElkAxiomConverterImpl(PredefinedElkClassFactory elkFactory,
			ModifiableIndexedObject.Factory factory,
			final OccurrenceListener occurrenceTracker, int increment,
			ReasonerProducer producer) {
		this(elkFactory, factory, factory, factory, factory, occurrenceTracker, increment,
				producer);
	}

	/**
	 * Creates an {@link ElkAxiomConverter} for converting {@link ElkAxiom}s
	 * that have already been indexed in the given
	 * {@link ModifiableOntologyIndex}. All {@link ModifiableIndexedObject}
	 * subexpressions of the converted {@link ModifiableIndexedAxiom}s are taken
	 * from this {@link ModifiableOntologyIndex} as well. The provided
	 * {@link ModifiableOntologyIndex} will not change. The converter may not
	 * work properly if used with {@link ElkAxiom}s that have not been indexed
	 * in the given {@link ModifiableOntologyIndex} (e.g.,
	 * {@link NullPointerException}s may occur).
	 * 
	 * @param elkFactory
	 *            used to create auxiliary {@link ElkObject}s
	 * 
	 * @param index
	 *            the {@link ModifiableOntologyIndex} from which all
	 *            {@link ModifiableIndexedObject}s are used.
	 */
	public ElkAxiomConverterImpl(PredefinedElkClassFactory elkFactory,
			ModifiableOntologyIndex index) {
		this(elkFactory, new ResolvingModifiableIndexedObjectFactory(index),
				index, 0, ReasonerProducer.dummy());
	}

	/**
	 * Creates an {@link ElkAxiomConverter} that converts {@link ElkAxiom}s and
	 * adds them to the provided {@link ModifiableOntologyIndex} with the given
	 * multiplicity. The converter will also insert all intermediate
	 * {@link ModifiableIndexedObject} subexpressions of the created
	 * {@link ModifiableIndexedAxiom}s with the same multiplicity for polarity
	 * of their occurrences. Some {@link ModifiableIndexedObject}s will be
	 * reused and only their multiplicity will be updated.
	 * 
	 * @param elkFactory
	 *            used to create auxiliary {@link ElkObject}s
	 * 
	 * @param index
	 *            the {@link ModifiableOntologyIndex} representing the ontology
	 *            to which the resulting {@link ModifiableIndexedObject}s will
	 *            be added and processed (compiled to rules).
	 * @param increment
	 *            the multiplicity with which the created
	 *            {@link ModifiableIndexedAxiom}s should be inserted to the
	 *            {@link ModifiableOntologyIndex} (e.g., 2 means 2 copies of
	 *            each create axiom should be added); it can be negative, which
	 *            means that the {@link ModifiableIndexedAxiom}s should be
	 *            removed the corresponding number of times.
	 * 
	 */
	public ElkAxiomConverterImpl(PredefinedElkClassFactory elkFactory,
			ModifiableOntologyIndex index, int increment) {
		this(elkFactory,
				new UpdatingModifiableIndexedObjectFactory(index,
						OccurrenceIncrement.getNeutralIncrement(increment)),
				new UpdatingModifiableIndexedObjectFactory(index,
						OccurrenceIncrement.getPositiveIncrement(increment)),
				new UpdatingModifiableIndexedObjectFactory(index,
						OccurrenceIncrement.getNegativeIncrement(increment)),
				new UpdatingModifiableIndexedObjectFactory(index,
						OccurrenceIncrement.getDualIncrement(increment)),
				index, increment, ReasonerProducer.dummy());
	}

	private  void indexDisjointMembers(
			DisjointnessIndexer indexer, A axiom,
			List members) {
		/*
		 * for many disjoint members, convert natively
		 */
		if (members.size() > DISJOINT_AXIOM_BINARIZATION_THRESHOLD) {
			List indexedMembers = new ArrayList(
					members.size());
			for (M member : members)
				indexedMembers.add(indexer.convert(member));
			indexer.indexNary(axiom, positiveFactory_
					.getIndexedClassExpressionList(indexedMembers));
			return;
		}
		/*
		 * otherwise create a binary disjointness axioms for all pairs (first,
		 * second) where second occurs after the first in the member list
		 */
		ModifiableIndexedClass indexedOwlNothing = positiveFactory_
				.getIndexedClass(elkFactory_.getOwlNothing());
		for (int firstPos = 0; firstPos < members.size(); firstPos++) {
			M first = members.get(firstPos);
			ModifiableIndexedClassExpression firstIndexed = indexer
					.convert(first);
			for (int secondPos = firstPos + 1; secondPos < members
					.size(); secondPos++) {
				M second = members.get(secondPos);
				ModifiableIndexedClassExpression secondIndexed = indexer
						.convert(second);
				indexer.indexBinary(axiom, firstPos, secondPos,
						negativeFactory_.getIndexedObjectIntersectionOf(
								firstIndexed, secondIndexed),
						indexedOwlNothing);
			}
		}
	}

	private ElkIndexingUnsupportedFeature unsupported(Feature feature) {
		return new ElkIndexingUnsupportedFeature(feature);
	}

	@Override
	public Void visit(ElkAsymmetricObjectPropertyAxiom axiom) {
		throw unsupported(Feature.ASYMMETRIC_OBJECT_PROPERTY);
	}

	@Override
	public Void visit(ElkClassAssertionAxiom axiom) {
		axiomInferenceFactory_.getElkClassAssertionAxiomConversion(axiom,
				axiom.getIndividual().accept(negativeConverter_),
				axiom.getClassExpression().accept(positiveConverter_));
		return null;
	}

	@Override
	public Void visit(ElkDataPropertyAssertionAxiom axiom) {
		throw unsupported(Feature.DATA_PROPERTY_ASSERTION);
	}

	@Override
	public Void visit(ElkDataPropertyDomainAxiom axiom) {
		throw unsupported(Feature.DATA_PROPERTY_DOMAIN);
	}

	@Override
	public Void visit(ElkDataPropertyRangeAxiom axiom) {
		throw unsupported(Feature.DATA_PROPERTY_RANGE);
	}

	@Override
	public Void visit(ElkDatatypeDefinitionAxiom axiom) {
		throw unsupported(Feature.DATATYPE_DEFINITION);
	}

	@Override
	public Void visit(ElkDeclarationAxiom axiom) {
		axiomInferenceFactory_.getElkDeclarationAxiomConversion(axiom,
				axiom.getEntity().accept(entityConverter_));
		return null;
	}

	@Override
	public Void visit(ElkDifferentIndividualsAxiom axiom) {
		indexDisjointMembers(elkDifferentIndividualsAxiomDisjointnessIndexer,
				axiom, axiom.getIndividuals());
		occurrenceListener_.occurrenceChanged(Feature.DIFFERENT_INDIVIDUALS,
				increment_);
		return null;
	}

	@Override
	public Void visit(ElkDisjointClassesAxiom axiom) {
		indexDisjointMembers(elkDisjointClassesAxiomDisjointnessIndexer, axiom,
				axiom.getClassExpressions());
		occurrenceListener_.occurrenceChanged(Feature.DISJOINT_CLASSES,
				increment_);
		return null;
	}

	@Override
	public Void visit(ElkDisjointDataPropertiesAxiom axiom) {
		throw unsupported(Feature.DISJOINT_DATA_PROPERTIES);
	}

	@Override
	public Void visit(ElkDisjointObjectPropertiesAxiom axiom) {
		throw unsupported(Feature.DISJOINT_OBJECT_PROPERTIES);
	}
	
	@Override
	public Void visit(ElkDisjointUnionAxiom axiom) {
		List disjoint = axiom
				.getClassExpressions();
		indexDisjointMembers(elkDisjointUnionAxiomDisjointnessIndexer, axiom,
				disjoint);
		ModifiableIndexedClass defined;
		ModifiableIndexedClassExpression member;
		int size = disjoint.size();
		switch (size) {
		case 0:
			defined = (ModifiableIndexedClass) axiom.getDefinedClass()
					.accept(positiveConverter_);
			axiomInferenceFactory_.getElkDisjointUnionAxiomOwlNothingConversion(
					axiom, defined, positiveFactory_
							.getIndexedClass(elkFactory_.getOwlNothing()));
			break;
		case 1:
			defined = (ModifiableIndexedClass) axiom.getDefinedClass()
					.accept(dualConverter_);
			member = disjoint.iterator().next().accept(dualConverter_);
			axiomInferenceFactory_
					.getElkDisjointUnionAxiomEquivalenceConversion(axiom,
							defined, member);
			break;
		default:
			// indexing only one direction of the equivalence
			occurrenceListener_.occurrenceChanged(
					Feature.DISJOINT_UNION, increment_);
			defined = (ModifiableIndexedClass) axiom.getDefinedClass()
					.accept(positiveConverter_);
			for (int pos = 0; pos < size; pos++) {
				ElkClassExpression c = disjoint.get(pos);
				member = c.accept(negativeConverter_);
				axiomInferenceFactory_
						.getElkDisjointUnionAxiomSubClassConversion(axiom, pos,
								member, defined);
			}
			break;
		}
		return null;
	}

	@Override
	public Void visit(ElkEquivalentClassesAxiom axiom) {
		// reduces equivalence to class definitions or sub-class axioms
		ModifiableIndexedClassExpression first = null;
		boolean firstIsAClass = false;
		List members = axiom
				.getClassExpressions();
		for (int pos = 0; pos < members.size(); pos++) {
			ElkClassExpression c = members.get(pos);
			if (first == null) {
				first = c.accept(dualConverter_);
				if (first instanceof IndexedClass) {
					firstIsAClass = true;
				}
			} else {
				ModifiableIndexedClassExpression other = c
						.accept(dualConverter_);
				if (!firstIsAClass && other instanceof ModifiableIndexedClass) {
					axiomInferenceFactory_
							.getElkEquivalentClassesAxiomEquivalenceConversion(
									axiom, pos, 0, other, first);
				} else {
					axiomInferenceFactory_
							.getElkEquivalentClassesAxiomEquivalenceConversion(
									axiom, 0, pos, first, other);
				}
			}
		}
		return null;

	}

	@Override
	public Void visit(ElkEquivalentDataPropertiesAxiom axiom) {
		throw unsupported(Feature.EQUIVALENT_DATA_PROPERTIES);
	}

	@Override
	public Void visit(ElkEquivalentObjectPropertiesAxiom axiom) {
		// reduces equivalence to sub-property axioms
		ModifiableIndexedObjectProperty first = null;
		List members = axiom
				.getObjectPropertyExpressions();
		for (int pos = 0; pos < members.size(); pos++) {
			ElkObjectPropertyExpression pe = members.get(pos);
			if (first == null)
				first = pe.accept(dualConverter_);
			else {
				ModifiableIndexedObjectProperty other = pe
						.accept(dualConverter_);
				axiomInferenceFactory_
						.getElkEquivalentObjectPropertiesAxiomConversion(axiom,
								0, pos, first, other);
				axiomInferenceFactory_
						.getElkEquivalentObjectPropertiesAxiomConversion(axiom,
								pos, 0, other, first);
			}
		}
		return null;
	}

	@Override
	public Void visit(ElkFunctionalDataPropertyAxiom axiom) {
		throw unsupported(Feature.FUNCTIONAL_DATA_PROPERTY);
	}

	@Override
	public Void visit(ElkFunctionalObjectPropertyAxiom axiom) {
		throw unsupported(Feature.FUNCTIONAL_OBJECT_PROPERTY);
	}

	@Override
	public Void visit(ElkHasKeyAxiom axiom) {
		throw unsupported(Feature.HAS_KEY);
	}

	@Override
	public Void visit(ElkInverseFunctionalObjectPropertyAxiom axiom) {
		throw unsupported(Feature.INVERSE_FUNCTIONAL_OBJECT_PROPERTY);
	}

	@Override
	public Void visit(ElkInverseObjectPropertiesAxiom axiom) {
		throw unsupported(Feature.INVERSE_OBJECT_PROPERTIES);
	}

	@Override
	public Void visit(ElkIrreflexiveObjectPropertyAxiom axiom) {
		throw unsupported(Feature.IRREFLEXIVE_OBJECT_PROPERTY);
	}

	@Override
	public Void visit(ElkNegativeDataPropertyAssertionAxiom axiom) {
		throw unsupported(Feature.NEGATIVE_DATA_PROPERTY_ASSERTION);
	}

	@Override
	public Void visit(ElkNegativeObjectPropertyAssertionAxiom axiom) {
		throw unsupported(Feature.NEGATIVE_OBJECT_PROPERTY_ASSERTION);
	}

	@Override
	public ModifiableIndexedPropertyChain visit(ElkObjectInverseOf expression) {
		throw unsupported(Feature.OBJECT_INVERSE_OF);
	}

	@Override
	public ModifiableIndexedPropertyChain visit(ElkObjectProperty expression) {
		return expression.accept(negativeConverter_);
	}

	@Override
	public Void visit(ElkObjectPropertyAssertionAxiom axiom) {
		occurrenceListener_.occurrenceChanged(
				Feature.OBJECT_PROPERTY_ASSERTION, increment_);
		axiomInferenceFactory_.getElkObjectPropertyAssertionAxiomConversion(
				axiom, axiom.getSubject().accept(negativeConverter_),
				positiveFactory_.getIndexedObjectSomeValuesFrom(
						axiom.getProperty().accept(positiveConverter_), axiom
								.getObject().accept(positiveConverter_)));
		return null;
	}

	@Override
	public ModifiableIndexedPropertyChain visit(
			ElkObjectPropertyChain elkObjectPropertyChain) {
		ModifiableIndexedPropertyChain result = null;
		// iterating over the chain backwards
		ListIterator iterator = elkObjectPropertyChain
				.getObjectPropertyExpressions()
				.listIterator(elkObjectPropertyChain
						.getObjectPropertyExpressions().size());
		while (iterator.hasPrevious()) {
			ModifiableIndexedObjectProperty iop = iterator.previous()
					.accept(negativeConverter_);
			if (result == null) {
				result = iop;
				continue;
			}
			result = negativeFactory_.getIndexedComplexPropertyChain(iop,
					result);
		}
		return result;
	}

	@Override
	public Void visit(ElkObjectPropertyDomainAxiom axiom) {
		ModifiableIndexedClass indexedOwlThing = negativeFactory_
				.getIndexedClass(elkFactory_.getOwlThing());
		axiomInferenceFactory_.getElkObjectPropertyDomainAxiomConversion(axiom,
				negativeFactory_.getIndexedObjectSomeValuesFrom(
						axiom.getProperty().accept(negativeConverter_),
						indexedOwlThing),
				axiom.getDomain().accept(positiveConverter_));
		return null;
	}

	@Override
	public Void visit(ElkObjectPropertyRangeAxiom axiom) {
		// not fully supported with property assertions
		occurrenceListener_.occurrenceChanged(
				Feature.OBJECT_PROPERTY_RANGE, increment_);
		axiomInferenceFactory_.getElkObjectPropertyRangeAxiomConversion(axiom,
				axiom.getProperty().accept(negativeConverter_),
				axiom.getRange().accept(positiveConverter_));
		return null;
	}

	@Override
	public Void visit(ElkReflexiveObjectPropertyAxiom axiom) {
		// not fully supported with property chains
		occurrenceListener_.occurrenceChanged(
				Feature.REFLEXIVE_OBJECT_PROPERTY, increment_);
		axiomInferenceFactory_.getElkReflexiveObjectPropertyAxiomConversion(
				axiom,
				negativeFactory_.getIndexedClass(elkFactory_.getOwlThing()),
				positiveFactory_.getIndexedObjectHasSelf(
						axiom.getProperty().accept(positiveConverter_)));
		return null;
	}

	@Override
	public Void visit(ElkSameIndividualAxiom axiom) {
		// reduces equivalence to sub-class axioms
		ModifiableIndexedIndividual first = null;
		List members = axiom.getIndividuals();
		for (int pos = 0; pos < members.size(); pos++) {
			ElkIndividual ind = members.get(pos);
			if (first == null) {
				first = ind.accept(dualConverter_);
			} else {
				ModifiableIndexedIndividual other = ind.accept(dualConverter_);
				axiomInferenceFactory_.getElkSameIndividualAxiomConversion(
						axiom, 0, pos, first, other);
				axiomInferenceFactory_.getElkSameIndividualAxiomConversion(
						axiom, pos, 0, other, first);
			}
		}
		return null;
	}

	@Override
	public Void visit(ElkSubClassOfAxiom axiom) {
		axiomInferenceFactory_.getElkSubClassOfAxiomConversion(axiom,
				axiom.getSubClassExpression().accept(negativeConverter_),
				axiom.getSuperClassExpression().accept(positiveConverter_));
		return null;
	}

	@Override
	public Void visit(ElkSubDataPropertyOfAxiom axiom) {
		throw unsupported(Feature.SUB_DATA_PROPERTY_OF);
	}

	@Override
	public Void visit(ElkSubObjectPropertyOfAxiom axiom) {
		axiomInferenceFactory_.getElkSubObjectPropertyOfAxiomConversion(axiom,
				axiom.getSubObjectPropertyExpression().accept(this),
				axiom.getSuperObjectPropertyExpression()
						.accept(positiveConverter_));
		return null;
	}

	@Override
	public Void visit(ElkSWRLRule axiom) {
		throw unsupported(Feature.SWRL_RULE);
	}

	@Override
	public Void visit(ElkSymmetricObjectPropertyAxiom axiom) {
		throw unsupported(Feature.SYMMETRIC_OBJECT_PROPERTY);
	}

	@Override
	public Void visit(ElkTransitiveObjectPropertyAxiom axiom) {
		ModifiableIndexedObjectProperty p = axiom.getProperty()
				.accept(dualConverter_);
		axiomInferenceFactory_.getElkTransitiveObjectPropertyAxiomConversion(
				axiom, negativeFactory_.getIndexedComplexPropertyChain(p, p),
				p);
		return null;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy