package org.obolibrary.robot.checks;

import java.util.HashSet;
import java.util.Set;

import org.obolibrary.robot.checks.InvalidReferenceViolation.Category;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.parameters.Imports;

/**
 * 
 * See: https://github.com/ontodev/robot/issues/1
 * 
 * @author cjm
 *
 */
public class InvalidReferenceChecker {
    
    
    /**
     * @param ontology
     * @param entity 
     * @return true if owlClass has no logical or non-logical axioms
     */
    public static boolean isDangling(OWLOntology ontology, OWLEntity entity)  {
        if (entity instanceof OWLClass) {
            OWLClass owlClass = (OWLClass)entity;
            if (ontology.getAxioms(owlClass, Imports.INCLUDED).size() > 0)
                return false;
            if (ontology.getAnnotationAssertionAxioms(owlClass.getIRI()).size() > 0)
                return false;
            return true;
        }
        if (entity instanceof OWLObjectProperty) {
            OWLObjectProperty owlProperty = (OWLObjectProperty)entity;
            if (ontology.getAxioms(owlProperty, Imports.INCLUDED).size() > 0)
                return false;
            if (ontology.getAnnotationAssertionAxioms(owlProperty.getIRI()).size() > 0)
                return false;
            return true;
        }
        return false;
    }
    
    /**
     * @param ontology
     * @param entity
     * @return true if entity is deprecated
     */
    public static boolean isDeprecated(OWLOntology ontology, OWLEntity entity)  {
        for (OWLAnnotationAssertionAxiom a : ontology.getAnnotationAssertionAxioms(entity.getIRI())) {
            if (a.isDeprecatedIRIAssertion()) {
                if (a.getValue().asLiteral().get().parseBoolean()) {
                    return true;
                }
            }
        }
        return false;
    }
   
    
    /**
     * @param ontology
     * @param axioms
     * @return all violations
     */
    public static Set<InvalidReferenceViolation> getInvalidReferenceViolations(OWLOntology ontology, Set<OWLAxiom> axioms, boolean ignoreDangling) {
        Set<InvalidReferenceViolation> violations = new HashSet<>();
        for (OWLAxiom axiom : axioms) {
            for (OWLEntity e : axiom.getSignature()) {
                if (!ignoreDangling && isDangling(ontology, e)) {
                    violations.add(InvalidReferenceViolation.create(axiom, e, Category.DANGLING));
                }
                if (isDeprecated(ontology, e)) {
                    violations.add(InvalidReferenceViolation.create(axiom, e, Category.DEPRECATED));
                }

            }
        
        }
        return violations;
    }
    
    /**
     * @param ontology
     * @param ignoreDangling
     * @return all violations in ontology
     */
    public static Set<InvalidReferenceViolation> getInvalidReferenceViolations(OWLOntology ontology, boolean ignoreDangling) {
        return getInvalidReferenceViolations(ontology, ontology.getAxioms(Imports.INCLUDED), ignoreDangling);
    }
    
    
    /**
     * Checks an import module. If the base ontology refers to deprecated entities in the import module
     * this constitutes a violation
     * 
     * @param importModule
     * @param baseOntology
     * @return all deprecation-reference violations in baseOntology with respect to import module
     */
    public static Set<InvalidReferenceViolation> checkImportModule(OWLOntology importModule, OWLOntology baseOntology) {
        return getInvalidReferenceViolations(importModule, baseOntology.getAxioms(Imports.INCLUDED), true);
    }
 
}

@@ -308,16 +308,73 @@
 LClass;%0A
+import org.semanticweb.owlapi.model.OWLDeclarationAxiom;%0A
 import o
@@ -577,16 +577,243 @@
 s;%0A%0A/**%0A
+ * Checks to determine if axioms contain invalid references: to dangling classes or deprecated classes.%0A * %0A * This is a structural check. To determine the *logical* validity of an axiom reference,%0A * robot uses OWL reasoning.%0A
  * %0A * S
@@ -2084,32 +2084,97 @@
 tity entity)  %7B%0A
+        for (OWLOntology o : ontology.getImportsClosure()) %7B%0A    
         for (OWL
@@ -2199,31 +2199,24 @@
 nAxiom a : o
-ntology
 .getAnnotati
@@ -2249,24 +2249,28 @@
 etIRI())) %7B%0A
+    
             
@@ -2317,24 +2317,28 @@
             
+    
 if (a.getVal
@@ -2390,32 +2390,36 @@
                 
+    
 return true;%0A   
@@ -2423,32 +2423,36 @@
                 
+    
 %7D%0A            %7D%0A
@@ -2441,34 +2441,42 @@
   %7D%0A            
+ 
-%7D%0A
+   %7D%0A    
         %7D%0A      
@@ -2461,32 +2461,42 @@
 %7D%0A            %7D%0A
+        %7D%0A
         return f
@@ -2516,32 +2516,330 @@
   %0A    %0A    /**%0A
+     * Finds axioms that reference a deprecated or dangling entity.%0A     * %0A     * Declaration axioms that reference a deprecated class do not count.%0A     * %0A     * Note that this does not count the value field of an annotation assertion, since these%0A     * reference IRIs and not entities%0A     * %0A
      * @param on
@@ -3441,32 +3441,103 @@
 ontology, e)) %7B%0A
+                    if (!(axiom instanceof OWLDeclarationAxiom)) %7B%0A    
                 
@@ -3617,24 +3617,46 @@
 PRECATED));%0A
+                    %7D%0A
             

check import closure for deprecation axioms