/*
 * #%L
 * ELK Reasoner
 *
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2011 - 2012 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.saturation.conclusions.classes;

import org.semanticweb.elk.reasoner.saturation.conclusions.model.BackwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ClassConclusion;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.SubClassInclusionComposed;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ContextInitialization;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ClassInconsistency;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.SubClassInclusionDecomposed;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.DisjointSubsumer;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ForwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.Propagation;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.SubContextInitialization;

/**
 * An object which can be used to measure the time spent on processing
 * {@link ClassConclusion}s using {@link ClassConclusion.Visitor}.
 *
 * @author "Yevgeny Kazakov"
 *
 */
public class ClassConclusionTimer {

	/**
	 * timer for {@link BackwardLink}s
	 */
	long timeBackwardLinks;

	/**
	 * timer for {@link ContextInitialization}s
	 */
	long timeContextInitializations;

	/**
	 * timer for {@link ClassInconsistency}s
	 */
	long timeContradictions;

	/**
	 * timer for {@link DisjointSubsumer}s
	 */
	long timeDisjointSubsumers;

	/**
	 * timer for {@link ForwardLink}s
	 */
	long timeForwardLinks;

	/**
	 * timer for {@link SubClassInclusionDecomposed}s
	 */
	long timeDecomposedSubsumers;

	/**
	 * timer for {@link SubClassInclusionComposed}s
	 */
	long timeComposedSubsumers;

	/**
	 * timer for {@link Propagation}s
	 */
	long timePropagations;

	/**
	 * timer for {@link SubContextInitialization}s
	 */
	long timeSubContextInitializations;

	public long getTimeBackwardLinks() {
		return timeBackwardLinks;
	}

	public long getTimeContradictions() {
		return timeContradictions;
	}

	public long getTimeContextInitializations() {
		return timeContextInitializations;
	}

	public long getTimeDisjointnessAxioms() {
		return timeDisjointSubsumers;
	}

	public long getTimeForwardLinks() {
		return timeForwardLinks;
	}

	public long getTimeComposedSubsumers() {
		return timeComposedSubsumers;
	}

	public long getTimeDecomposedSubsumers() {
		return timeDecomposedSubsumers;
	}

	public long getTimePropagations() {
		return timePropagations;
	}

	public long getSubContextInitializations() {
		return timeSubContextInitializations;
	}

	public long getTotalTime() {
		return timeComposedSubsumers + timeDecomposedSubsumers
				+ timeBackwardLinks + timeForwardLinks + timePropagations
				+ timeContradictions + timeDisjointSubsumers
				+ timeContextInitializations + timeSubContextInitializations;
	}

	/**
	 * Adds all timers of the argument to the corresponding counters of this
	 * object. The timers should not be directly modified other than using this
	 * method during this operation. The timers in the argument will be reseted
	 * after this operation.
	 *
	 * @param timer
	 *            the object which counters should be added
	 */
	public synchronized void add(ClassConclusionTimer timer) {
		this.timeComposedSubsumers += timer.timeComposedSubsumers;
		this.timeDecomposedSubsumers += timer.timeDecomposedSubsumers;
		this.timeBackwardLinks += timer.timeBackwardLinks;
		this.timeForwardLinks += timer.timeForwardLinks;
		this.timeContradictions += timer.timeContradictions;
		this.timePropagations += timer.timePropagations;
		this.timeDisjointSubsumers += timer.timeDisjointSubsumers;
		this.timeContextInitializations += timer.timeContextInitializations;
		this.timeSubContextInitializations += timer.timeSubContextInitializations;
	}

	/**
	 * Reset all times to zero.
	 */
	public void reset() {
		timeComposedSubsumers = 0;
		timeDecomposedSubsumers = 0;
		timeBackwardLinks = 0;
		timeForwardLinks = 0;
		timeContradictions = 0;
		timePropagations = 0;
		timeDisjointSubsumers = 0;
		timeContextInitializations = 0;
		timeSubContextInitializations = 0;
	}

}


package org.semanticweb.elk.owl.managers;

/*
 * #%L
 * ELK OWL Model Implementation
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2016 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%
 */

import java.lang.ref.ReferenceQueue;
import java.util.HashMap;

import org.semanticweb.elk.owl.implementation.ElkObjectBaseFactory;
import org.semanticweb.elk.owl.interfaces.ElkAnnotationProperty;
import org.semanticweb.elk.owl.interfaces.ElkClass;
import org.semanticweb.elk.owl.interfaces.ElkDataProperty;
import org.semanticweb.elk.owl.interfaces.ElkDatatype;
import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.owl.interfaces.ElkNamedIndividual;
import org.semanticweb.elk.owl.interfaces.ElkObject;
import org.semanticweb.elk.owl.interfaces.ElkObjectDelegatingFactory;
import org.semanticweb.elk.owl.interfaces.ElkObjectProperty;
import org.semanticweb.elk.owl.iris.ElkIri;
import org.semanticweb.elk.owl.visitors.ElkEntityVisitor;

/**
 * An {@link ElkObject.Factory} that reuses already created {@link ElkEntity}s.
 * That is, any two structurally equivalent {@link ElkEntity}s (i.e., with the
 * same {@link ElkIri}s) entities will be the same object. For other types of
 * {@link ElkObject}s this is not the case: every time a new object is created.
 *
 * @author Frantisek Simancik
 * @author "Yevgeny Kazakov"
 *
 */
public class ElkObjectEntityRecyclingFactory
		extends ElkObjectDelegatingFactory {

	public ElkObjectEntityRecyclingFactory(ElkObject.Factory factory) {
		super(factory);
	}

	public ElkObjectEntityRecyclingFactory() {
		this(new ElkObjectBaseFactory());
	}

	// TODO: simplify the implementation to use just one weak wrapper

	@SuppressWarnings("unchecked")
	@Override
	protected <C extends ElkObject> C filter(C candidate) {
		if (candidate instanceof ElkEntity)
			return (C) getCanonicalElkEntity((ElkEntity) candidate);
		else
			return candidate;
	}

	private HashMap<WeakWrapper<? extends ElkEntity>, WeakWrapper<? extends ElkEntity>> cache = new HashMap<WeakWrapper<? extends ElkEntity>, WeakWrapper<? extends ElkEntity>>();

	private ReferenceQueue<ElkEntity> referenceQueue = new ReferenceQueue<ElkEntity>();

	private ElkEntityVisitor<WeakWrapper<? extends ElkEntity>> wrapper = new ElkEntityVisitor<WeakWrapper<? extends ElkEntity>>() {

		@Override
		public WeakWrapper<? extends ElkEntity> visit(ElkClass elkClass) {
			return new WeakElkClassWrapper(elkClass, referenceQueue);
		}

		@Override
		public WeakWrapper<? extends ElkEntity> visit(ElkDatatype elkDatatype) {
			return new WeakElkDatatypeWrapper(elkDatatype, referenceQueue);
		}

		@Override
		public WeakWrapper<? extends ElkEntity> visit(
				ElkObjectProperty elkObjectProperty) {
			return new WeakElkObjectPropertyWrapper(elkObjectProperty,
					referenceQueue);
		}

		@Override
		public WeakWrapper<? extends ElkEntity> visit(
				ElkDataProperty elkDataProperty) {
			return new WeakElkDataPropertyWrapper(elkDataProperty,
					referenceQueue);
		}

		@Override
		public WeakWrapper<? extends ElkEntity> visit(
				ElkNamedIndividual elkNamedIndividual) {
			return new WeakElkNamedIndividualWrapper(elkNamedIndividual,
					referenceQueue);
		}

		@Override
		public WeakWrapper<? extends ElkEntity> visit(
				ElkAnnotationProperty elkAnnotationProperty) {
			return new WeakElkAnnotationPropertyWrapper(elkAnnotationProperty,
					referenceQueue);
		}

	};

	private ElkEntity getCanonicalElkEntity(ElkEntity entity) {
		processQueue();

		if (entity == null)
			return null;

		WeakWrapper<? extends ElkEntity> key = entity.accept(wrapper);
		WeakWrapper<? extends ElkEntity> value = cache.get(key);

		if (value != null) {
			ElkEntity result = value.get();
			if (result != null)
				return result;
		}

		cache.put(key, key);
		return entity;
	}

	private final void processQueue() {
		WeakWrapper<? extends ElkEntity> w = null;

		while ((w = (WeakWrapper<? extends ElkEntity>) referenceQueue
				.poll()) != null) {
			cache.remove(w);
		}
	}

}


package org.semanticweb.elk.reasoner.saturation.rules;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2012 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%
 */

import org.semanticweb.elk.reasoner.saturation.rules.backwardlinks.BackwardLinkChainFromBackwardLinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.backwardlinks.ContradictionOverBackwardLinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.backwardlinks.SubsumerBackwardLinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.contextinit.OwlThingContextInitRule;
import org.semanticweb.elk.reasoner.saturation.rules.contextinit.RootContextInitializationRule;
import org.semanticweb.elk.reasoner.saturation.rules.contradiction.ContradictionPropagationRule;
import org.semanticweb.elk.reasoner.saturation.rules.disjointsubsumer.ContradictionCompositionRule;
import org.semanticweb.elk.reasoner.saturation.rules.forwardlink.BackwardLinkFromForwardLinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.forwardlink.NonReflexiveBackwardLinkCompositionRule;
import org.semanticweb.elk.reasoner.saturation.rules.forwardlink.ReflexiveBackwardLinkCompositionRule;
import org.semanticweb.elk.reasoner.saturation.rules.propagations.SubsumerPropagationRule;
import org.semanticweb.elk.reasoner.saturation.rules.subcontextinit.PropagationInitializationRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ComposedFromDecomposedSubsumerRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ContradictionFromNegationRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ContradictionFromOwlNothingRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.DisjointSubsumerFromMemberRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.EquivalentClassFirstFromSecondRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.EquivalentClassSecondFromFirstRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedClassDecompositionRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedClassFromDefinitionRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedObjectComplementOfDecomposition;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedObjectHasSelfDecomposition;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedObjectIntersectionOfDecomposition;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.IndexedObjectSomeValuesFromDecomposition;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ObjectIntersectionFromFirstConjunctRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ObjectIntersectionFromSecondConjunctRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.ObjectUnionFromDisjunctRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.PropagationFromExistentialFillerRule;
import org.semanticweb.elk.reasoner.saturation.rules.subsumers.SuperClassFromSubClassRule;

/**
 * An object which can be used to measure time spent within a methods of a
 * {@link RuleVisitor}. The fields of the timer correspond to the methods of
 * {@link RuleVisitor}.
 *
 * @author "Yevgeny Kazakov"
 *
 */
public class RuleApplicationTimer {

	/**
	 * timer for {@link BackwardLinkChainFromBackwardLinkRule}
	 */
	long timeBackwardLinkChainFromBackwardLinkRule;

