| /* |
| * 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.jena.reasoner.rulesys; |
| |
| import java.util.*; |
| |
| import org.apache.jena.graph.* ; |
| import org.apache.jena.rdf.model.* ; |
| import org.apache.jena.reasoner.* ; |
| import org.apache.jena.reasoner.rulesys.impl.RDFSCMPPreprocessHook ; |
| import org.apache.jena.vocabulary.ReasonerVocabulary ; |
| |
| /** |
| * A full implementation of RDFS reasoning using a hybrid rule system, together |
| * with optimized subclass/subproperty closure using the transitive graph caches. |
| * Implements the container membership property rules using an optional |
| * data scanning hook. Implements datatype range validation. |
| */ |
| public class RDFSRuleReasoner extends GenericRuleReasoner { |
| |
| /** Constant: used to indicate default RDFS processing level */ |
| public static final String DEFAULT_RULES = "default"; |
| |
| /** Constant: used to indicate full RDFS processing level */ |
| public static final String FULL_RULES = "full"; |
| |
| /** Constant: used to indicate minimal RDFS processing level */ |
| public static final String SIMPLE_RULES = "simple"; |
| |
| /** The location of the default RDFS rule definitions on the class path */ |
| protected static final String RULE_FILE = "etc/rdfs-fb-tgc-noresource.rules"; |
| |
| /** The location of the full RDFS rule definitions on the class path */ |
| protected static final String FULL_RULE_FILE = "etc/rdfs-fb-tgc.rules"; |
| |
| /** The location of the simple RDFS rule definitions on the class path */ |
| protected static final String SIMPLE_RULE_FILE = "etc/rdfs-fb-tgc-simple.rules"; |
| |
| /** The cached rule sets, indexed by processing level */ |
| protected static Map<String, List<Rule>> ruleSets = new HashMap<>(); |
| |
| /** The rule file names, indexed by processing level */ |
| protected static Map<String, String> ruleFiles = Map.of |
| (DEFAULT_RULES, RULE_FILE, |
| FULL_RULES, FULL_RULE_FILE, |
| SIMPLE_RULES, SIMPLE_RULE_FILE); |
| |
| /** The (stateless) preprocessor for container membership properties */ |
| protected static RulePreprocessHook cmpProcessor = new RDFSCMPPreprocessHook(); |
| |
| /** |
| * Constructor |
| */ |
| public RDFSRuleReasoner( ReasonerFactory parent ) { |
| super(loadRulesLevel(DEFAULT_RULES), parent); |
| setMode(HYBRID); |
| setTransitiveClosureCaching(true); |
| //addPreprocessingHook(new RDFSCMPPreprocessHook()); |
| } |
| |
| /** |
| * Constructor |
| * @param factory the parent reasoner factory which is consulted to answer capability questions |
| * @param configuration RDF information to configure the rule set and mode, can be null |
| */ |
| public RDFSRuleReasoner(ReasonerFactory factory, Resource configuration) { |
| this(factory); |
| if (configuration != null) { |
| StmtIterator i = configuration.listProperties(); |
| while (i.hasNext()) { |
| Statement st = i.nextStatement(); |
| doSetParameter(st.getPredicate(), st.getObject()); |
| } |
| } |
| } |
| |
| /** |
| * Internal constructor, used to generated a partial binding of a schema |
| * to a rule reasoner instance. |
| */ |
| protected RDFSRuleReasoner(FBRuleInfGraph schemaGraph, ReasonerFactory factory) { |
| super(schemaGraph.getRules(), factory); |
| this.schemaGraph = schemaGraph; |
| } |
| |
| /** |
| * Internal version of setParameter that does not directly raise an |
| * exception on parameters it does not recognize. |
| * @return false if the parameter was not recognized |
| */ |
| @Override |
| protected boolean doSetParameter(Property parameter, Object value) { |
| if ( value instanceof Literal ) |
| // Without risk of quoting |
| value = ((Literal)value).getString(); |
| |
| if (parameter.equals(ReasonerVocabulary.PROPenableCMPScan)) { |
| boolean scanProperties = Util.convertBooleanPredicateArg(parameter, value); |
| if (scanProperties) { |
| addPreprocessingHook(cmpProcessor); |
| } else { |
| removePreprocessingHook(cmpProcessor); |
| } |
| return true; |
| } else if (parameter.equals(ReasonerVocabulary.PROPsetRDFSLevel)) { |
| String level = ((String)value).toLowerCase(); |
| setRules(loadRulesLevel(level)); |
| if (level.equals(FULL_RULES)) { |
| addPreprocessingHook(cmpProcessor); |
| } else { |
| removePreprocessingHook(cmpProcessor); |
| } |
| return true; |
| } else { |
| return super.doSetParameter(parameter, value); |
| } |
| } |
| |
| /** |
| * Attach the reasoner to a set of RDF data to process. |
| * The reasoner may already have been bound to specific rules or ontology |
| * axioms (encoded in RDF) through earlier bindRuleset calls. |
| * |
| * @param data the RDF data to be processed, some reasoners may restrict |
| * the range of RDF which is legal here (e.g. syntactic restrictions in OWL). |
| * @return an inference graph through which the data+reasoner can be queried. |
| * @throws ReasonerException if the data is ill-formed according to the |
| * constraints imposed by this reasoner. |
| */ |
| @Override |
| public InfGraph bind(Graph data) throws ReasonerException { |
| Graph schemaArg = schemaGraph == null ? getPreload() : schemaGraph; |
| InfGraph graph = null; |
| List<Rule> ruleSet = ((FBRuleInfGraph)schemaArg).getRules(); |
| FBRuleInfGraph fbgraph = new RDFSRuleInfGraph(this, ruleSet, schemaArg); |
| graph = fbgraph; |
| if (enableTGCCaching) fbgraph.setUseTGCCache(); |
| fbgraph.setTraceOn(traceOn); |
| if (preprocessorHooks!= null) { |
| for (RulePreprocessHook rulePreprocessHook : preprocessorHooks) |
| { |
| fbgraph.addPreprocessingHook(rulePreprocessHook); |
| } |
| } |
| graph.setDerivationLogging(recordDerivations); |
| graph.rebind(data); |
| return graph; |
| } |
| |
| /** |
| * Precompute the implications of a schema graph. The statements in the graph |
| * will be combined with the data when the final InfGraph is created. |
| */ |
| @Override |
| public Reasoner bindSchema(Graph tbox) throws ReasonerException { |
| if (schemaGraph != null) { |
| throw new ReasonerException("Can only bind one schema at a time to an RDFSRuleReasoner"); |
| } |
| FBRuleInfGraph graph = new FBRuleInfGraph(this, rules, getPreload(), tbox); |
| if (enableTGCCaching) (graph).setUseTGCCache(); |
| graph.prepare(); |
| RDFSRuleReasoner grr = new RDFSRuleReasoner(graph, factory); |
| grr.setDerivationLogging(recordDerivations); |
| grr.setTraceOn(traceOn); |
| grr.setTransitiveClosureCaching(enableTGCCaching); |
| grr.setFunctorFiltering(filterFunctors); |
| if (preprocessorHooks != null) { |
| for (RulePreprocessHook rulePreprocessHook : preprocessorHooks) |
| { |
| grr.addPreprocessingHook(rulePreprocessHook); |
| } |
| } |
| return grr; |
| } |
| |
| /** |
| * Return the RDFS rule set, loading it in if necessary. |
| * @param level a string defining the processing level required |
| */ |
| public static List<Rule> loadRulesLevel(String level) { |
| List<Rule> ruleSet = ruleSets.get(level); |
| if (ruleSet == null) { |
| String file = ruleFiles.get(level); |
| if (file == null) { |
| throw new ReasonerException("Illegal RDFS conformance level: " + level); |
| } |
| ruleSet = loadRules( file ); |
| ruleSets.put(level, ruleSet); |
| } |
| return ruleSet; |
| } |
| |
| /** |
| * Return the Jena Graph Capabilities that the inference graphs generated |
| * by this reasoner are expected to conform to. |
| */ |
| @Override |
| public Capabilities getGraphCapabilities() { |
| return BaseInfGraph.reasonerInfCapabilities; |
| } |
| |
| } |