<commit_before>/**
 * 
 */
package org.semanticweb.elk.reasoner.stages.debug;

import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.semanticweb.elk.owl.exceptions.ElkException;
import org.semanticweb.elk.owl.exceptions.ElkRuntimeException;
import org.semanticweb.elk.reasoner.indexing.OntologyIndex;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedClass.OwlThingContextInitializationRule;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedClassExpression;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedDisjointnessAxiom;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedObjectIntersectionOf;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedPropertyChain;
import org.semanticweb.elk.reasoner.saturation.SaturationState.Writer;
import org.semanticweb.elk.reasoner.saturation.conclusions.BackwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.Contradiction;
import org.semanticweb.elk.reasoner.saturation.conclusions.ForwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.Propagation;
import org.semanticweb.elk.reasoner.saturation.context.Context;
import org.semanticweb.elk.reasoner.saturation.rules.LinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.RuleApplicationVisitor;
import org.semanticweb.elk.util.collections.ArrayHashSet;

/**
 * Inspects all class expressions that are reachable via context rules or
 * backward link rules to make sure they all exist in the index
 * 
 * @author <NAME>
 * 
 *         <EMAIL>
 */
public class SaturationGraphValidationStage extends BasePostProcessingStage {

	private static final Logger LOGGER_ = Logger.getLogger(SaturationGraphValidationStage.class);
	
	private final OntologyIndex index_;
	private final ClassExpressionValidator iceValidator_ = new ClassExpressionValidator();
	private final ContextValidator contextValidator_ = new ContextValidator();
	private final ContextRuleValidator ruleValidator_ = new ContextRuleValidator();
	
	public SaturationGraphValidationStage(final OntologyIndex index) {
		index_ = index;
	}
	
	@Override
	public String getName() {
		return "Saturation graph validation";
	}

	@Override
	public void execute() throws ElkException {
		// starting from indexed class expressions
		for (IndexedClassExpression ice : index_.getIndexedClassExpressions()) {
			iceValidator_.validate(ice);
		}
	}

	/**
	 * 
	 */
	private class ClassExpressionValidator {
		
		private final Set<IndexedClassExpression> cache_ = new ArrayHashSet<IndexedClassExpression>();
		
		void validate(IndexedClassExpression ice) {
			if (!cache_.add(ice)) {
				return;
			}
			
			if (LOGGER_.isTraceEnabled()) {
				LOGGER_.trace("Validating class expression " + ice);
			}
			
			// this is the main check
			if (!index_.getIndexedClassExpressions().contains(ice)) {
				throw new ElkRuntimeException("Dead class expression detected " + ice);
			}
			
			// validating context
			contextValidator_.validate(ice.getContext());
			
			// validating context rules
			LinkRule<Context> rule = ice.getCompositionRuleHead();
			
			while (rule != null) {
				rule.accept(ruleValidator_, null, null);
				rule = rule.next();
			}
		}
	}
	
	/**
	 * 
	 * 
	 */
	private class ContextValidator {
		
		private final Set<Context> cache_ = new ArrayHashSet<Context>();
		
		void validate(Context context) {
			if (context == null || !cache_.add(context)) {
				return;
			}
			
			if (LOGGER_.isTraceEnabled()) {
				LOGGER_.trace("Validating context for " + context.getRoot());
			}
			
			// validating subsumers recursively
			for (IndexedClassExpression subsumer : context.getSubsumers()) {
				iceValidator_.validate(subsumer);
			}
			
			//validating backward links
			for (IndexedPropertyChain prop : context.getBackwardLinksByObjectProperty().keySet()) {
				for (Context linkedContext : context.getBackwardLinksByObjectProperty().get(prop)) {
					validate(linkedContext);
				}
			}
			
			//validating backward link rules
			LinkRule<BackwardLink> rule = context.getBackwardLinkRuleHead();
			
			while (rule != null) {
				rule.accept(ruleValidator_, null, null);
				rule = rule.next();
			}
		}
	}
	
	/**
	 * 
	 */
	private class ContextRuleValidator implements RuleApplicationVisitor {

		@Override
		public void visit(
				OwlThingContextInitializationRule owlThingContextInitializationRule,
				Writer writer, Context context) {
		}

		@Override
		public void visit(IndexedDisjointnessAxiom.ThisCompositionRule thisCompositionRule,
				Writer writer, Context context) {
			for (IndexedDisjointnessAxiom axiom : thisCompositionRule.getDisjointnessAxioms()) {
				if (!index_.getIndexedAxioms().contains(axiom)) {
					throw new ElkRuntimeException("Dead disjointness axiom detected " + axiom);
				}
				
				for (IndexedClassExpression ice : axiom.getDisjointMembers()) {
					iceValidator_.validate(ice);
				}
			}
			
		}