	/**
	 * timer for {@link BackwardLinkFromForwardLinkRule}
	 */
	long timeBackwardLinkFromForwardLinkRule;

	/**
	 * timer for {@link ComposedFromDecomposedSubsumerRule}
	 */
	long timeComposedFromDecomposedSubsumerRule;

	/**
	 * time for {@link ContradictionCompositionRule}
	 */
	long timeContradictionCompositionRule;

	/**
	 * timer for {@link ContradictionFromNegationRule}
	 */
	long timeContradictionFromNegationRule;

	/**
	 * timer for {@link ContradictionFromOwlNothingRule}
	 */
	long timeContradictionFromOwlNothingRule;

	/**
	 * timer for {@link ContradictionOverBackwardLinkRule}
	 */
	long timeContradictionOverBackwardLinkRule;

	/**
	 * time for {@link ContradictionPropagationRule}
	 */
	long timeContradictionPropagationRule;

	/**
	 * timer for {@link DisjointSubsumerFromMemberRule}
	 */
	long timeDisjointSubsumerFromMemberRule;

	/**
	 * timer for {@link IndexedClassDecompositionRule}
	 */
	long timeIndexedClassDecompositionRule;

	/**
	 * timer for {@link IndexedClassFromDefinitionRule}
	 */
	long timeIndexedClassFromDefinitionRule;

	/**
	 * timer for {@link IndexedObjectComplementOfDecomposition}
	 */
	long timeIndexedObjectComplementOfDecomposition;

	/**
	 * timer for {@link IndexedObjectHasSelfDecomposition}
	 */
	long timeIndexedObjectHasSelfDecomposition;

	/**
	 * time for {@link IndexedObjectIntersectionOfDecomposition}
	 */
	long timeIndexedObjectIntersectionOfDecomposition;

	/**
	 * time for {@link IndexedObjectSomeValuesFromDecomposition}
	 */
	long timeIndexedObjectSomeValuesFromDecomposition;

	/**
	 * time for {@link NonReflexiveBackwardLinkCompositionRule}
	 */
	long timeNonReflexiveBackwardLinkCompositionRule;

	/**
	 * timer for {@link ObjectIntersectionFromFirstConjunctRule}
	 */
	long timeObjectIntersectionFromFirstConjunctRule;

	/**
	 * timer for {@link ObjectIntersectionFromSecondConjunctRule}
	 */
	long timeObjectIntersectionFromSecondConjunctRule;

	/**
	 * timer for {@link ObjectUnionFromDisjunctRule}
	 */
	long timeObjectUnionFromDisjunctRule;

	/**
	 * timer for {@link OwlThingContextInitRule}
	 */
	long timeOwlThingContextInitRule;

	/**
	 * timer for {@link PropagationFromExistentialFillerRule}
	 */
	long timePropagationFromExistentialFillerRule;

	/**
	 * timer for {@link PropagationInitializationRule}
	 */
	long timePropagationInitializationRule;

	/**
	 * timer for {@link ReflexiveBackwardLinkCompositionRule}
	 */
	long timeReflexiveBackwardLinkCompositionRule;

	/**
	 * timer for {@link RootContextInitializationRule}
	 */
	long timeRootContextInitializationRule;

	/**
	 * timer for {@link SubsumerBackwardLinkRule}
	 */
	long timeSubsumerBackwardLinkRule;

	/**
	 * timer for {@link SubsumerPropagationRule}
	 */
	long timeSubsumerPropagationRule;

	/**
	 * timer for {@link SuperClassFromSubClassRule}
	 */
	long timeSuperClassFromSubClassRule;

	/**
	 * timer for {@link EquivalentClassFirstFromSecondRule}
	 */
	long timeEquivalentClassFirstFromSecondRule;

	/**
	 * timer for {@link EquivalentClassSecondFromFirstRule}
	 */
	long timeEquivalentClassSecondFromFirstRule;

	/**
	 * Add the values the corresponding values of the given timer
	 *
	 * @param timer
	 */
	public synchronized void add(RuleApplicationTimer timer) {
		timeOwlThingContextInitRule += timer.timeOwlThingContextInitRule;
		timeRootContextInitializationRule += timer.timeRootContextInitializationRule;
		timeDisjointSubsumerFromMemberRule += timer.timeDisjointSubsumerFromMemberRule;
		timeContradictionFromNegationRule += timer.timeContradictionFromNegationRule;
		timeObjectIntersectionFromFirstConjunctRule += timer.timeObjectIntersectionFromFirstConjunctRule;
		timeObjectIntersectionFromSecondConjunctRule += timer.timeObjectIntersectionFromSecondConjunctRule;
		timeSuperClassFromSubClassRule += timer.timeSuperClassFromSubClassRule;
		timePropagationFromExistentialFillerRule += timer.timePropagationFromExistentialFillerRule;
		timeObjectUnionFromDisjunctRule += timer.timeObjectUnionFromDisjunctRule;
		timeBackwardLinkChainFromBackwardLinkRule += timer.timeBackwardLinkChainFromBackwardLinkRule;
		timeReflexiveBackwardLinkCompositionRule += timer.timeReflexiveBackwardLinkCompositionRule;
		timeNonReflexiveBackwardLinkCompositionRule += timer.timeNonReflexiveBackwardLinkCompositionRule;
		timeSubsumerBackwardLinkRule += timer.timeSubsumerBackwardLinkRule;
		timeContradictionOverBackwardLinkRule += timer.timeContradictionOverBackwardLinkRule;
		timeContradictionPropagationRule += timer.timeContradictionPropagationRule;
		timeContradictionCompositionRule += timer.timeContradictionCompositionRule;
		timeIndexedObjectIntersectionOfDecomposition += timer.timeIndexedObjectIntersectionOfDecomposition;
		timeIndexedObjectSomeValuesFromDecomposition += timer.timeIndexedObjectSomeValuesFromDecomposition;
		timeIndexedObjectComplementOfDecomposition += timer.timeIndexedObjectComplementOfDecomposition;
		timeIndexedObjectHasSelfDecomposition += timer.timeIndexedObjectHasSelfDecomposition;
		timeContradictionFromOwlNothingRule += timer.timeContradictionFromOwlNothingRule;
		timeSubsumerPropagationRule += timer.timeSubsumerPropagationRule;
		timePropagationInitializationRule += timer.timePropagationInitializationRule;
		timeBackwardLinkFromForwardLinkRule += timer.timeBackwardLinkFromForwardLinkRule;
		timeComposedFromDecomposedSubsumerRule += timer.timeComposedFromDecomposedSubsumerRule;
		timeIndexedClassDecompositionRule += timer.timeIndexedClassDecompositionRule;
		timeIndexedClassFromDefinitionRule += timer.timeIndexedClassFromDefinitionRule;
		timeEquivalentClassFirstFromSecondRule += timer.timeEquivalentClassFirstFromSecondRule;
		timeEquivalentClassSecondFromFirstRule += timer.timeEquivalentClassSecondFromFirstRule;
	}

	public long getTotalRuleAppTime() {
		return timeOwlThingContextInitRule + timeRootContextInitializationRule
				+ timeDisjointSubsumerFromMemberRule
				+ timeContradictionFromNegationRule
				+ timeObjectIntersectionFromFirstConjunctRule
				+ timeObjectIntersectionFromSecondConjunctRule
				+ timeSuperClassFromSubClassRule
				+ timePropagationFromExistentialFillerRule
				+ timeObjectUnionFromDisjunctRule
				+ timeBackwardLinkChainFromBackwardLinkRule
				+ timeSubsumerBackwardLinkRule
				+ timeContradictionOverBackwardLinkRule
				+ timeContradictionPropagationRule
				+ timeContradictionCompositionRule
				+ timeNonReflexiveBackwardLinkCompositionRule
				+ timeReflexiveBackwardLinkCompositionRule
				+ timeIndexedObjectIntersectionOfDecomposition
				+ timeIndexedObjectSomeValuesFromDecomposition
				+ timeIndexedObjectComplementOfDecomposition
				+ timeIndexedObjectHasSelfDecomposition
				+ timeContradictionFromOwlNothingRule
				+ timeSubsumerPropagationRule
				+ timePropagationInitializationRule
				+ timeBackwardLinkFromForwardLinkRule
				+ timeComposedFromDecomposedSubsumerRule
				+ timeIndexedClassDecompositionRule
				+ timeIndexedClassFromDefinitionRule
				+ timeEquivalentClassFirstFromSecondRule
				+ timeEquivalentClassSecondFromFirstRule;
	}

	/**
	 * Reset all timers to zero.
	 */
	public void reset() {
		timeOwlThingContextInitRule = 0;
		timeRootContextInitializationRule = 0;
		timeDisjointSubsumerFromMemberRule = 0;
		timeContradictionFromNegationRule = 0;
		timeObjectIntersectionFromFirstConjunctRule = 0;
		timeObjectIntersectionFromSecondConjunctRule = 0;
		timeSuperClassFromSubClassRule = 0;
		timePropagationFromExistentialFillerRule = 0;
		timeObjectUnionFromDisjunctRule = 0;
		timeBackwardLinkChainFromBackwardLinkRule = 0;
		timeSubsumerBackwardLinkRule = 0;
		timeContradictionOverBackwardLinkRule = 0;
		timeContradictionPropagationRule = 0;
		timeContradictionCompositionRule = 0;
		timeNonReflexiveBackwardLinkCompositionRule = 0;
		timeReflexiveBackwardLinkCompositionRule = 0;
		timeIndexedObjectIntersectionOfDecomposition = 0;
		timeIndexedObjectSomeValuesFromDecomposition = 0;
		timeIndexedObjectComplementOfDecomposition = 0;
		timeIndexedObjectHasSelfDecomposition = 0;
		timeContradictionFromOwlNothingRule = 0;
		timeSubsumerPropagationRule = 0;
		timePropagationInitializationRule = 0;
		timeBackwardLinkFromForwardLinkRule = 0;
		timeComposedFromDecomposedSubsumerRule = 0;
		timeIndexedClassDecompositionRule = 0;
		timeIndexedClassFromDefinitionRule = 0;
		timeEquivalentClassFirstFromSecondRule = 0;
		timeEquivalentClassSecondFromFirstRule = 0;
	}

}


package org.semanticweb.elk.reasoner.saturation.conclusions.classes;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2016 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%
 */

import org.semanticweb.elk.Reference;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ClassConclusion;
import org.semanticweb.elk.reasoner.saturation.context.ClassConclusionSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A {@link ClassConclusion.Visitor} that checks if visited
 * {@link ClassConclusion} is contained the {@link ClassConclusionSet} value of
 * the given {@link Reference}. The visit method returns {@code true} if the
 * {@link ClassConclusion} occurs in the {@link ClassConclusionSet} and
 * {@code false} otherwise.
 *
 * @see ClassConclusionInsertionVisitor
 * @see ClassConclusionDeletionVisitor
 * @see ClassConclusionOccurrenceCheckingVisitor
 *
 * @author "Yevgeny Kazakov"
 */
