All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.topbraid.shacl.rules.TripleRule Maven / Gradle / Ivy

There is a newer version: 1.4.3
Show newest version
/*
 *  Licensed 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.
 *
 *  See the NOTICE file distributed with this work for additional
 *  information regarding copyright ownership.
 */
package org.topbraid.shacl.rules;

import java.util.List;

import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QuerySolutionMap;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.topbraid.jenax.progress.ProgressMonitor;
import org.topbraid.jenax.util.ARQFactory;
import org.topbraid.jenax.util.JenaUtil;
import org.topbraid.shacl.engine.Shape;
import org.topbraid.shacl.expr.AppendContext;
import org.topbraid.shacl.expr.ComplexNodeExpression;
import org.topbraid.shacl.expr.NodeExpression;
import org.topbraid.shacl.expr.NodeExpressionFactory;
import org.topbraid.shacl.vocabulary.SH;

class TripleRule extends Rule {
	
	private static boolean SPARQL_MODE = false;
	
	private NodeExpression object;
	
	private NodeExpression predicate;
	
	private NodeExpression subject;

	
	TripleRule(Resource resource) {
		super(resource);
		this.object = createNodeExpression(resource, SH.object);
		this.predicate = createNodeExpression(resource, SH.predicate);
		this.subject = createNodeExpression(resource, SH.subject);
	}
	
	
	private NodeExpression createNodeExpression(Resource resource, Property predicate) {
		Statement s = resource.getProperty(predicate);
		if(s == null) {
			throw new IllegalArgumentException("Triple rule without " + predicate.getLocalName());
		}
		return NodeExpressionFactory.get().create(s.getObject());
	}


	@Override
	public void execute(RuleEngine ruleEngine, List focusNodes, Shape shape) {
		if(SPARQL_MODE) {
			executeSPARQL(ruleEngine, focusNodes, shape);
		}
		else {
			ProgressMonitor monitor = ruleEngine.getProgressMonitor();
			for(RDFNode focusNode : focusNodes) {
				
				if(monitor != null && monitor.isCanceled()) {
					return;
				}

				List subjects = subject.eval(focusNode, ruleEngine);
				List predicates = predicate.eval(focusNode, ruleEngine);
				List objects = object.eval(focusNode, ruleEngine);
				for(RDFNode subjectR : subjects) {
					if(subjectR.isResource()) {
						Resource subject = (Resource) subjectR;
						for(RDFNode predicateR : predicates) {
							if(predicateR.isURIResource()) {
								Property predicate = JenaUtil.asProperty((Resource)predicateR);
								for(RDFNode object : objects) {
									ruleEngine.infer(Triple.create(subject.asNode(), predicate.asNode(), object.asNode()), this, shape);
								}
							}
						}
					}
				}
			}
		}
	}
	
	
	private void executeSPARQL(RuleEngine ruleEngine, List focusNodes, Shape shape) {
		String queryString = getSPARQL();
		Query query = ARQFactory.get().createQuery(ruleEngine.getDataset().getDefaultModel(), queryString);
		QuerySolutionMap binding = new QuerySolutionMap();
		for(RDFNode focusNode : focusNodes) {
			binding.add(SH.thisVar.getVarName(), focusNode);
			Model c;
			try ( QueryExecution qexec = ARQFactory.get().createQueryExecution(query, ruleEngine.getDataset(), binding) ) {
			    c = qexec.execConstruct();
			}
			for(Triple triple : c.getGraph().find(Node.ANY, Node.ANY, Node.ANY).toList()) {
			    ruleEngine.infer(triple, this, shape);
			}
		}
	}


	private String getSPARQL() {
		String label;
		StringBuffer sb = new StringBuffer();
		AppendContext context = new AppendContext(sb);
		sb.append("\nCONSTRUCT {\n");
		sb.append("    ");
		if(subject instanceof ComplexNodeExpression) {
			sb.append("?subject");
		}
		else {
			sb.append(subject);
		}
		sb.append(" ");
		if(predicate instanceof ComplexNodeExpression) {
			sb.append("?predicate");
		}
		else {
			sb.append(predicate);
		}
		sb.append(" ");
		if(object instanceof ComplexNodeExpression) {
			sb.append("?object");
		}
		else {
			sb.append(object);
		}
		sb.append(" .\n}\nWHERE {\n");
		context.increaseIndent();
		if(subject instanceof ComplexNodeExpression) {
			((ComplexNodeExpression)subject).appendLabel(context, "subject");
		}
		if(predicate instanceof ComplexNodeExpression) {
			((ComplexNodeExpression)predicate).appendLabel(context, "predicate");
		}
		if(object instanceof ComplexNodeExpression) {
			((ComplexNodeExpression)object).appendLabel(context, "object");
		}
		context.decreaseIndent();
		sb.append("}");
		label = sb.toString();
		return label;
	}
	
	
	@Override
    public String toString() {
		String label = getLabel();
		if(label == null) {
			label = getSPARQL();
		}
		return getLabelStart("Triple") + label;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy