package org.apache.rya.reasoning;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;

/**
 * Contains all the schema information we might need about a property.
 *
 * Rules implemented dynamically by getter methods:
 *
 * scm-op   States that every object property is its own subproperty and
 *          equivalent property.
 * scm-dp   States that every datatype property is its own subproperty and
 *          equivalent property.
 * scm-eqp1 States that if two properties are equivalent, they are also
 *          subproperties. Equivalence is represented this way internally.
 * scm-eqp2 States that if two properties are each other's subproperties,
 *          they are also equivalent properties.
 *
 * Rules implemented explicitly by calling methods once all the necessary data
 * has been read in:
 *
 * scm-spo  States that subPropertyOf is transitive; computed by
 *          computeSuperProperties().
 * scm-dom1 States that a property with domain c also has as domain any
 *          of c's superclasses. Computed in inheritDomainRange().
 * scm-dom2 States that a property inherits its superproperties' domains.
 *          Computed in inheritDomainRange().
 * scm-rng1 States that a property with range c also has as domain any
 *          of c's superclasses. Computed in inheritDomainRange().
 * scm-rng2 States that a property inherits its superproperties' ranges.
 *          Computed in inheritDomainRange().
 * svm-svf1 States that property restriction c1 is a subclass of another c2 if
 *          they are someValuesFrom restrictions on the same property where
 *          c1's target class is a subclass of c2's target class.
 *          Computed in compareRestrictions(), depends on subclass info.
 * svm-avf1 States that property restriction c1 is a subclass of another c2 if
 *          they are allValuesFrom restrictions on the same property where
 *          c1's target class is a subclass of c2's target class.
 *          Computed in compareRestrictions(), depends on subclass info.
 */
public class OwlProperty implements Serializable {
    private static final long serialVersionUID = 1L;

    private IRI uri;

    // Boolean qualities the property might have
    private boolean transitive = false;
    private boolean symmetric = false;
    private boolean asymmetric = false;
    private boolean functional = false;
    private boolean inverseFunctional = false;
    private boolean irreflexive = false;

    // Relations to other properties
    private Set<OwlProperty> superProperties = new HashSet<OwlProperty>();
    private Set<OwlProperty> disjointProperties = new HashSet<OwlProperty>();
    private Set<OwlProperty> inverseProperties = new HashSet<OwlProperty>();

    // Relations to classes
    private Set<OwlClass> domain = new HashSet<OwlClass>();
    private Set<OwlClass> range = new HashSet<OwlClass>();

    // Restrictions on this property
    private Set<OwlClass> restrictions = new HashSet<OwlClass>();

    OwlProperty(IRI uri) {
        this.uri = uri;
    }

    boolean addSuperProperty(OwlProperty p) {
        return superProperties.add(p);
    }

    /**
     * Add an equivalient property
     * RL rule scm-eqp1: Store equivalence as mutual subPropertyOf relations
     */
    boolean addEquivalentProperty(OwlProperty p) {
        boolean change = this.superProperties.add(p);
        change = p.superProperties.add(this) || change;
        return change;
    }

    boolean addDisjoint(OwlProperty p) { return disjointProperties.add(p); }
    boolean addInverse(OwlProperty p) { return inverseProperties.add(p); }
    boolean addDomain(OwlClass c) {
        return domain.add(c);
    }
    boolean addRange(OwlClass c) {
        return range.add(c);
    }
    boolean addRestriction(OwlClass r) { return restrictions.add(r); }

    public void setURI(IRI uri) { this.uri = uri; }
    void setTransitive() { transitive = true; }
    void setSymmetric() { symmetric = true; }
    void setAsymmetric() { asymmetric = true; }
    void setFunctional() { functional = true; }
    void setInverseFunctional() { inverseFunctional = true; }
    void setIrreflexive() { irreflexive = true; }

    public IRI getURI() { return uri; }
    public boolean isTransitive() { return transitive; }
    public boolean isSymmetric() { return symmetric; }
    public boolean isAsymmetric() { return asymmetric; }
    public boolean isFunctional() { return functional; }
    public boolean isInverseFunctional() { return inverseFunctional; }
    public boolean isIrreflexive() { return irreflexive; }

    /**
     * Apply RL rule scm-spo: subPropertyOf transitivity.
     * Follows subPropertyOf chains to compute all the ancestor properties.
     * Assumes the hierarchy is small enough that a simple BFS is fine.
     * @return  Whether new information was discovered
     */
    boolean computeSuperProperties() {
        Set<OwlProperty> ancestors = new HashSet<OwlProperty>();
        Set<OwlProperty> frontier = new HashSet<OwlProperty>(superProperties);
        while (!frontier.isEmpty()) {
            Set<OwlProperty> next = new HashSet<OwlProperty>();
            for (OwlProperty ancestor : frontier) {
                // This node is an ancestor; it's parents should be explored next
                ancestors.add(ancestor);
                next.addAll(ancestor.superProperties);
            }
            // Don't revisit nodes
            next.removeAll(ancestors);
            frontier = next;
        }
        boolean newInfo = !ancestors.equals(superProperties);
        superProperties = ancestors;
        return newInfo;
    }