public class ClassConclusionOccurrenceCheckingVisitor extends
		DummyClassConclusionVisitor<Boolean> {

	// logger for events
	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(ClassConclusionOccurrenceCheckingVisitor.class);

	private final Reference<? extends ClassConclusionSet> conclusionsRef_;

	public ClassConclusionOccurrenceCheckingVisitor(Reference<? extends ClassConclusionSet> conclusions) {
		this.conclusionsRef_ = conclusions;
	}

	// TODO: make this by combining the visitor in order to avoid overheads when
	// logging is switched off
	@Override
	protected Boolean defaultVisit(ClassConclusion conclusion) {
		ClassConclusionSet conclusions = conclusionsRef_.get();
		boolean result = conclusions == null
				? false
				: conclusions.containsConclusion(conclusion);
		if (LOGGER_.isTraceEnabled()) {
			LOGGER_.trace("{}: check occurrence of {}: {}", conclusions,
					conclusion, result ? "success" : "failure");
		}
		return result;
	}

}


/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2016 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.stages;

import org.semanticweb.elk.exceptions.ElkException;
import org.semanticweb.elk.owl.interfaces.ElkObjectProperty;
import org.semanticweb.elk.owl.predefined.PredefinedElkObjectPropertyFactory;
import org.semanticweb.elk.reasoner.saturation.properties.ObjectPropertyTaxonomyComputation;
import org.semanticweb.elk.reasoner.saturation.properties.TransitiveReductionOutputEquivalent;
import org.semanticweb.elk.reasoner.saturation.properties.TransitiveReductionOutputEquivalentDirect;
import org.semanticweb.elk.reasoner.saturation.properties.TransitiveReductionOutputExtreme;
import org.semanticweb.elk.reasoner.saturation.properties.TransitiveReductionOutputVisitor;
import org.semanticweb.elk.reasoner.taxonomy.ElkObjectPropertyKeyProvider;
import org.semanticweb.elk.reasoner.taxonomy.ReverseObjectPropertyTaxonomy;
import org.semanticweb.elk.reasoner.taxonomy.ReverseTaxonomy;
import org.semanticweb.elk.reasoner.taxonomy.model.NonBottomTaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.Taxonomy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Keeps track of state of the object property taxonomy.
 *
 * @author Peter Skocovsky
 */
public class ObjectPropertyTaxonomyState {

	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(ObjectPropertyTaxonomyState.class);

	private final PredefinedElkObjectPropertyFactory elkFactory_;

	/**
	 * Object property taxonomy is constructed in the opposite order than class
	 * taxonomy, i.e., from super-properties to sub-properties. In order to use
	 * the same taxonomy implementation as for the class taxonomy, property
	 * taxonomy is up side down. It must be reversed before passing it out of
	 * the reasoner!
	 */
	private ReverseObjectPropertyTaxonomy taxonomy_ = null;

	public ObjectPropertyTaxonomyState(
			final PredefinedElkObjectPropertyFactory elkFactory) {
		this.elkFactory_ = elkFactory;
		resetTaxonomy();
	}

	public Taxonomy<ElkObjectProperty> getTaxonomy() {
		return new ReverseTaxonomy<ElkObjectProperty>(taxonomy_);
	}

	private void resetTaxonomy() {
		LOGGER_.trace("Reset object property taxonomy");
		taxonomy_ = new ReverseObjectPropertyTaxonomy(elkFactory_,
				ElkObjectPropertyKeyProvider.INSTANCE);
	}

	/**
	 * Receives the output of the transitive reduction of sub object properties
	 * and constructs the taxonomy from it.
	 */
	private final TransitiveReductionOutputVisitor<ElkObjectProperty> transitiveReductionOutputProcessor_ = new TransitiveReductionOutputVisitor<ElkObjectProperty>() {

		@Override
		public void visit(
				final TransitiveReductionOutputEquivalentDirect<ElkObjectProperty> output) {
			// Properties equivalent to top should not be submitted here.

			final NonBottomTaxonomyNode<ElkObjectProperty> node = taxonomy_
					.getCreateNode(output.getEquivalent());
			taxonomy_.setCreateDirectSupernodes(node,
					output.getDirectlyRelated());

		}

		@Override
		public void visit(
				final TransitiveReductionOutputExtreme<ElkObjectProperty> output) {
			taxonomy_.addToBottomNode(output.getExtremeMember());
		}

		@Override
		public void visit(
				final TransitiveReductionOutputEquivalent<ElkObjectProperty> output) {
			throw new IllegalArgumentException(
					"Object property transitive reduction is not expected to emit "
							+ output.getClass());
		}

	};

	/**
	 * Creates stage that computes object property taxonomy.
	 *
	 * @param reasoner
	 *            the reasoner for which the reasoner stage is created
	 * @param preStages
	 *            the reasoner stages that should be executed directly before
	 *            this stage
	 * @return the stage that computes object property taxonomy.
	 */
	AbstractReasonerStage createStage(final AbstractReasonerState reasoner,
			final AbstractReasonerStage... preStages) {
		return new AbstractReasonerStage(reasoner, preStages) {

			/**
			 * The computation used for this stage.
			 */
			private ObjectPropertyTaxonomyComputation computation_ = null;

			@Override
			public String getName() {
				return "Object Property Taxonomy Computation";
			}

			@Override
			public boolean preExecute() {
				if (!super.preExecute()) {
					return false;
				}

				resetTaxonomy();

				computation_ = new ObjectPropertyTaxonomyComputation(
						reasoner.ontologyIndex, reasoner.getInterrupter(),
						transitiveReductionOutputProcessor_,
						reasoner.getElkFactory(), reasoner.getProcessExecutor(),
						workerNo, reasoner.getProgressMonitor());

				return true;
			}

			@Override
			void executeStage() throws ElkException {
				computation_.process();
			}

			@Override
			public boolean postExecute() {
				if (!super.postExecute()) {
					return false;
				}
				this.computation_ = null;
				return true;
			}

			@Override
			public void printInfo() {
				// TODO Auto-generated method stub

			}

		};
	}

}


/**
 *
 */
package org.semanticweb.elk.reasoner.saturation.inferences;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2015 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%
 */

import org.semanticweb.elk.reasoner.indexing.model.IndexedContextRoot;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObjectHasSelf;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ForwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.SubClassInclusionDecomposed;
import org.semanticweb.elk.reasoner.tracing.Conclusion;
import org.semanticweb.elk.reasoner.tracing.Conclusion.Factory;

/**
 * A {@link ClassInference} producing a {@link ForwardLink} from a
 * {@link SubClassInclusionDecomposed} with
 * {@link SubClassInclusionDecomposed#getSubsumer()} of the type
 * {@link IndexedObjectHasSelf}:

 *
 *

 *  [C] ⊑ -∃R.Self
 * ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
 *  [C] ⊑ <∃R>.C
 *

 *
 * The parameters can be obtained as follows:

 *
 * C = {@link #getOrigin()} = {@link #getDestination()}

 * ∃R.Self = {@link #getDecomposedExistential()} (from which R can be obtained)
 *

 *
 * @author "Yevgeny Kazakov"
 *
 */
public class ForwardLinkOfObjectHasSelf extends AbstractClassInference
		implements ForwardLinkInference {

	private final IndexedObjectHasSelf existential_;

	public ForwardLinkOfObjectHasSelf(IndexedContextRoot inferenceRoot,
			IndexedObjectHasSelf subsumer) {
		super(inferenceRoot);
		existential_ = subsumer;
	}

	public IndexedObjectHasSelf getDecomposedExistential() {
		return this.existential_;
	}

	public SubClassInclusionDecomposed getPremise(
			SubClassInclusionDecomposed.Factory factory) {
		return factory.getSubClassInclusionDecomposed(getOrigin(),
				existential_);
	}

	/**
	 * @param factory
	 *            the factory for creating conclusions
	 *
	 * @return the conclusion produced by this inference
	 */
	public ForwardLink getConclusion(ForwardLink.Factory factory) {
		return factory.getForwardLink(getDestination(),
				existential_.getProperty(), getOrigin());
	}

	@Override
	public IndexedContextRoot getOrigin() {
		return getDestination();
	}

	@Override
	public int getPremiseCount() {
		return 1;
	}

	@Override
	public Conclusion getPremise(int index, Factory factory) {
		switch (index) {
		case 0:
			return getPremise(factory);
		default:
			return failGetPremise(index);
		}
	}

	@Override
	public final <O> O accept(ClassInference.Visitor<O> visitor) {
		return visitor.visit(this);
	}

	@Override
	public final <O> O accept(ForwardLinkInference.Visitor<O> visitor) {
		return visitor.visit(this);
	}

	/**
	 * Visitor pattern for instances
	 *
	 * @author Yevgeny Kazakov
	 *
	 * @param <O>
	 *            the type of the output
	 */
	public static interface Visitor<O> {

		public O visit(ForwardLinkOfObjectHasSelf inference);

	}

}


package org.semanticweb.elk.reasoner.saturation.rules.contextinit;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2015 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%
 */

import org.semanticweb.elk.reasoner.indexing.model.IndexedClass;
import org.semanticweb.elk.reasoner.indexing.model.ModifiableOntologyIndex;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.ContextInitialization;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.SubClassInclusion;
import org.semanticweb.elk.reasoner.saturation.context.ContextPremises;
import org.semanticweb.elk.reasoner.saturation.inferences.SubClassInclusionOwlThing;
import org.semanticweb.elk.reasoner.saturation.rules.ClassInferenceProducer;
import org.semanticweb.elk.util.collections.chains.Chain;
import org.semanticweb.elk.util.collections.chains.Matcher;
import org.semanticweb.elk.util.collections.chains.ReferenceFactory;
import org.semanticweb.elk.util.collections.chains.SimpleTypeBasedMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A {@link ChainableContextInitRule} that produces {@link SubClassInclusion}
 * {@code owl:Thing} in a context. It should be applied only if
 * {@code owl:Thing} occurs negatively in the ontology.
 */
public class OwlThingContextInitRule extends AbstractChainableContextInitRule {

	// logger for events
	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(OwlThingContextInitRule.class);

	public static final String NAME = "owl:Thing Introduction";

	private IndexedClass owlThing_;

	private OwlThingContextInitRule(ChainableContextInitRule tail) {
		super(tail);
	}

	private OwlThingContextInitRule(IndexedClass owlThing) {
		super(null);
		this.owlThing_ = owlThing;
	}

