/* * 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.test; import static org.apache.jena.reasoner.rulesys.Rule.parseRule; import java.util.ArrayList ; import java.util.HashSet ; import java.util.List ; import java.util.Set ; import org.apache.jena.assembler.test.AssemblerTestBase ; import org.apache.jena.graph.Node; import org.apache.jena.rdf.model.InfModel ; import org.apache.jena.rdf.model.Model ; import org.apache.jena.rdf.model.ModelFactory ; import org.apache.jena.rdf.model.Resource ; import org.apache.jena.reasoner.rulesys.* ; import org.apache.jena.reasoner.rulesys.builtins.BaseBuiltin; import org.apache.jena.vocabulary.RDF; import org.apache.jena.vocabulary.ReasonerVocabulary ; /** Your eyes will bleed with the number of backslashes required in the substitute strings. */ public class TestGenericRuleReasonerConfig extends AssemblerTestBase { public TestGenericRuleReasonerConfig( String name ) { super( name ); } @Override protected Model setRequiredPrefixes( Model x ) { x.setNsPrefix( "jr", ReasonerVocabulary.JenaReasonerNS ); return super.setRequiredPrefixes( x ); } public void testLoadsSingleRuleSetViaURL() { // testLoadsSingleRuleViaURL( "jms" ); testLoadsSingleRuleViaURL( "jr" ); } private void testLoadsSingleRuleViaURL( String ns ) { String where = "file:testing/modelspecs/example.rules"; Resource r = resourceInModel( "x <ns>:ruleSetURL <where>".replaceAll( "<ns>", ns ).replaceAll( "<where>", where ) ); List<Rule> rules = Rule.rulesFromURL( where ); GenericRuleReasoner grr = new GenericRuleReasoner( null, r ); assertEquals( rules, grr.getRules() ); } public void testLoadsSingleRuleFromString() { // testLoadsSingleRuleFromString( "jms" ); testLoadsSingleRuleFromString( "jr" ); } private void testLoadsSingleRuleFromString( String ns ) { String rule = "[R: (?x rdf:type eg:Thing) -> (?x eg:thing true)]"; List<Rule> rules = Rule.parseRules( rule ); Resource r = resourceInModel( "x <ns>:hasRule '<it>'".replaceAll( "<ns>", ns ).replaceAll( "<it>", rule.replaceAll( " ", "\\\\\\\\s" ) ) ); GenericRuleReasoner grr = new GenericRuleReasoner( null, r ); assertEquals( rules, grr.getRules() ); } public void testLoadsSingleRuleViaRuleSetStringString() { // testLoadsRulesViaRuleSetStrings( "jms" ); testLoadsRulesViaRuleSetStrings( "jr" ); } private void testLoadsRulesViaRuleSetStrings( String ns ) { String ruleA = "[R: (?x rdf:type eg:Thing) -> (?x eg:thing true)]"; String ruleB = "[S: (?x rdf:type eg:Thung) -> (?x eg:thing false)]"; Set<Rule> rules = rulesFromTwoStrings( ruleA, ruleB ); String modelString = "x <ns>:ruleSet _x; _x <ns>:hasRule '<A>'; _x <ns>:hasRule '<B>'" .replaceAll( "<ns>", ns ) .replaceAll( "<A>", ruleA.replaceAll( " ", "\\\\\\\\s" ) ) .replaceAll( "<B>", ruleB.replaceAll( " ", "\\\\\\\\s" ) ) ; Resource r = resourceInModel( modelString ); GenericRuleReasoner grr = new GenericRuleReasoner( null, r ); assertEquals( rules, new HashSet<>( grr.getRules() ) ); } public void testLoadsMultipleRuleSetsViaRuleSetNode() { // testLoadsMultipleRuleSetsViaRuleSetNode( "jms" ); testLoadsMultipleRuleSetsViaRuleSetNode( "jr" ); } private void testLoadsMultipleRuleSetsViaRuleSetNode( String ns ) { String whereA = "file:testing/modelspecs/example.rules"; String whereB = "file:testing/modelspecs/extra.rules"; Resource r = resourceInModel( "x <ns>:ruleSet _a; _a <ns>:ruleSetURL <whereA>; _a <ns>:ruleSetURL <whereB>".replaceAll( "<ns>", ns ).replaceAll( "<whereA>", whereA ).replaceAll( "<whereB>", whereB ) ); GenericRuleReasoner grr = new GenericRuleReasoner( null, r ); assertEquals( rulesFromTwoPlaces( whereA, whereB ), new HashSet<>( grr.getRules() ) ); } private Set<Rule> rulesFromTwoStrings( String ruleA, String ruleB ) { Set<Rule> rules = new HashSet<>( Rule.parseRules( ruleA ) ); rules.addAll( Rule.parseRules( ruleB ) ); return rules; } private Set<Rule> rulesFromTwoPlaces( String whereA, String whereB ) { Set<Rule> rules = new HashSet<>(); rules.addAll( Rule.rulesFromURL( whereA ) ); rules.addAll( Rule.rulesFromURL( whereB ) ); return rules; } public void testRuleLoadingWithOverridenBuiltins() { List<Node> savedNode=new ArrayList<>(); Builtin b= new BaseBuiltin() { @Override public String getName() { return "groo"; } @Override public int getArgLength() { return 1; } @Override public void headAction(Node[] args, int length, RuleContext context) { savedNode.add(getArg(0,args,context)); } }; BuiltinRegistry r=new OverrideBuiltinRegistry(BuiltinRegistry.theRegistry); r.register(b); assertEquals(b,r.getImplementation("groo")); List<Rule> rules=new ArrayList<>(); // // note that the head action does not appear to fire unless we put a triple in the head as well.. is // this expected? // rules.add(parseRule("[ (?instance rdf:type ?type) -> groo(?type) ]",r)); GenericRuleReasoner article=new GenericRuleReasoner(rules); article.setMode(GenericRuleReasoner.FORWARD_RETE); Model input=ModelFactory.createDefaultModel(); input.add(input.createResource(), RDF.type,input.createResource("http://example.com/Renegade")); InfModel output=ModelFactory.createInfModel(article,input); output.size(); // not optional, inferences are not run if we don't trigger them assertEquals(1,savedNode.size()); assertEquals("http://example.com/Renegade",savedNode.get(0).getURI()); } }