		@Override
		public void visit(
				org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedObjectIntersectionOf.ThisCompositionRule thisCompositionRule,
				Writer writer, Context context) {
			for (Map.Entry<IndexedClassExpression, IndexedObjectIntersectionOf> entry : thisCompositionRule.getConjunctionsByConjunct().entrySet()) {<commit_msg>using occurs() for checking liveness of an indexed object<commit_after>/**
 * 
 */
package org.semanticweb.elk.reasoner.stages.debug;

import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.semanticweb.elk.owl.exceptions.ElkException;
import org.semanticweb.elk.owl.exceptions.ElkRuntimeException;
import org.semanticweb.elk.reasoner.indexing.OntologyIndex;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedClass.OwlThingContextInitializationRule;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedClassExpression;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedDisjointnessAxiom;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedObjectIntersectionOf;
import org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedPropertyChain;
import org.semanticweb.elk.reasoner.saturation.SaturationState.Writer;
import org.semanticweb.elk.reasoner.saturation.conclusions.BackwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.Contradiction;
import org.semanticweb.elk.reasoner.saturation.conclusions.ForwardLink;
import org.semanticweb.elk.reasoner.saturation.conclusions.Propagation;
import org.semanticweb.elk.reasoner.saturation.context.Context;
import org.semanticweb.elk.reasoner.saturation.rules.LinkRule;
import org.semanticweb.elk.reasoner.saturation.rules.RuleApplicationVisitor;
import org.semanticweb.elk.util.collections.ArrayHashSet;

/**
 * Inspects all class expressions that are reachable via context rules or
 * backward link rules to make sure they all exist in the index
 * 
 * @author <NAME>
 * 
 *         <EMAIL>
 */
public class SaturationGraphValidationStage extends BasePostProcessingStage {

	private static final Logger LOGGER_ = Logger.getLogger(SaturationGraphValidationStage.class);
	
	private final OntologyIndex index_;
	private final ClassExpressionValidator iceValidator_ = new ClassExpressionValidator();
	private final ContextValidator contextValidator_ = new ContextValidator();
	private final ContextRuleValidator ruleValidator_ = new ContextRuleValidator();
	
	public SaturationGraphValidationStage(final OntologyIndex index) {
		index_ = index;
	}
	
	@Override
	public String getName() {
		return "Saturation graph validation";
	}

	@Override
	public void execute() throws ElkException {
		// starting from indexed class expressions
		for (IndexedClassExpression ice : index_.getIndexedClassExpressions()) {
			iceValidator_.validate(ice);
		}
	}

	/**
	 * 
	 */
	private class ClassExpressionValidator {
		
		private final Set<IndexedClassExpression> cache_ = new ArrayHashSet<IndexedClassExpression>();
		
		void validate(IndexedClassExpression ice) {
			if (!cache_.add(ice)) {
				return;
			}
			
			if (LOGGER_.isTraceEnabled()) {
				LOGGER_.trace("Validating class expression " + ice);
			}
			
			// this is the main check
			if (!ice.occurs()) {
				throw new ElkRuntimeException("Dead class expression detected " + ice);
			}
			
			// validating context
			contextValidator_.validate(ice.getContext());
			
			// validating context rules
			LinkRule<Context> rule = ice.getCompositionRuleHead();
			
			while (rule != null) {
				rule.accept(ruleValidator_, null, null);
				rule = rule.next();
			}
		}
	}
	
	/**
	 * 
	 * 
	 */
	private class ContextValidator {
		
		private final Set<Context> cache_ = new ArrayHashSet<Context>();
		
		void validate(Context context) {
			if (context == null || !cache_.add(context)) {
				return;
			}
			
			if (LOGGER_.isTraceEnabled()) {
				LOGGER_.trace("Validating context for " + context.getRoot());
			}
			
			// validating subsumers recursively
			for (IndexedClassExpression subsumer : context.getSubsumers()) {
				iceValidator_.validate(subsumer);
			}
			
			//validating backward links
			for (IndexedPropertyChain prop : context.getBackwardLinksByObjectProperty().keySet()) {
				for (Context linkedContext : context.getBackwardLinksByObjectProperty().get(prop)) {
					validate(linkedContext);
				}
			}
			
			//validating backward link rules
			LinkRule<BackwardLink> rule = context.getBackwardLinkRuleHead();
			
			while (rule != null) {
				rule.accept(ruleValidator_, null, null);
				rule = rule.next();
			}
		}
	}
	
	/**
	 * 
	 */
	private class ContextRuleValidator implements RuleApplicationVisitor {

		@Override
		public void visit(
				OwlThingContextInitializationRule owlThingContextInitializationRule,
				Writer writer, Context context) {
		}

		@Override
		public void visit(IndexedDisjointnessAxiom.ThisCompositionRule thisCompositionRule,
				Writer writer, Context context) {
			for (IndexedDisjointnessAxiom axiom : thisCompositionRule.getDisjointnessAxioms()) {
				if (!axiom.occurs()) {
					throw new ElkRuntimeException("Dead disjointness axiom detected " + axiom);
				}
				
				for (IndexedClassExpression ice : axiom.getDisjointMembers()) {
					iceValidator_.validate(ice);
				}
			}
			
		}

		@Override
		public void visit(
				org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedObjectIntersectionOf.ThisCompositionRule thisCompositionRule,
				Writer writer, Context context) {
			for (Map.Entry<IndexedClassExpression, IndexedObjectIntersectionOf> entry : thisCompositionRule.getConjunctionsByConjunct().entrySet()) {
{'fraction_non_alphanumeric': 0.09663945319916462, 'fraction_numerical': 0.00018986140117714068, 'mean_word_length': 4.524383848977451, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4338307', 'n_tokens_mistral': 3580, 'n_tokens_neox': 3088, 'n_words': 606}