	/**
	 * Add an {@link OwlThingContextInitRule} to the given
	 * {@link ModifiableOntologyIndex}
	 *
	 * @param owlThing
	 * @param index
	 * @return {@code true} if the operation was successful and {@code false}
	 *         otherwise; if {@code false} is returned, the index remains
	 *         unchanged
	 */
	public static boolean addRuleFor(IndexedClass owlThing,
			ModifiableOntologyIndex index) {
		LOGGER_.trace("{}: adding {}", owlThing, NAME);
		return index.addContextInitRule(new OwlThingContextInitRule(owlThing));
	}

	/**
	 * Removes an {@link OwlThingContextInitRule} from the given
	 * {@link ModifiableOntologyIndex}
	 *
	 * @param owlThing
	 * @param index
	 * @return {@code true} if the operation was successful and {@code false}
	 *         otherwise; if {@code false} is returned, the index remains
	 *         unchanged
	 */
	public static boolean removeRuleFor(IndexedClass owlThing,
			ModifiableOntologyIndex index) {
		LOGGER_.trace("{}: removing {}", owlThing, NAME);
		return index
				.removeContextInitRule(new OwlThingContextInitRule(owlThing));
	}

	@Override
	public String toString() {
		return NAME;
	}

	@Override
	public void apply(ContextInitialization premise, ContextPremises premises,
			ClassInferenceProducer producer) {
		producer.produce(
				new SubClassInclusionOwlThing(premises.getRoot(), owlThing_));
	}

	@Override
	public boolean isTracingRule() {
		return true;
	}

	@Override
	public boolean addTo(Chain<ChainableContextInitRule> ruleChain) {
		OwlThingContextInitRule rule = ruleChain.getCreate(MATCHER_, FACTORY_);
		if (rule.owlThing_ == null) {
			// new rule created
			rule.owlThing_ = owlThing_;
		}
		// owl:Thing was already registered
		return true;
	}

	@Override
	public boolean removeFrom(Chain<ChainableContextInitRule> ruleChain) {
		return ruleChain.remove(MATCHER_) != null;
	}

	@Override
	public void accept(LinkedContextInitRuleVisitor<?> visitor,
			ContextInitialization premise, ContextPremises premises,
			ClassInferenceProducer producer) {
		visitor.visit(this, premise, premises, producer);
	}

	private static final Matcher<ChainableContextInitRule, OwlThingContextInitRule> MATCHER_ = new SimpleTypeBasedMatcher<ChainableContextInitRule, OwlThingContextInitRule>(
			OwlThingContextInitRule.class);

	private static final ReferenceFactory<ChainableContextInitRule, OwlThingContextInitRule> FACTORY_ = new ReferenceFactory<ChainableContextInitRule, OwlThingContextInitRule>() {
		@Override
		public OwlThingContextInitRule create(ChainableContextInitRule tail) {
			return new OwlThingContextInitRule(tail);
		}
	};

}


/*
 * #%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 23, 2011
 */
package org.semanticweb.elk.util.collections;

import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * hash maps using array and linear probing for resolving hash collision see [1]
 * p.526. Reuses some code from the implementation of HashMap.
 *
 * [1] Donald E. Knuth, The Art of Computer Programming, Volume 3, Sorting and
 * Searching, Second Edition
 *
 * @author Yevgeny Kazakov
 * @param <K>
 *            the type of the keys
 * @param <V>
 *            the type of the values
 *
 */
public class ArrayHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {

	/**
	 * The table for the keys; the length MUST always be a power of two.
	 */
	protected volatile transient K[] keys;

	/**
	 * The table for the values; the length MUST be equal to the length of keys
	 * and MUST always be a power of two.
	 */
	protected volatile transient V[] values;

	/**
	 * The number of key-value entries contained in this map.
	 */
	protected transient int size;

	@SuppressWarnings("unchecked")
	public ArrayHashMap(int initialCapacity) {
		int capacity = LinearProbing.getInitialCapacity(initialCapacity);
		this.keys = (K[]) new Object[capacity];
		this.values = (V[]) new Object[capacity];
		this.size = 0;
	}

	@SuppressWarnings("unchecked")
	public ArrayHashMap() {
		int capacity = LinearProbing.DEFAULT_INITIAL_CAPACITY;
		this.keys = (K[]) new Object[capacity];
		this.values = (V[]) new Object[capacity];
		this.size = 0;
	}

	@Override
	public int size() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return size == 0;
	}

	@Override
	public boolean containsKey(Object key) {
		if (key == null)
			throw new NullPointerException();
		return LinearProbing.contains(keys, key);
	}

	@Override
	public boolean containsValue(Object value) {
		if (value == null)
			throw new NullPointerException();
		V[] v = this.values;
		// we could not do much better than linear search
		for (int i = 0; i < keys.length; i++)
			if (value.equals(v[i]))
				return true;
		return false;
	}

	@Override
	public V get(Object key) {
		if (key == null)
			throw new NullPointerException();
		// to avoid problems in the middle of resizing, we copy keys and values
		// when they have the same size
		K[] k;
		V[] v;
		for (;;) {
			k = this.keys;
			v = this.values;
			if (k.length == v.length)
				break;
		}
		int pos = LinearProbing.getPosition(k, key);
		if (k[pos] == null)
			return null;
		// else
		return v[pos];
	}

	/**
	 * Associates the given key with the given value in the map defined by the
	 * keys and value arrays. If an entry with the key equal to the given one
	 * already exists in the map, the value for this key will be overwritten
	 * with the given value.
	 *
	 * @param keys
	 *            the keys of the map
	 * @param values
	 *            the values of the map
	 * @param key
	 *            the key of the entry
	 * @param value
	 *            the value of the entry
	 * @return the previous value associated with the key or <tt>null</tt> if
	 *         there was no such a previous value.
	 */
	private static <K, V> V putKeyValue(K[] keys, V[] values, K key, V value) {
		int pos = LinearProbing.getPosition(keys, key);
		if (keys[pos] == null) {
			keys[pos] = key;
			values[pos] = value;
			return null;
		}
		// else
		V oldValue = values[pos];
		values[pos] = value;
		return oldValue;
	}

	/**
	 * Remove the entry in the keys and values such that the key of the entry is
	 * equal to the given object according to the equality function.
	 *
	 * @param keys
	 *            the array of keys
	 * @param values
	 *            the arrays of values
	 * @param key
	 *            the key for which to delete the entry
	 * @return the value of the deleted entry, <tt>null</tt> if nothing has been
	 *         deleted
	 */
	private static <K, V> V removeEntry(K[] keys, V[] values, Object key) {
		int pos = LinearProbing.getPosition(keys, key);
		if (keys[pos] == null)
			return null;
		// else
		V result = values[pos];
		LinearProbing.remove(keys, values, pos);
		return result;
	}

	/**
	 * Increasing the capacity of the map
	 */
	private void enlarge() {
		int oldCapacity = keys.length;
		if (oldCapacity == LinearProbing.MAXIMUM_CAPACITY)
			throw new IllegalArgumentException(
					"Map cannot grow beyond capacity: "
							+ LinearProbing.MAXIMUM_CAPACITY);
		K oldKeys[] = keys;
		V oldValues[] = values;
		int newCapacity = oldCapacity << 1;
		@SuppressWarnings("unchecked")
		K newKeys[] = (K[]) new Object[newCapacity];
		@SuppressWarnings("unchecked")
		V newValues[] = (V[]) new Object[newCapacity];
		for (int i = 0; i < oldCapacity; i++) {
			K key = oldKeys[i];
			if (key != null)
				putKeyValue(newKeys, newValues, key, oldValues[i]);
		}
		this.keys = newKeys;
		this.values = newValues;
	}

	/**
	 * Decreasing the capacity of the map
	 */
	private void shrink() {
		int oldCapacity = keys.length;
		if (oldCapacity <= LinearProbing.DEFAULT_INITIAL_CAPACITY)
			return;
		K oldKeys[] = keys;
		V oldValues[] = values;
		int newCapacity = oldCapacity >> 1;
		@SuppressWarnings("unchecked")
		K newKeys[] = (K[]) new Object[newCapacity];
		@SuppressWarnings("unchecked")
		V newValues[] = (V[]) new Object[newCapacity];
		for (int i = 0; i < oldCapacity; i++) {
			K key = oldKeys[i];
			if (key != null)
				putKeyValue(newKeys, newValues, key, oldValues[i]);
		}
		this.keys = newKeys;
		this.values = newValues;
	}

	@Override
	public V put(K key, V value) {
		if (key == null)
			throw new NullPointerException();
		V result = putKeyValue(keys, values, key, value);
		if (result == null && ++size == LinearProbing.getUpperSize(keys.length))
			enlarge();
		return result;
	}

	@Override
	public V remove(Object key) {
		if (key == null)
			throw new NullPointerException();
		V result = removeEntry(keys, values, key);
		if (result != null && --size == LinearProbing.getLowerSize(keys.length))
			shrink();
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void clear() {
		int capacity = keys.length >> 2;
		if (capacity == 0)
			capacity = 1;
		size = 0;
		this.keys = (K[]) new Object[capacity];
		this.values = (V[]) new Object[capacity];
	}

	@Override
	public Set<K> keySet() {
		return new KeySet();
	}

	@Override
	public Collection<V> values() {
		return new ValueCollection();
	}

	@Override
	public Set<java.util.Map.Entry<K, V>> entrySet() {
		return new EntrySet();
	}

	private class KeyIterator extends LinearProbingIterator<K, K> {

		KeyIterator() {
			super(keys, size);
			init();
		}

		@Override
		void checkSize(int expectedSize) {
			if (expectedSize != size)
				throw new ConcurrentModificationException();
		}

		@Override
		void remove(int pos) {
			LinearProbing.remove(dataSnapshot, values, pos);
			size--;
		}

		@Override
		K getValue(K element, int pos) {
			return element;
		}

	}

	private final class KeySet extends AbstractSet<K> implements
			DirectAccess<K> {

		@Override
		public Iterator<K> iterator() {
			return new KeyIterator();
		}

		@Override
		public boolean contains(Object o) {
			return ArrayHashMap.this.containsKey(o);
		}

		@Override
		public boolean remove(Object o) {
			return ArrayHashMap.this.remove(o) != null;
		}

		@Override
		public int size() {
			return size;
		}

		@Override
		public void clear() {
			ArrayHashMap.this.clear();
		}

		@Override
		public K[] getRawData() {
			return keys;
		}

	}

	private class ValueIterator extends LinearProbingIterator<V, V> {

		ValueIterator() {
			super(values, size);
			init();
		}

		@Override
		void checkSize(int expectedSize) {
			if (expectedSize != size)
				throw new ConcurrentModificationException();
		}

		@Override
		void remove(int pos) {
			LinearProbing.remove(keys, dataSnapshot, pos);
			size--;
		}

		@Override
		V getValue(V element, int pos) {
			return element;
		}

	}

	private final class ValueCollection extends AbstractCollection<V> implements
			DirectAccess<V> {

		@Override
		public Iterator<V> iterator() {
			return new ValueIterator();
		}

		@Override
		public int size() {
			return size;
		}

		@Override
		public void clear() {
			ArrayHashMap.this.clear();
		}

		@Override
		public V[] getRawData() {
			return values;
		}

	}

	private class EntryIterator extends
			LinearProbingIterator<K, Map.Entry<K, V>> {

		final V[] valuesSnapshot;

		EntryIterator() {
			super(keys, size);
			this.valuesSnapshot = values;
			init();
		}

		@Override
		void checkSize(int expectedSize) {
			if (expectedSize != size)
				throw new ConcurrentModificationException();
		}

		@Override
		void remove(int pos) {
			LinearProbing.remove(dataSnapshot, values, pos);
			size--;
		}

		@Override
		Map.Entry<K, V> getValue(K element, int pos) {
			return new Entry(this, pos);
		}
	}

	class Entry implements Map.Entry<K, V> {
		// copy of the iterator
		final EntryIterator iterator;
		// position of the cursor
		final int cursor;

		Entry(EntryIterator iterator, int cursor) {
			this.iterator = iterator;
			this.cursor = cursor;
		}

		@Override
		public K getKey() {
			return iterator.dataSnapshot[cursor];
		}

		@Override
		public V getValue() {
			return iterator.valuesSnapshot[cursor];
		}

		@Override
		public V setValue(V value) {
			V previous = iterator.valuesSnapshot[cursor];
			iterator.valuesSnapshot[cursor] = value;
			return previous;
		}

	}

	private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
		@Override
		public Iterator<Map.Entry<K, V>> iterator() {
			return new EntryIterator();
		}

		@Override
		public boolean contains(Object o) {
			if (!(o instanceof Map.Entry<?, ?>))
				return false;
			Object k = ((Map.Entry<?, ?>) o).getKey();
			return ArrayHashMap.this.containsKey(k);
		}

		@Override
		public boolean remove(Object o) {
			if (!(o instanceof Map.Entry<?, ?>))
				return false;
			Object k = ((Map.Entry<?, ?>) o).getKey();
			return ArrayHashMap.this.remove(k) != null;
		}

		@Override
		public int size() {
			return size;
		}

		@Override
		public void clear() {
			ArrayHashMap.this.clear();
		}
	}

}