    /**
     * Infer domain and range from parents' domains and ranges. Only looks at
     * those superproperties that are explicitly known; computeSuperProperties
     * should generally be called first to get the full closure.
     */
    void inheritDomainRange() {
        //RL rule scm-dom2: (p2 domain c) && (p1 subPropertyOf p2) -> (p1 domain c)
        //RL rule scm-rng2: (p2 range c) && (p1 subPropertyOf p2) -> (p1 range c)
        for (OwlProperty ancestorProperty : superProperties) {
            for (OwlClass c : ancestorProperty.domain) {
                addDomain(c);
            }
            for (OwlClass c : ancestorProperty.range) {
                addRange(c);
            }
        }
        //RL rule scm-dom1: (p domain c1) && (c1 subClassOf c2) -> (p domain c2)
        for (OwlClass domainClass : new HashSet<OwlClass>(this.domain)) {
            domainClass.inheritDomains(this);
        }
        //RL rule scm-rng1: (p range c1) && (c1 subClassOf c2) -> (p range c2)
        for (OwlClass rangeClass : new HashSet<OwlClass>(this.range)) {
            rangeClass.inheritRanges(this);
        }
    }

    /**
     * Get all the superproperties of this subproperty.
     */
    public Set<IRI> getSuperProperties() {
        Set<IRI> ancestors = new HashSet<>();
        for (OwlProperty ancestor : superProperties) {
            ancestors.add(ancestor.uri);
        }
        // RL rules scm-op & scm-dp: Every property is a subproperty of itself
        ancestors.add(this.uri);
        return ancestors;
    }

    /**
     * Get all the equivalent properties for this property.
     * Apply RL rules scm-op and scm-dp: Every property is its own equivalent.
     */
    public Set<IRI> getEquivalentProperties() {
        Set<IRI> equivalents = new HashSet<>();
        for (OwlProperty other : superProperties) {
            if (other.superProperties.contains(this)) {
                equivalents.add(other.uri);
            }
        }
        // RL rules scm-op & scm-dp: Every property is equivalent to itself
        equivalents.add(this.uri);
        return equivalents;
    }

    /**
     * Get all properties declared disjoint with this one.
     */
    public Set<IRI> getDisjointProperties() {
        Set<IRI> disjoint = new HashSet<>();
        for (OwlProperty other : disjointProperties) {
            disjoint.add(other.uri);
        }
        return disjoint;
    }

    /**
     * Get all properties declared inverse of this one.
     */
    public Set<IRI> getInverseProperties() {
        Set<IRI> inverse = new HashSet<>();
        for (OwlProperty other : inverseProperties) {
            inverse.add(other.uri);
        }
        return inverse;
    }

    /**
     * Get the domain (set of class URIs/Resources).
     */
    public Set<Resource> getDomain() {
        Set<Resource> domain = new HashSet<>();
        for (OwlClass d : this.domain) {
            domain.add(d.getURI());
        }
        return domain;
    }

    /**
     * Get the range (set of class URIs/Resources).
     */
    public Set<Resource> getRange() {
        Set<Resource> range = new HashSet<>();
        for (OwlClass r : this.range) {
            range.add(r.getURI());
        }
        return range;
    }

    /**
     * Get the property restrictions relevant to this property.
     */
    public Set<Resource> getRestrictions() {
        Set<Resource> restrictions = new HashSet<>();
        for (OwlClass pr : this.restrictions) {
            restrictions.add(pr.getURI());
        }
        return restrictions;
    }

    /**
     * Apply property restriction rules that involve the same property.
     * RL rule scm-svf1: [someValuesFrom sub] subClassOf [someValuesFrom super]
     * RL rule scm-avf1: [allValuesFrom sub] subClassOf [allValuesFrom super]
     * Doesn't check subclass transitivity.
     * @return  Whether any information was generated
     */
    public boolean compareRestrictions() {
        boolean newInfo = false;
        for (OwlClass c1 : restrictions) {
            // Get all superclasses of this restriction's avf target class(es)
            // and avf target classes.
            Set<Resource> avfSuperClasses = c1.getAvfSuperClasses();
            Set<Resource> svfSuperClasses = c1.getSvfSuperClasses();
            if (avfSuperClasses.isEmpty() && svfSuperClasses.isEmpty()) {
                continue;
            }
            // Compare each other restriction's avf and svf targets to the
            // appropriate set of superclasses.
            for (OwlClass c2 : restrictions) {
                //svm-svf1, svm-avf1
                if (c1 != c2) {
                    Set<Resource> avf2 = c2.allValuesFrom();
                    avf2.retainAll(avfSuperClasses);
                    if (avf2.isEmpty()) {
                        Set<Resource> svf2 = c2.someValuesFrom();
                        svf2.retainAll(svfSuperClasses);
                        if (svf2.isEmpty()) {
                            continue;
                        }
                    }
                    // If c2's target is one of the parent classes of c1's
                    // target, then c2 is a more general version of c1 and
                    // therefore a superclass of c1.
                    newInfo = c1.addSuperClass(c2) || newInfo;
                }
            }
        }
        return newInfo;
    }
}
