KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > rulesys > FBRuleReasoner


1 /******************************************************************
2  * File: FBRuleReasoner.java
3  * Created by: Dave Reynolds
4  * Created on: 29-May-2003
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * [See end of file]
8  * $Id: FBRuleReasoner.java,v 1.19 2005/04/08 16:37:51 der Exp $
9  *****************************************************************/

10 package com.hp.hpl.jena.reasoner.rulesys;
11
12 import com.hp.hpl.jena.rdf.model.*;
13 import com.hp.hpl.jena.reasoner.*;
14 import com.hp.hpl.jena.shared.WrappedIOException;
15 import com.hp.hpl.jena.vocabulary.ReasonerVocabulary;
16 import com.hp.hpl.jena.graph.*;
17
18 import java.util.*;
19
20 /**
21  * Rule-based reasoner interface. This is the default rule reasoner to use.
22  * It supports both forward reasoning and backward reasoning, including use
23  * of forward rules to generate and instantiate backward rules.
24  *
25  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
26  * @version $Revision: 1.19 $ on $Date: 2005/04/08 16:37:51 $
27  */

28 public class FBRuleReasoner implements RuleReasoner {
29     
30     /** The parent reasoner factory which is consulted to answer capability questions */
31     protected ReasonerFactory factory;
32
33     /** The rules to be used by this instance of the forward engine */
34     protected List rules = new ArrayList();
35     
36     /** A precomputed set of schema deductions */
37     protected Graph schemaGraph;
38     
39     /** Flag to set whether the inference class should record derivations */
40     protected boolean recordDerivations = false;
41
42     /** Flag which, if true, enables tracing of rule actions to logger.info */
43     boolean traceOn = false;
44 // boolean traceOn = true;
45

46     /** Flag, if true we cache the closure of the pure rule set with its axioms */
47     protected static final boolean cachePreload = true;
48     
49     /** The cached empty closure, if wanted */
50     protected InfGraph preload;
51     
52     /** The original configuration properties, if any */
53     protected Resource configuration;
54     
55     /** The graph capabilities of the infgraphs generated by this reasoner */
56     protected Capabilities capabilities;
57      
58     /**
59      * Constructor. This is the raw version that does not reference a ReasonerFactory
60      * and so has no capabilities description.
61      * @param rules a list of Rule instances which defines the ruleset to process
62      */

63     public FBRuleReasoner(List rules) {
64         if (rules == null) throw new NullPointerException JavaDoc( "null rules" );
65         this.rules = rules;
66     }
67     
68     /**
69      * Constructor
70      * @param factory the parent reasoner factory which is consulted to answer capability questions
71      */

72     public FBRuleReasoner(ReasonerFactory factory) {
73         this( new ArrayList(), factory);
74     }
75    
76     /**
77      * Constructor
78      * @param factory the parent reasoner factory which is consulted to answer capability questions
79      * @param configuration RDF node to configure the rule set and mode, can be null
80      */

81     public FBRuleReasoner(ReasonerFactory factory, Resource configuration) {
82         this( new ArrayList(), factory);
83         this.configuration = configuration;
84         if (configuration != null) loadConfiguration( configuration );
85     }
86    
87     /**
88          load the configuration from the configuring Resource (in its Model).
89     */

90     protected void loadConfiguration( Resource configuration )
91         {
92         StmtIterator i = configuration.listProperties();
93         while (i.hasNext()) {
94             Statement st = i.nextStatement();
95             doSetRDFNodeParameter( st.getPredicate(), st.getObject() );
96         }
97         }
98
99     /**
100      * Constructor
101      * @param rules a list of Rule instances which defines the ruleset to process
102      * @param factory the parent reasoner factory which is consulted to answer capability questions
103      */

104     public FBRuleReasoner(List rules, ReasonerFactory factory) {
105         this(rules);
106         this.factory = factory;
107     }
108     
109     /**
110      * Internal constructor, used to generated a partial binding of a schema
111      * to a rule reasoner instance.
112      */

113     protected FBRuleReasoner(List rules, Graph schemaGraph, ReasonerFactory factory) {
114         this(rules, factory);
115         this.schemaGraph = schemaGraph;
116     }
117
118     /**
119          Add the given rules to the current set and answer this Reasoner. Provided
120          so that the Factory can deal out reasoners with specified rulesets.
121          There may well be a better way to arrange this.
122          TODO review & revise
123     */

124     public FBRuleReasoner addRules(List rules) {
125         List combined = new ArrayList( this.rules );
126         combined.addAll( rules );
127         setRules( combined );
128         return this;
129         }
130
131     /**
132      * Return a description of the capabilities of this reasoner encoded in
133      * RDF. These capabilities may be static or may depend on configuration
134      * information supplied at construction time. May be null if there are
135      * no useful capabilities registered.
136      */

137     public Model getReasonerCapabilities() {
138         if (factory != null) {
139             return factory.getCapabilities();
140         } else {
141             return null;
142         }
143     }
144     
145     /**
146      * Add a configuration description for this reasoner into a partial
147      * configuration specification model.
148      * @param configSpec a Model into which the configuration information should be placed
149      * @param base the Resource to which the configuration parameters should be added.
150      */

151     public void addDescription(Model configSpec, Resource base) {
152         if (configuration != null) {
153             StmtIterator i = configuration.listProperties();
154             while (i.hasNext()) {
155                 Statement st = i.nextStatement();
156                 configSpec.add(base, st.getPredicate(), st.getObject());
157             }
158         }
159     }
160
161     /**
162      * Determine whether the given property is recognized and treated specially
163      * by this reasoner. This is a convenience packaging of a special case of getCapabilities.
164      * @param property the property which we want to ask the reasoner about, given as a Node since
165      * this is part of the SPI rather than API
166      * @return true if the given property is handled specially by the reasoner.
167      */

168     public boolean supportsProperty(Property property) {
169         if (factory == null) return false;
170         Model caps = factory.getCapabilities();
171         Resource root = caps.getResource(factory.getURI());
172         return caps.contains(root, ReasonerVocabulary.supportsP, property);
173     }
174     
175     /**
176      * Precompute the implications of a schema graph. The statements in the graph
177      * will be combined with the data when the final InfGraph is created.
178      */

179     public Reasoner bindSchema(Graph tbox) throws ReasonerException {
180         if (schemaGraph != null) {
181             throw new ReasonerException("Can only bind one schema at a time to an OWLRuleReasoner");
182         }
183         FBRuleInfGraph graph = new FBRuleInfGraph(this, rules, getPreload(), tbox);
184         graph.prepare();
185         FBRuleReasoner fbr = new FBRuleReasoner(rules, graph, factory);
186         fbr.setDerivationLogging(recordDerivations);
187         fbr.setTraceOn(traceOn);
188         return fbr;
189     }
190     
191     /**
192      * Precompute the implications of a schema Model. The statements in the graph
193      * will be combined with the data when the final InfGraph is created.
194      */

195     public Reasoner bindSchema(Model tbox) throws ReasonerException {
196         return bindSchema(tbox.getGraph());
197     }
198     
199     /**
200      * Attach the reasoner to a set of RDF data to process.
201      * The reasoner may already have been bound to specific rules or ontology
202      * axioms (encoded in RDF) through earlier bindRuleset calls.
203      *
204      * @param data the RDF data to be processed, some reasoners may restrict
205      * the range of RDF which is legal here (e.g. syntactic restrictions in OWL).
206      * @return an inference graph through which the data+reasoner can be queried.
207      * @throws ReasonerException if the data is ill-formed according to the
208      * constraints imposed by this reasoner.
209      */

210     public InfGraph bind(Graph data) throws ReasonerException {
211         Graph schemaArg = schemaGraph == null ? getPreload() : (FBRuleInfGraph)schemaGraph;
212         FBRuleInfGraph graph = new FBRuleInfGraph(this, rules, schemaArg);
213         graph.setDerivationLogging(recordDerivations);
214         graph.setTraceOn(traceOn);
215         graph.rebind(data);
216         return graph;
217     }
218     
219     /**
220      * Set (or change) the rule set that this reasoner should execute.
221      * @param rules a list of Rule objects
222      */

223     public void setRules(List rules) {
224         this.rules = rules;
225         preload = null;
226     }
227     
228     /**
229      * Return the list of Rules used by this reasoner
230      * @return a List of Rule objects
231      */

232     public List getRules() {
233         return rules;
234     }
235     
236     /**
237          Answer the list of rules loaded from the given filename. May throw a
238          ReasonerException wrapping an IOException.
239     */

240     public static List loadRules( String JavaDoc fileName ) {
241         try
242             { return Rule.parseRules(Util.loadRuleParserFromResourceFile( fileName ) ); }
243         catch (WrappedIOException e)
244             { throw new ReasonerException("Can't load rules file: " + fileName, e.getCause() ); }
245     }
246     
247     /**
248      * Register an RDF predicate as one whose presence in a goal should force
249      * the goal to be tabled. This is better done directly in the rule set.
250      */

251     public synchronized void tablePredicate(Node predicate) {
252         // Create a dummy rule which tables the predicate ...
253
Rule tablePredicateRule = new Rule("",
254                 new ClauseEntry[]{
255                     new Functor("table", new Node[] { predicate })
256                 },
257                 new ClauseEntry[]{});
258         // ... end append the rule to the ruleset
259
rules.add(tablePredicateRule);
260     }
261     
262     /**
263      * Get the single static precomputed rule closure.
264      */

265     protected synchronized InfGraph getPreload() {
266         if (cachePreload && preload == null) {
267             preload = (new FBRuleInfGraph(this, rules, null));
268             preload.prepare();
269         }
270         return preload;
271     }
272        
273     /**
274      * Switch on/off drivation logging.
275      * If set to true then the InfGraph created from the bind operation will start
276      * life with recording of derivations switched on. This is currently only of relevance
277      * to rule-based reasoners.
278      * <p>
279      * Default - false.
280      */

281     public void setDerivationLogging(boolean logOn) {
282         recordDerivations = logOn;
283     }
284     
285     /**
286      * Set the state of the trace flag. If set to true then rule firings
287      * are logged out to the Log at "INFO" level.
288      */

289     public void setTraceOn(boolean state) {
290         traceOn = state;
291     }
292     
293     /**
294      * Return the state of the trace flag.If set to true then rule firings
295      * are logged out to the Log at "INFO" level.
296      */

297     public boolean isTraceOn() {
298         return traceOn;
299     }
300
301     /**
302      * Set a configuration parameter for the reasoner. The supported parameters
303      * are:
304      * <ul>
305      * <li>PROPderivationLogging - set to true to enable recording all rule derivations</li>
306      * <li>PROPtraceOn - set to true to enable verbose trace information to be sent to the logger INFO channel</li>
307      * </ul>
308      *
309      * @param parameter the property identifying the parameter to be changed
310      * @param value the new value for the parameter, typically this is a wrapped
311      * java object like Boolean or Integer.
312      * @throws IllegalParameterException if the parameter is unknown
313      */

314     public void setParameter(Property parameter, Object JavaDoc value) {
315         if (!doSetParameter(parameter, value)) {
316             throw new IllegalParameterException("RuleReasoner does not recognize configuration parameter " + parameter);
317         } else {
318             // Record the configuration change
319
if (configuration == null) {
320                 Model configModel = ModelFactory.createDefaultModel();
321                 configuration = configModel.createResource();
322             }
323             Util.updateParameter(configuration, parameter, value);
324         }
325     }
326
327     /**
328          Set a parameter from a statement, given the property and its RDFNode value.
329          Most parameters are, historically, set from the string value of the RDFNode,
330          but newer parameters may have Resource values with embedded models,
331          for which their toString() is not just suspect, but definitively wrong. Hence the
332          introduction of this relay station.
333          
334          @param parameter the propoerty naming the value to set
335          @param value the RDFNode with the value of that property
336          @return true if the property was understood, false otherwise
337     */

338     protected boolean doSetRDFNodeParameter( Property parameter, RDFNode value )
339         {
340         return
341             (value instanceof Resource && doSetResourceParameter( parameter, (Resource) value ))
342             || doSetParameter( parameter, value.toString() )
343             ;
344         }
345     
346     /**
347          Set a parameter with a Resource value. Answer false if the parameter is not
348          understood. Default understands no parameters; subclasses may override.
349     */

350     protected boolean doSetResourceParameter( Property parameter, Resource value )
351         { return false; }
352     
353     /**
354      * Set a configuration parameter for the reasoner. The supported parameters
355      * are:
356      * <ul>
357      * <li>PROPderivationLogging - set to true to enable recording all rule derivations</li>
358      * <li>PROPtraceOn - set to true to enable verbose trace information to be sent to the logger INFO channel</li>
359      * </ul>
360      * @param parameter the property identifying the parameter to be changed
361      * @param value the new value for the parameter, typically this is a wrapped
362      * java object like Boolean or Integer.
363      * @return false if the parameter was not known
364      */

365     protected boolean doSetParameter(Property parameter, Object JavaDoc value) {
366         if (parameter.equals(ReasonerVocabulary.PROPderivationLogging)) {
367             recordDerivations = Util.convertBooleanPredicateArg(parameter, value);
368             return true;
369         } else if (parameter.equals(ReasonerVocabulary.PROPtraceOn)) {
370             traceOn = Util.convertBooleanPredicateArg(parameter, value);
371             return true;
372         } else {
373             return false;
374         }
375     }
376
377     /**
378      * Return the Jena Graph Capabilties that the inference graphs generated
379      * by this reasoner are expected to conform to.
380      */

381     public Capabilities getGraphCapabilities() {
382         if (capabilities == null) {
383             capabilities = new BaseInfGraph.InfCapabilities();
384         }
385         return capabilities;
386     }
387
388 }
389
390
391 /*
392     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
393     All rights reserved.
394
395     Redistribution and use in source and binary forms, with or without
396     modification, are permitted provided that the following conditions
397     are met:
398
399     1. Redistributions of source code must retain the above copyright
400        notice, this list of conditions and the following disclaimer.
401
402     2. Redistributions in binary form must reproduce the above copyright
403        notice, this list of conditions and the following disclaimer in the
404        documentation and/or other materials provided with the distribution.
405
406     3. The name of the author may not be used to endorse or promote products
407        derived from this software without specific prior written permission.
408
409     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
410     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
411     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
412     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
413     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
414     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
415     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
416     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
417     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
418     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
419 */
Popular Tags