/*
 * #%L
 * elk-util-common
 *
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2011 - 2012 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.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.semanticweb.elk.io.IOUtils;

//TODO: Documentation
/**
 * The base class responsible for loading configurations
 *
 * @author Pavel Klinov
 *
 *         pavel.klinov@uni-ulm.de
 */
public class ConfigurationFactory {

	static final String STANDARD_RESOURCE_NAME = "elk";

	final static Logger LOGGER_ = LoggerFactory.getLogger(ConfigurationFactory.class);

	/**
	 *
	 * @param prefix
	 * @param configClass
	 * @return the {@link BaseConfiguration} for the specified parameters
	 * @throws ConfigurationException
	 */
	@SuppressWarnings("static-method")
	public BaseConfiguration getConfiguration(String prefix,
			Class<? extends BaseConfiguration> configClass)
			throws ConfigurationException {
		// try to find elk.properties. if doesn't exist, use the default
		// parameter values for the given class
		ResourceBundle bundle = null;
		BaseConfiguration config = instantiate(configClass);

		try {
			bundle = ResourceBundle.getBundle(STANDARD_RESOURCE_NAME,
					Locale.getDefault(), configClass.getClassLoader());
		} catch (MissingResourceException e) {
		}

		if (bundle == null) {
			LOGGER_.debug("Loading default configuration parameters for "
					+ configClass);
		} else {
			// copy parameters from the bundle
			copyParameters(prefix, config, bundle);
		}

		copyParameters(prefix, config, System.getProperties());

		return config;
	}

	@SuppressWarnings("static-method")
	public BaseConfiguration getConfiguration(InputStream source,
			String prefix, Class<? extends BaseConfiguration> configClass)
			throws ConfigurationException, IOException {

		ResourceBundle bundle = new PropertyResourceBundle(source);
		BaseConfiguration config = instantiate(configClass);

		copyParameters(prefix, config, bundle);

		copyParameters(prefix, config, System.getProperties());

		return config;
	}

	/**
	 * Not a thread-safe method. Shouldn't be invoked concurrently.
	 *
	 * @param configOnDisk
	 * @param config
	 * @throws ConfigurationException
	 * @throws IOException
	 */
	public void saveConfiguration(File configOnDisk, BaseConfiguration config)
			throws ConfigurationException, IOException {
		/*
		 * Unfortunately, we can't directly write the config on disk because the
		 * parameters in it may be just a subset of those on disk. So we load it
		 * first (alternatively one may use a singleton, which I typically try
		 * to avoid). It should work reasonably well unless there're too many
		 * parameters (in which case we should think of a mini key-value store).
		 */
		InputStream stream = null;
		BaseConfiguration loadedConfig = null;
		Properties diskProps = new Properties();

		try {
			stream = new FileInputStream(configOnDisk);
			loadedConfig = getConfiguration(stream, "", config.getClass());
			// copy parameters
			copyParameters(loadedConfig, diskProps);
		} catch (Throwable e) {
			LOGGER_.info("Overwriting configuration since it can't be loaded (perhaps doesn't exist?)");
		} finally {
			IOUtils.closeQuietly(stream);
		}

		copyParameters(config, diskProps);
		// now save it to the file
		saveProperties(diskProps, configOnDisk);
	}

	private static void saveProperties(Properties diskProps, File configOnDisk) {
		OutputStream stream = null;

		try {
			stream = new FileOutputStream(configOnDisk);
			diskProps.store(
					stream,
					"ELK parameters saved at "
							+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
									.format(new Date()));
		} catch (FileNotFoundException e) {
			throw new ConfigurationException(
					"Configuration cannot be saved because the destination file cannot be written",
					e);
		} catch (IOException e) {
			throw new ConfigurationException(
					"Configuration cannot be saved because the destination file cannot be written",
					e);
		} finally {
			IOUtils.closeQuietly(stream);
		}
	}

	private static void copyParameters(BaseConfiguration config,
			Properties diskProps) {
		for (String key : config.getParameterNames()) {
			diskProps.setProperty(key, config.getParameter(key).toString());
		}
	}

	private static void copyParameters(String prefix, BaseConfiguration config,
			ResourceBundle bundle) {
		for (String key : bundle.keySet()) {
			if (key.startsWith(prefix)) {
				config.setParameter(key, bundle.getString(key));
			}
		}
	}

	private static void copyParameters(final String prefix,
			final BaseConfiguration config, final Properties properties) {
		for (final Object key : properties.keySet()) {
			final String property = key.toString();
			if (property.startsWith(prefix)) {
				config.setParameter(property, properties.getProperty(property));
			}
		}
	}

	private static BaseConfiguration instantiate(
			Class<? extends BaseConfiguration> configClass)
			throws ConfigurationException {
		BaseConfiguration config = null;

		try {
			config = configClass.getConstructor().newInstance();

			config.initConfiguration();

			return config;

		} catch (Throwable e) {
			throw new ConfigurationException(
					"Failed to instantiate the configuration class "
							+ configClass);
		}
	}

}


package org.semanticweb.elk.util.collections;
/*
 * #%L
 * ELK Utilities Collections
 * $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%
 */

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A skeleton for creating iterators of collections backed by arrays with linear
 * probing resolution of hash collisions.
 *
 * @see LinearProbing
 *
 * @author "Yevgeny Kazakov"
 *
 * @param <E>
 *            the elements for which linear probing is used
 * @param <V>
 *            the elements that should be iterated by the iterator
 */
abstract class LinearProbingIterator<E, V> implements Iterator<V> {
	// copy of the data
	final E[] dataSnapshot;
	// expected size to check for concurrent modifications
	private int sizeSnapshot_;
	// the element at which to start iteration
	private int start_;
	// cursor of the current element
	private int current_;
	// cursor of the next element
	private int next_;

	LinearProbingIterator(E[] data, int size) {
		this.dataSnapshot = data;
		this.sizeSnapshot_ = size;
	}

	void init() {
		this.start_ = seekFirstNull();
		this.next_ = seekNext(start_);
		this.current_ = next_;
	}

	/**
	 * Checks if the given size is the correct size of the data.
	 *
	 * @param expectedSize
	 */
	abstract void checkSize(int expectedSize);

	/**
	 * Removes the element at the given position, moving other elements if
	 * necessary
	 *
	 * @param pos
	 */
	abstract void remove(int pos);

	/**
	 * Converts the given element and its position in the data to the
	 * corresponding value of the iterator.
	 *
	 * @param element
	 * @param pos
	 * @return
	 */
	abstract V getValue(E element, int pos);

	/**
	 * @return the position of the first {@code null} element
	 */
	int seekFirstNull() {
		for (int pos = 0; pos < dataSnapshot.length; pos++) {
			if (dataSnapshot[pos] == null)
				return pos;
		}
		throw new RuntimeException("Set is full! (" + dataSnapshot.length
				+ " elements)");
	}

	/**
	 * @param pos
	 *            the position to test
	 * @return {@code true} if it is occupied
	 */
	boolean isOccupied(int pos) {
		return dataSnapshot[pos] != null;
	}

	/**
	 * Searches for the next non-{@code null} element after the given position
	 * before the start position
	 *
	 * @param pos
	 *            position after which to search
	 * @return the position of the non-{@code null} element, or {@link #start_}
	 *         if there are no such element
	 */
	int seekNext(int pos) {
		for (;;) {
			if (++pos == dataSnapshot.length)
				pos = 0;
			if (pos == start_ || isOccupied(pos))
				return pos;
		}
	}

	@Override
	public boolean hasNext() {
		return next_ != start_;
	}

	@Override
	public V next() {
		checkSize(sizeSnapshot_);
		if (next_ == start_)
			throw new NoSuchElementException();
		this.current_ = next_;
		E element = dataSnapshot[current_];
		this.next_ = seekNext(current_);
		return getValue(element, current_);
	}

	@Override
	public void remove() {
		checkSize(sizeSnapshot_);
		if (current_ == next_)
			// the current element was not returned or was already removed
			throw new IllegalStateException();
		remove(current_);
		if (isOccupied(current_))
			// something was copied to the current position
			next_ = current_;
		else
			current_ = next_;
		sizeSnapshot_--;
	}

}


/**
 *
 */
package org.semanticweb.elk.ore;

