package org.apache.rya.rdftriplestore.inference;
/*
 * 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.util.Set;
import java.util.UUID;

import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
import org.apache.rya.api.utils.NullableStatementImpl;
import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.Var;

/**
 * Expands the query tree to account for any relevant domain and range information known to the
 * {@link InferenceEngine}.
 *
 * Given a triple <:s :p :o>, if :p has an rdfs:domain of :D and rdfs:range of :R, the semantics of
 * domain and range imply that :s has type :D and that :o has type :R.
 *
 * Only operates on {@link StatementPattern} nodes whose form is <?subject rdfs:type :DefinedClass>.
 * If the class is the domain of any predicate, as reported by the {@link InferenceEngine}, a
 * subtree is constructed to infer the type based on the domain. If the class is the range of any
 * predicate, a subtree is similarly constructed to infer the type based on the range. If one or
 * both apply, then the original node is replaced with the union of the new subtree(s) and the
 * original statement pattern.
 *
 * If there are multiple ways to infer the type for one resource, the resulting query tree will
 * match all of them and produce multiple solutions for that resource.
 */
public class DomainRangeVisitor extends AbstractInferVisitor {
    /**
     * Creates a new {@link DomainRangeVisitor}.
     * @param conf The {@link RdfCloudTripleStoreConfiguration}.
     * @param inferenceEngine The InferenceEngine containing the relevant ontology.
     */
    public DomainRangeVisitor(RdfCloudTripleStoreConfiguration conf, InferenceEngine inferenceEngine) {
        super(conf, inferenceEngine);
        include = conf.isInferDomainRange();
    }

    /**
     * Checks whether this statement pattern might be inferred using domain and/or range knowledge,
     * and, if so, replaces the statement pattern with a union of itself and any possible
     * derivations.
     */
    @Override
    protected void meetSP(StatementPattern node) throws Exception {
        final Var subjVar = node.getSubjectVar();
        final Var predVar = node.getPredicateVar();
        final Var objVar = node.getObjectVar();
        final Var contextVar = node.getContextVar();
        // Only applies to statement patterns that query for members of a defined type.
        if (predVar != null && RDF.TYPE.equals(predVar.getValue())
                && objVar != null && objVar.getValue() instanceof IRI) {
            final IRI inferredType = (IRI) objVar.getValue();
            // Preserve the original node so explicit type assertions are still matched:
            TupleExpr currentNode = node.clone();
            // If there are any properties with this type as domain, check for appropriate triples:
            final Set<IRI> domainProperties = inferenceEngine.getPropertiesWithDomain(inferredType);
            if (!domainProperties.isEmpty()) {
                Var domainPredVar = new Var("p-" + UUID.randomUUID());
                Var domainObjVar = new Var("o-" + UUID.randomUUID());
                domainObjVar.setAnonymous(true);
                Var domainVar = new Var(RDFS.DOMAIN.stringValue(), RDFS.DOMAIN);
                StatementPattern domainSP = new DoNotExpandSP(subjVar, domainPredVar, domainObjVar, contextVar);
                // Enumerate predicates having this type as domain
                FixedStatementPattern domainFSP = new FixedStatementPattern(domainPredVar, domainVar, objVar);
                for (IRI property : domainProperties) {
                    domainFSP.statements.add(new NullableStatementImpl(property, RDFS.DOMAIN, inferredType));
                }
                // For each such predicate, any triple <subjVar predicate _:any> implies the type
                currentNode = new InferUnion(currentNode, new InferJoin(domainFSP, domainSP));
            }
            // If there are any properties with this type as range, check for appropriate triples:
            final Set<IRI> rangeProperties = inferenceEngine.getPropertiesWithRange(inferredType);
            if (!rangeProperties.isEmpty()) {
                Var rangePredVar = new Var("p-" + UUID.randomUUID());
                Var rangeSubjVar = new Var("s-" + UUID.randomUUID());
                rangeSubjVar.setAnonymous(true);
                Var rangeVar = new Var(RDFS.RANGE.stringValue(), RDFS.RANGE);
                StatementPattern rangeSP = new DoNotExpandSP(rangeSubjVar, rangePredVar, subjVar, contextVar);
                // Enumerate predicates having this type as range
                FixedStatementPattern rangeFSP = new FixedStatementPattern(rangePredVar, rangeVar, objVar);
                for (IRI property : rangeProperties) {
                    rangeFSP.statements.add(new NullableStatementImpl(property, RDFS.RANGE, inferredType));
                }
                // For each such predicate, any triple <_:any predicate subjVar> implies the type
                currentNode = new InferUnion(currentNode, new InferJoin(rangeFSP, rangeSP));
            }
            node.replaceWith(currentNode);
        }
    }
}
