blob: 43eae4af43ad3694f03f59aeeeca505f02a83256 [file] [log] [blame]
/*
* 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.
*/
package org.apache.rya.rdftriplestore.inference;
import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.algebra.Extension;
import org.eclipse.rdf4j.query.algebra.ExtensionElem;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.Var;
/**
* Expands the query tree to account for any relevant has-self class expressions
* in the ontology known to the {@link InferenceEngine}.
*
* Only operates on {@link StatementPattern} nodes, and only those including a
* defined type or defined predicate which is relevant to a has-self expression
* in the ontology. When applicable, replaces the node with one or more
* {@link InferUnion}s, one of whose leaves is the original StatementPattern.
*
* A has-self restriction defines the set of resources that are connected to
* themselves by a property. If the ontology states that a type is a resource
* that has a self referencing property, then the inference engine should:
* <li>1. Rewrite queries of the from ?x rdf:type :T to find all resources
* matching ?x :P ?x (as well as anything explicitly stated to be of type :T)
* </li>
* <li>2. Rewrite queries of the from :CONST :P ?o or ?subj :P :CONST to match
* :CONST if :CONST is known to have the type :T
* </li>
*/
public class HasSelfVisitor extends AbstractInferVisitor {
private static final Var TYPE_VAR = new Var(RDF.TYPE.stringValue(), RDF.TYPE);
/**
* Creates a new {@link HasSelfVisitor}.
* @param conf The {@link RdfCloudTripleStoreConfiguration}.
* @param inferenceEngine The InferenceEngine containing the relevant ontology.
*/
public HasSelfVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
super(conf, inferenceEngine);
include = conf.isInferHasSelf();
}
@Override
protected void meetSP(final StatementPattern node) throws Exception {
final IRI pred = (IRI) node.getPredicateVar().getValue();
final Var obj = node.getObjectVar();
//if originalSP like (?s rdf:type :C1): require that C1 is defined, i.e. not a variable
// node <- originalSP
final StatementPattern clone = node.clone();
if (RDF.TYPE.equals(pred) && obj.isConstant()) {
//for property in getHasSelfImplyingType(C1):
if (obj.getValue() instanceof IRI) {
for (final IRI property : inferenceEngine.getHasSelfImplyingType((IRI) obj.getValue())) {
//node <- InferUnion(node, StatementPattern(?s, property, ?s)).
final InferUnion union = new InferUnion(clone,
new StatementPattern(clone.getSubjectVar(),
new Var(property.stringValue(), property),
clone.getSubjectVar()));
//originalSP.replaceWith(node)
node.replaceWith(union);
}
}
//else if originalSP like (s :p o): where p is not a variable and at least one of s and o are variables
} else if (node.getPredicateVar().isConstant()
&& (!node.getSubjectVar().isConstant() ||
!node.getObjectVar().isConstant())) {
//for type in getHasSelfImplyingProperty(p):
for (final Resource type : inferenceEngine.getHasSelfImplyingProperty(pred)) {
final Extension extension;
if(obj.isConstant()) { // subject is the variable
//Extension(StatementPattern(o, rdf:type, type), ExtensionElem(o, "s"))
extension = new Extension(
new StatementPattern(obj, TYPE_VAR, new Var(type.stringValue(), type)),
new ExtensionElem(obj, node.getSubjectVar().getName()));
} else { //o is a variable and s may either be defined or a variable
//Extension(StatementPattern(s, rdf:type, type), ExtensionElem(s, "o"))
extension = new Extension(
new StatementPattern(node.getSubjectVar(), TYPE_VAR, new Var(type.stringValue(), type)),
new ExtensionElem(node.getSubjectVar(), obj.getName()));
}
// node <- InferUnion(node, newNode)
final InferUnion union = new InferUnion(extension, clone);
node.replaceWith(union);
}
}
}
}