/*
 * #%L
 * ELK ORE build
 * $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%
 */

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.semanticweb.elk.io.IOUtils;
import org.semanticweb.elk.owl.interfaces.ElkClass;
import org.semanticweb.elk.owl.interfaces.ElkClassAssertionAxiom;
import org.semanticweb.elk.owl.interfaces.ElkDeclarationAxiom;
import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.owl.interfaces.ElkEquivalentClassesAxiom;
import org.semanticweb.elk.owl.interfaces.ElkNamedIndividual;
import org.semanticweb.elk.owl.interfaces.ElkObject;
import org.semanticweb.elk.owl.interfaces.ElkSameIndividualAxiom;
import org.semanticweb.elk.owl.interfaces.ElkSubClassOfAxiom;
import org.semanticweb.elk.owl.managers.ElkObjectEntityRecyclingFactory;
import org.semanticweb.elk.owl.predefined.PredefinedElkIris;
import org.semanticweb.elk.owl.printers.OwlFunctionalStylePrinter;
import org.semanticweb.elk.reasoner.taxonomy.ElkClassKeyProvider;
import org.semanticweb.elk.reasoner.taxonomy.ElkIndividualKeyProvider;
import org.semanticweb.elk.reasoner.taxonomy.model.InstanceNode;
import org.semanticweb.elk.reasoner.taxonomy.model.InstanceTaxonomy;
import org.semanticweb.elk.reasoner.taxonomy.model.Taxonomy;
import org.semanticweb.elk.reasoner.taxonomy.model.TaxonomyNode;

/**
 * TaxonomyPrinter that satisfies the ORE specification
 *
 * @author Pavel Klinov
 *
 *         pavel.klinov@uni-ulm.de
 */
public class OreTaxonomyPrinter {

	protected static Comparator<ElkEntity>
			CLASS_COMPARATOR = ElkClassKeyProvider.INSTANCE.getComparator(),
			INDIVIDUAL_COMPARATOR = ElkIndividualKeyProvider.INSTANCE.getComparator();

	// prints SubClassOf(A, owl:Thing) for all direct subclasses of owl:Thing
	static void printClassTaxonomy(Taxonomy<ElkClass> taxonomy, File out)
			throws IOException {
		FileWriter fstream = null;
		BufferedWriter writer = null;

		try {
			fstream = new FileWriter(out);
			writer = new BufferedWriter(fstream);

			writer.append("Ontology(\n");

			processTaxomomy(taxonomy, writer);

			writer.append(")\n");
			writer.flush();

		} finally {
			IOUtils.closeQuietly(fstream);
			IOUtils.closeQuietly(writer);
		}
	}

	static void printInstanceTaxonomy(
			InstanceTaxonomy<ElkClass, ElkNamedIndividual> taxonomy, File out)
			throws IOException {
		FileWriter fstream = null;
		BufferedWriter writer = null;

		try {
			fstream = new FileWriter(out);
			writer = new BufferedWriter(fstream);

			writer.append("Ontology(\n");

			processInstanceTaxomomy(taxonomy, writer);

			writer.append(")\n");
			writer.flush();

		} finally {
			IOUtils.closeQuietly(fstream);
			IOUtils.closeQuietly(writer);
		}
	}

	protected static void processTaxomomy(Taxonomy<ElkClass> classTaxonomy,
			Appendable writer) throws IOException {
		ElkObject.Factory objectFactory = new ElkObjectEntityRecyclingFactory();

		printDeclarations(classTaxonomy, objectFactory, writer);

		TreeSet<ElkClass> canonicalElkClasses = new TreeSet<ElkClass>(
				CLASS_COMPARATOR);
		for (TaxonomyNode<ElkClass> classNode : classTaxonomy.getNodes())
			canonicalElkClasses.add(classNode.getCanonicalMember());

		for (ElkClass elkClass : canonicalElkClasses) {
			TaxonomyNode<ElkClass> classNode = classTaxonomy.getNode(elkClass);

			ArrayList<ElkClass> orderedEquivalentClasses = new ArrayList<ElkClass>(
					classNode.size());
			for (ElkClass member : classNode) {
				orderedEquivalentClasses.add(member);
			}
			Collections.sort(orderedEquivalentClasses, CLASS_COMPARATOR);

			TreeSet<ElkClass> orderedSubClasses = new TreeSet<ElkClass>(
					CLASS_COMPARATOR);
			for (TaxonomyNode<ElkClass> childNode : classNode
					.getDirectSubNodes()) {
				orderedSubClasses.add(childNode.getCanonicalMember());
			}
			// adding owl:Thing if the class is its direct subclass
			if (orderedEquivalentClasses.isEmpty()
					&& orderedSubClasses.isEmpty()) {
				orderedSubClasses.add(objectFactory.getOwlThing());
			}

			printClassAxioms(elkClass, orderedEquivalentClasses,
					orderedSubClasses, writer);
		}
	}

	/**
	 * Prints class declarations
	 *
	 * @param classTaxonomy
	 * @param objectFactory
	 * @param writer
	 * @throws IOException
	 */
	protected static void printDeclarations(Taxonomy<ElkClass> classTaxonomy,
			ElkObject.Factory objectFactory, Appendable writer)
			throws IOException {

		List<ElkClass> classes = new ArrayList<ElkClass>(classTaxonomy
				.getNodes().size() * 2);

		for (TaxonomyNode<ElkClass> classNode : classTaxonomy.getNodes()) {
			for (ElkClass clazz : classNode) {
				if (!clazz.getIri().equals(PredefinedElkIris.OWL_THING)
						&& !clazz.getIri()
								.equals(PredefinedElkIris.OWL_NOTHING)) {
					classes.add(clazz);

				}
			}
		}

		Collections.sort(classes, CLASS_COMPARATOR);

		for (ElkClass clazz : classes) {
			ElkDeclarationAxiom decl = objectFactory.getDeclarationAxiom(clazz);
			OwlFunctionalStylePrinter.append(writer, decl, true);
			writer.append('\n');
		}
	}

	protected static void processInstanceTaxomomy(
			InstanceTaxonomy<ElkClass, ElkNamedIndividual> taxonomy,
			Writer writer) throws IOException {
		ElkObject.Factory objectFactory = new ElkObjectEntityRecyclingFactory();

		printIndividualDeclarations(taxonomy.getInstanceNodes(), objectFactory,
				writer);
		// TBox printed here
		// processTaxomomy(taxonomy, writer);
		// print the ABox
		TreeSet<ElkNamedIndividual> canonicalIndividuals = new TreeSet<ElkNamedIndividual>(
				INDIVIDUAL_COMPARATOR);
		for (InstanceNode<ElkClass, ElkNamedIndividual> node : taxonomy
				.getInstanceNodes()) {
			canonicalIndividuals.add(node.getCanonicalMember());
		}

		for (ElkNamedIndividual individual : canonicalIndividuals) {
			InstanceNode<ElkClass, ElkNamedIndividual> node = taxonomy
					.getInstanceNode(individual);

			ArrayList<ElkNamedIndividual> orderedSameIndividuals = new ArrayList<ElkNamedIndividual>(
					node.size());
			for (ElkNamedIndividual member : node) {
				orderedSameIndividuals.add(member);
			}
			Collections.sort(orderedSameIndividuals, INDIVIDUAL_COMPARATOR);

			TreeSet<ElkClass> orderedTypes = new TreeSet<ElkClass>(
					CLASS_COMPARATOR);
			for (TaxonomyNode<ElkClass> typeNode : node.getAllTypeNodes()) {
				for (ElkClass member : typeNode) {
					orderedTypes.add(member);
				}
			}

			orderedTypes.add(objectFactory.getOwlThing());

			printIndividualAxioms(individual, orderedSameIndividuals,
					orderedTypes, objectFactory, writer);
		}
	}

	protected static void printIndividualDeclarations(
			Set<? extends InstanceNode<ElkClass, ElkNamedIndividual>> individualNodes,
			ElkObject.Factory objectFactory, Writer writer) throws IOException {
		for (InstanceNode<ElkClass, ElkNamedIndividual> individualNode : individualNodes) {
			for (ElkNamedIndividual individual : individualNode) {
				ElkDeclarationAxiom decl = objectFactory
						.getDeclarationAxiom(individual);
				OwlFunctionalStylePrinter.append(writer, decl, true);
				writer.append('\n');
			}
		}
	}

	protected static void printClassAxioms(ElkClass elkClass,
			ArrayList<ElkClass> orderedEquivalentClasses,
			TreeSet<ElkClass> orderedSubClasses, Appendable writer)
			throws IOException {

		ElkObject.Factory objectFactory = new ElkObjectEntityRecyclingFactory();

		if (orderedEquivalentClasses.size() > 1) {
			ElkEquivalentClassesAxiom elkEquivalentClassesAxiom = objectFactory
					.getEquivalentClassesAxiom(orderedEquivalentClasses);
			OwlFunctionalStylePrinter.append(writer, elkEquivalentClassesAxiom,
					true);
			writer.append('\n');
		}

		for (ElkClass elkSubClass : orderedSubClasses)
			if (!elkSubClass.getIri().equals(PredefinedElkIris.OWL_NOTHING)) {
				ElkSubClassOfAxiom elkSubClassAxiom = objectFactory
						.getSubClassOfAxiom(elkSubClass, elkClass);
				OwlFunctionalStylePrinter
						.append(writer, elkSubClassAxiom, true);
				writer.append('\n');
			}
	}

	protected static void printIndividualAxioms(ElkNamedIndividual individual,
			ArrayList<ElkNamedIndividual> orderedSameIndividuals,
			TreeSet<ElkClass> orderedDirectClasses,
			ElkObject.Factory objectFactory, Writer writer) throws IOException {

		if (orderedSameIndividuals.size() > 1) {
			ElkSameIndividualAxiom axiom = objectFactory
					.getSameIndividualAxiom(orderedSameIndividuals);

			OwlFunctionalStylePrinter.append(writer, axiom, true);
			writer.append('\n');
		}

		for (ElkClass clazz : orderedDirectClasses) {
			ElkClassAssertionAxiom axiom = objectFactory
					.getClassAssertionAxiom(clazz, individual);

			OwlFunctionalStylePrinter.append(writer, axiom, true);
			writer.append('\n');
		}
	}
}


/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2013 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.taxonomy;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.reasoner.taxonomy.model.GenericInstanceNode;
import org.semanticweb.elk.reasoner.taxonomy.model.GenericTaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.GenericTypeNode;
import org.semanticweb.elk.util.collections.ArrayHashSet;
import org.semanticweb.elk.util.collections.Operations;
import org.semanticweb.elk.util.collections.Operations.Functor;

/**
 * A collection of utility methods, mostly for the frequent use case of
 * recursive traversal
 *
 * @author Pavel Klinov
 *
 *         pavel.klinov@uni-ulm.de
 * @author Peter Skocovsky
 */
public class TaxonomyNodeUtils {

	public static <N> Set<N> getAllReachable(
					final Collection<? extends N> direct,
					final Functor<N, Set<? extends N>> succ) {

		final Set<N> result = new ArrayHashSet<N>(direct.size());
		result.addAll(direct);
		final Queue<N> todo = new LinkedList<N>(direct);

		while (!todo.isEmpty()) {
			final N next = todo.poll();

			for (final N succNode : succ.apply(next)) {
				if (result.add(succNode)) {
					todo.add(succNode);
				}
			}
		}

		return Collections.unmodifiableSet(result);
	}

	public static <N, O> Set<O> collectFromAllReachable(
					final Collection<? extends N> direct,
					final Collection<? extends O> init,
					final Functor<N, Set<? extends N>> succ,
					final Functor<N, Set<? extends O>> collect) {

		final Set<O> result = new ArrayHashSet<O>();
		result.addAll(init);
		final Set<N> queued = new ArrayHashSet<N>();
		queued.addAll(direct);
		final Queue<N> todo = new LinkedList<N>(direct);

		while (!todo.isEmpty()) {
			final N next = todo.poll();

			result.addAll(collect.apply(next));

			for (final N succNode : succ.apply(next)) {
				if (queued.add(succNode)) {
					todo.add(succNode);
				}
			}
		}

		return Collections.unmodifiableSet(result);
	}

	/**
	 * Returns all super-nodes of a node whose direct super-nodes are
	 * direct.
	 *
	 * @param direct
	 *            The direct super-nodes.
	 * @return all super-nodes of a node whose direct super-nodes are
	 *         direct.
	 */
	public static <T extends ElkEntity, N extends GenericTaxonomyNode<T, N>>
			Set<? extends N> getAllSuperNodes(final Collection<? extends N> direct) {
		return getAllReachable(direct, new Functor<N, Set<? extends N>>() {

			@Override
			public Set<? extends N> apply(final N node) {
				return node.getDirectSuperNodes();
			}});
	}

	/**
	 * Returns all sub-nodes of a node whose direct sub-nodes are
	 * direct.
	 *
	 * @param direct
	 *            The direct sub-nodes.
	 * @return all sub-nodes of a node whose direct sub-nodes are
	 *         direct.
	 */
	public static <T extends ElkEntity, N extends GenericTaxonomyNode<T, N>>
			Set<? extends N> getAllSubNodes(final Collection<? extends N> direct) {
		return getAllReachable(direct, new Functor<N, Set<? extends N>>() {

			@Override
			public Set<? extends N> apply(final N node) {
				return node.getDirectSubNodes();
			}});
	}

	/**
	 * Returns all instance nodes of the specified type node and all its
	 * sub-nodes.
	 *
	 * @param node
	 *            The type node whose instances should be returned.
	 * @return all instance nodes of the specified type node and all its
	 *         sub-nodes.
	 */
	public static <T extends ElkEntity, I extends ElkEntity, TN extends GenericTypeNode<T, I, TN, IN>, IN extends GenericInstanceNode<T, I, TN, IN>>
			Set<? extends IN> getAllInstanceNodes(final GenericTypeNode<T, I, TN, IN> node) {
		return TaxonomyNodeUtils.collectFromAllReachable(
				node.getDirectSubNodes(),
				node.getDirectInstanceNodes(),
				new Operations.Functor<GenericTypeNode<T, I, TN, IN>, Set<? extends GenericTypeNode<T, I, TN, IN>>>() {
					@Override
					public Set<? extends TN> apply(final GenericTypeNode<T, I, TN, IN> node) {
						return node.getDirectSubNodes();
					}
				},
				new Operations.Functor<GenericTypeNode<T, I, TN, IN>, Set<? extends IN>>() {
					@Override
					public Set<? extends IN> apply(final GenericTypeNode<T, I, TN, IN> node) {
						return node.getDirectInstanceNodes();
					}
				});
	}

}


package org.semanticweb.elk.util.collections.chains;

import java.util.Map;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2012 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%
 */

/**
 * This class provides a skeletal implementation of the {@link Chain} interface
 * to minimize the effort required to implement this interface. Essentially, one
 * has to provide only the implementation of the {@link Link} interface.
 *
 * @author "Yevgeny Kazakov"
 *
 * @param <T>
 *            The type of elements in the chain.
 */
public abstract class AbstractChain<T extends ModifiableLink<T>> implements
		Chain<T> {

	@Override
	public <S extends T> S find(Matcher<? super T, S> matcher) {
		T candidate = next();
		for (;;) {
			if (candidate == null)
				return null;
			S match = matcher.match(candidate);
			if (match != null)
				return match;
			candidate = candidate.next();
		}
	}

	@Override
	public <S extends T> S getCreate(Matcher<? super T, S> matcher,
			ReferenceFactory<T, S> factory) {
		T candidate = next();
		for (;;) {
			if (candidate == null) {
				S result = factory.create(next());
				setNext(result);
				return result;
			}
			S match = matcher.match(candidate);
			if (match != null)
				return match;
			candidate = candidate.next();
		}
	}

	@Override
	public <S extends T> S remove(Matcher<? super T, S> matcher) {
		ModifiableLink<T> point = this;
		for (;;) {
			T next = point.next();
			if (next == null)
				return null;
			S match = matcher.match(next);
			if (match != null) {
				point.setNext(next.next());
				return match;
			}
			point = next;
		}
	}

	/**
	 * Creates a {@link Chain} view of the value associated with the given key
	 * in the given {@link Map}. The values of the map must be instances of the
	 * type that can be used in the {@link Chain} interface. All operations with
	 * the returned {@link Chain}, such as addition or removal, will be
	 * reflected accordingly in the corresponding value in the {@link Map}.
	 *
	 * @param map
	 *            the {@link Map} that backs the data
	 * @param key
	 *            the key for which to return the {@link Chain} view of the data
	 * @return the {@link Chain} view of the data associated with key in map
	 */
	public static <K, T extends ModifiableLink<T>> Chain<T> getMapBackedChain(
			final Map<K, T> map, final K key) {
		return new AbstractChain<T>() {

			@Override
			public T next() {
				return map.get(key);
			}

			@Override
			public void setNext(T next) {
				if (next == null)
					map.remove(key);
				else
					map.put(key, next);
			}
		};
	}
}


/*
 * #%L
 * ELK Utilities Collections
 *
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2011 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.util.collections.entryset;

import java.util.AbstractCollection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * TODO: update documentation
 *
 * A collection of entries, maintained modulo structural equality
 * {@code Entry#structuralEquals(Object)}. This may be different from
 * {@code Entry#equals(Object)}, which is used for finding an element in the
 * collection. The main methods are inserting, removing, and finding elements
 * modulo structural equality.
 *
 * The implementation is largely based on the implementation of
 * {@linkplain HashSet} from the standard Java collection library.
 *
 * @author "Yevgeny Kazakov"
 *
 *
 * @param <E>
 *            the type of entries in the collection
 */
public class EntryCollection<E extends Entry<?, E>>
		extends AbstractCollection<E> {

	/**
	 * The default initial capacity - MUST be a power of two.
	 */
	static final int DEFAULT_INITIAL_CAPACITY = 16;

	/**
	 * The maximum capacity, used if a higher value is implicitly specified by
	 * either of the constructors with arguments. MUST be a power of two <=
	 * 1<<30.
	 */
	static final int MAXIMUM_CAPACITY = 1 << 30;

	/**
	 * The under-load factor used when none specified in constructor.
	 */
	static final float DEFAULT_UNDERLOAD_FACTOR = 0.15f;

	/**
	 * The over-load factor used when none specified in constructor.
	 */
	static final float DEFAULT_OVERLOAD_FACTOR = 0.75f;

	/**
	 * The bucket array, resized as necessary. Length MUST Always be a power of
	 * two.
	 */
	transient E[] buckets;

	/**
	 * The number of entries contained in this map.
	 */
	transient int size;

	/**
	 * The minimum size of the set, below which the set is not shrink.
	 *
	 * @serial
	 */
	int minsize;

	/**
	 * The next minimum size value at which to shrink the buckets array array
	 * (capacity * under-load factor).
	 *
	 * @serial
	 */
	int undersize;

	/**
	 * The next maximum size value at which to expand the buckets array
	 * (capacity * over-load factor).
	 *
	 * @serial
	 */
	int oversize;

	/**
	 * The over-load factor for the buckets array.
	 *
	 * @serial
	 */
	final float overloadFactor;

	/**
	 * The under-load factor for the buckets array.
	 *
	 * @serial
	 */
	final float underloadFactor;

	/**
	 * The number of times this {@link EntryCollection} has been modified. This
	 * field is used to make iterators on Collection-views of the HashMap
	 * fail-fast. (See ConcurrentModificationException).
	 */
	transient int modCount;

	/**
	 * Constructs an empty {@link EntryCollection} with the specified initial
	 * capacity, under-load factor, and over-load factor. The over-load factor
	 * needs to be larger than twice the under-load factor (ideally even more).
	 *
	 * @param initialCapacity
	 *            the initial capacity
	 * @param underloadFactor
	 *            the under-load factor
	 * @param overloadFactor
	 *            the over-load factor
	 * @throws IllegalArgumentException
	 *             if the initial capacity is negative or the load factor is
	 *             non-positive
	 */
	@SuppressWarnings("unchecked")
	public EntryCollection(int initialCapacity, float underloadFactor,
			float overloadFactor) {
		if (initialCapacity < 0)
			throw new IllegalArgumentException(
					"Illegal initial capacity: " + initialCapacity);
		if (initialCapacity > MAXIMUM_CAPACITY)
			initialCapacity = MAXIMUM_CAPACITY;
		if (overloadFactor <= 0 || Float.isNaN(overloadFactor))
			throw new IllegalArgumentException(
					"Illegal load factor: " + overloadFactor);

		// Find a power of 2 >= initialCapacity
		int capacity = 1;
		while (capacity < initialCapacity)
			capacity <<= 1;

		this.underloadFactor = underloadFactor;
		this.overloadFactor = overloadFactor;
		this.minsize = initialCapacity;
		undersize = (int) (capacity * underloadFactor);
		oversize = (int) (capacity * overloadFactor);
		buckets = (E[]) new Entry[capacity];
		init();
	}

	/**
	 * Constructs an empty {@link EntryCollection} with the specified initial
	 * capacity, the default under-load factor (0.15), and the default over-load
	 * factor (0.75).
	 *
	 * @param initialCapacity
	 *            the initial capacity.
	 * @throws IllegalArgumentException
	 *             if the initial capacity is negative.
	 */
	public EntryCollection(int initialCapacity) {
		this(initialCapacity, DEFAULT_UNDERLOAD_FACTOR,
				DEFAULT_OVERLOAD_FACTOR);
	}

	/**
	 * Constructs an empty {@link EntryCollection} with the default initial
	 * capacity (16), the default under-load factor (0.15), and the default
	 * over-load factor (0.75).
	 */
	@SuppressWarnings("unchecked")
	public EntryCollection() {
		this.underloadFactor = DEFAULT_UNDERLOAD_FACTOR;
		this.overloadFactor = DEFAULT_OVERLOAD_FACTOR;
		undersize = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_UNDERLOAD_FACTOR);
		oversize = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_OVERLOAD_FACTOR);
		buckets = (E[]) new Entry[DEFAULT_INITIAL_CAPACITY];
		init();
	}

	// internal utilities

	/**
	 * Initialization hook for subclasses. This method is called in all
	 * constructors and pseudo-constructors (clone, readObject) after
	 * {@link EntryCollection} has been initialized but before any entries have
	 * been inserted. (In the absence of this method, readObject would require
	 * explicit knowledge of subclasses.)
	 */
	void init() {
	}

	/**
	 * Applies a supplemental hash function to a given hashCode, which defends
	 * against poor quality hash functions. This is critical because
	 * {@link EntryCollection} uses power-of-two length buckets array, that
	 * otherwise encounter collisions for hashCodes that do not differ in lower
	 * bits.
	 */
	static int hash(int h) {
		// This function ensures that hashCodes that differ only by
		// constant multiples at each bit position have a bounded
		// number of collisions (approximately 8 at default load factor).
		h ^= (h >>> 20) ^ (h >>> 12);
		return h ^ (h >>> 7) ^ (h >>> 4);
	}

	/**
	 * Returns index for hash code h.
	 */
	static int indexFor(int h, int length) {
		return hash(h) & (length - 1);
	}

	/**
	 * Returns the number of entries in this set.
	 *
	 * @return the number of entries in this set
	 */
	@Override
	public int size() {
		return size;
	}

	/**
	 * Finds and returns the entry in set that is structurally equal to the
	 * input entry if there is one. Equality of entries is decided using
	 * {@link Entry#structuralHashCode()} and
	 * {@link Entry#structuralEquals(Object)} methods.
	 *
	 * @param entry
	 *            the entry for which the equal entry should be found
	 *
	 * @return the entry in the set that is equal to the input entry if there is
	 *         one, or {@code null} otherwise
	 *
	 */
	public <T extends Entry<T, ?>> T findStructural(Entry<T, ?> entry) {
		int h = entry.structuralHashCode();
		int i = indexFor(h, buckets.length);
		T result = null;
		for (E r = buckets[i]; r != null; r = r.getNext()) {
			if (r.structuralHashCode() == h
					&& (result = entry.structuralEquals(r)) != null)
				return result;
		}
		// else fail
		return null;
	}

	/**
	 * Adds the given entry to this collection; the entry is added even if a
	 * structurally equal entry (modulo {@link Entry#structuralHashCode()} and
	 * {@link Entry#structuralEquals(Object)}) is already present in the
	 * collection
	 *
	 * @param entry
	 *            the entry to be inserted; it is not allowed to have linked
	 *            elements: {@link Entry#getNext()} should be {@code null}
	 */
	public void addStructural(E entry) {
		if (entry.getNext() != null)
			throw new IllegalArgumentException(
					"The given entry should be fresh!");
		int h = entry.structuralHashCode();
		int i = indexFor(h, buckets.length);
		modCount++;
		E e = buckets[i];
		entry.setNext(e);
		buckets[i] = entry;
		if (size++ >= oversize)
			resize(2 * buckets.length);
	}

	/**
	 * Removes and returns the entry in the set that is structurally equal to
	 * the specified entry. Returns {@code null} if the set contains no such
	 * entry. Equality of entries is decided using
	 * {@link Entry#structuralHashCode()} and
	 * {@link Entry#structuralEquals(Object)} methods.
	 *
	 * @param entry
	 *            the entry that is used for finding the entry to be removed
	 * @return the removed entry, or {@code null} if no entry that is equal to
	 *         the input object is found
	 */
	public <T extends Entry<T, ?>> T removeStructural(Entry<T, ?> entry) {
		int h = entry.structuralHashCode();
		int i = indexFor(h, buckets.length);
		E prev = buckets[i];
		E r = prev;
		T result = null;

		while (r != null) {
			E next = r.getNext();
			if (r.structuralHashCode() == h
					&& (result = entry.structuralEquals(r)) != null) {
				modCount++;
				if (prev == r)
					buckets[i] = next;
				else
					prev.setNext(next);
				if (size-- <= undersize && buckets.length >= 2 * minsize)
					resize(buckets.length / 2);
				return result;
			}
			prev = r;
			r = next;
		}
		// not found
		return null;
	}

	/**
	 * Rehashes the contents of this map into a new array with a new capacity.
	 * This method is called automatically when the number of entries in this
	 * set becomes below the {@link #undersize} or above the {@link #oversize}.
	 *
	 * If current capacity is MAXIMUM_CAPACITY, this method does not resize the
	 * map, but sets threshold to Integer.MAX_VALUE. This has the effect of
	 * preventing future calls.
	 *
	 * @param newCapacity
	 *            the new capacity, MUST be a power of two
	 */
	void resize(int newCapacity) {
		E[] oldTable = buckets;
		int oldCapacity = oldTable.length;
		if (oldCapacity == MAXIMUM_CAPACITY) {
			oversize = Integer.MAX_VALUE;
			oversize = (int) (newCapacity * overloadFactor);
			return;
		}

		@SuppressWarnings("unchecked")
		E[] newTable = (E[]) new Entry[newCapacity];
		transfer(newTable);
		buckets = newTable;
		undersize = (int) (newCapacity * underloadFactor);
		oversize = (int) (newCapacity * overloadFactor);
	}

	/**
	 * Transfers all entries from current buckets array to new buckets array.
	 */
	/**
	 * @param newArray
	 *            the new buckets array into which the entries are transferred.
	 */
	void transfer(E[] newArray) {
		E[] src = buckets;
		int newCapacity = newArray.length;
		for (int j = 0; j < src.length; j++) {
			E e = src[j];
			if (e != null) {
				src[j] = null;
				do {
					E next = e.getNext();
					int i = indexFor(e.structuralHashCode(), newCapacity);
					e.setNext(newArray[i]);
					newArray[i] = e;
					e = next;
				} while (e != null);
			}
		}
	}

	/**
	 * Removes all entries from this set. The set will be empty after this call
	 * returns.
	 */
	@Override
	public void clear() {
		modCount++;
		E[] tab = buckets;
		for (int i = 0; i < tab.length; i++)
			tab[i] = null;
		size = 0;
	}

	@Override
	public Iterator<E> iterator() {
		return new EntryIterator();
	}

	/**
	 * The iterator over the entries in the collection.
	 *
	 * @author "Yevgeny Kazakov"
	 *
	 */
	private class EntryIterator implements Iterator<E> {
		E next; // next entry to return
		int expectedModCount; // For fast-fail
		int index; // current slot
		E current; // current entry

		EntryIterator() {
			expectedModCount = modCount;
			if (size > 0) { // advance to first entry
				E[] t = buckets;
				while (index < t.length && (next = t[index++]) == null)
					;
			}
		}

		@Override
		public final boolean hasNext() {
			return next != null;
		}

		@Override
		public final E next() {
			if (modCount != expectedModCount)
				throw new ConcurrentModificationException();
			E e = next;
			if (e == null)
				throw new NoSuchElementException();

			if ((next = e.getNext()) == null) {
				E[] t = buckets;
				while (index < t.length && (next = t[index++]) == null)
					;
			}
			current = e;
			return e;
		}

		@Override
		public void remove() {
			if (current == null)
				throw new IllegalStateException();
			if (modCount != expectedModCount)
				throw new ConcurrentModificationException();
			EntryCollection.this.removeStructural((Entry<?, ?>) current);
			current = null;
			expectedModCount = modCount;
		}

	}

}


package org.semanticweb.elk.reasoner.saturation.conclusions.classes;

import org.semanticweb.elk.Reference;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2015 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%
 */

import org.semanticweb.elk.reasoner.saturation.conclusions.model.ClassConclusion;
import org.semanticweb.elk.reasoner.saturation.context.ClassConclusionSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A {@link ClassConclusion.Visitor} that removes the visited
 * {@link ClassConclusion} from the {@link ClassConclusionSet} of the given
 * {@link Reference}. The visit method returns {@link true} if the
 * {@link ClassConclusionSet} was modified as the result of this operation,
 * i.e., the {@link ClassConclusion} was contained in the
 * {@link ClassConclusionSet}.
 *
 * @see ClassConclusionInsertionVisitor
 * @see ClassConclusionOccurrenceCheckingVisitor
 *
 * @author "Yevgeny Kazakov"
 */
public class ClassConclusionDeletionVisitor extends
		DummyClassConclusionVisitor<Boolean> {

	// logger for events
	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(ClassConclusionDeletionVisitor.class);

	private final Reference<? extends ClassConclusionSet> conclusionsRef;

	public ClassConclusionDeletionVisitor(Reference<? extends ClassConclusionSet> conclusionsRef) {
		this.conclusionsRef = conclusionsRef;

	}

	// TODO: make this by combining the visitor in order to avoid overheads when
	// logging is switched off
	@Override
	protected Boolean defaultVisit(ClassConclusion conclusion) {
		ClassConclusionSet conclusions = conclusionsRef.get();
		boolean result = conclusions.removeConclusion(conclusion);
		if (LOGGER_.isTraceEnabled()) {
			LOGGER_.trace("{}: deleting {}: {}", conclusions, conclusion,
					result ? "success" : "failure");
		}
		return result;
	}

}


package org.semanticweb.elk.reasoner.saturation.inferences;

/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2015 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%
 */

import org.semanticweb.elk.reasoner.indexing.model.IndexedContextRoot;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObjectProperty;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObjectSomeValuesFrom;
import org.semanticweb.elk.reasoner.saturation.conclusions.model.Propagation;

abstract class AbstractPropagationInference extends AbstractSubClassInference
		implements PropagationInference {

	private final IndexedObjectSomeValuesFrom carry_;

	public AbstractPropagationInference(IndexedContextRoot root,
			IndexedObjectProperty relation, IndexedObjectSomeValuesFrom carry) {
		super(root, relation);
		this.carry_ = carry;
	}

	public IndexedObjectProperty getRelation() {
		return getSubDestination();
	}

	public IndexedObjectSomeValuesFrom getCarry() {
		return this.carry_;
	}

	public IndexedObjectSomeValuesFrom getConclusionCarry() {
		return getCarry();
	}

	/**
	 * @param factory
	 *            the factory for creating conclusions
	 *
	 * @return the conclusion produced by this inference
	 */
	public final Propagation getConclusion(Propagation.Factory factory) {
		return factory.getPropagation(getDestination(), getRelation(),
				getCarry());
	}

	@Override
	public final <O> O accept(SubClassInference.Visitor<O> visitor) {
		return accept((PropagationInference.Visitor<O>) visitor);
	}

}