001: /*****************************************************************************
002: * Source code information
003: * -----------------------
004: * Original author Ian Dickinson, HP Labs Bristol
005: * Author email Ian.Dickinson@hp.com
006: * Package Jena 2
007: * Web http://sourceforge.net/projects/jena/
008: * Created July 19th 2003
009: * Filename $RCSfile: DIGReasoner.java,v $
010: * Revision $Revision: 1.12 $
011: * Release status $State: Exp $
012: *
013: * Last modified on $Date: 2008/01/02 12:07:09 $
014: * by $Author: andy_seaborne $
015: *
016: * (c) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
017: * [See end of file]
018: * ****************************************************************************/package com.hp.hpl.jena.reasoner.dig;
019:
020: // Imports
021: ///////////////
022: import java.io.*;
023:
024: import org.apache.commons.logging.LogFactory;
025:
026: import com.hp.hpl.jena.graph.*;
027: import com.hp.hpl.jena.ontology.*;
028: import com.hp.hpl.jena.ontology.OntModelSpec;
029: import com.hp.hpl.jena.rdf.model.*;
030: import com.hp.hpl.jena.reasoner.*;
031: import com.hp.hpl.jena.reasoner.rulesys.Util;
032: import com.hp.hpl.jena.util.FileUtils;
033: import com.hp.hpl.jena.vocabulary.ReasonerVocabulary;
034:
035: /**
036: * <p>
037: * This reasoner is the generator of inf-graphs that can use an external DIG inference engine
038: * to perform DL reasoning tasks.
039: * </p>
040: *
041: * @author Ian Dickinson, HP Labs (<a href="mailto:Ian.Dickinson@hp.com">email</a>)
042: * @version Release @release@ ($Id: DIGReasoner.java,v 1.12 2008/01/02 12:07:09 andy_seaborne Exp $)
043: */
044: public class DIGReasoner implements Reasoner {
045:
046: // Constants
047: //////////////////////////////////
048:
049: // Static variables
050: //////////////////////////////////
051:
052: /** The graph capabilities of the infgraphs generated by this reasoner */
053: protected Capabilities capabilities;
054:
055: // Instance variables
056: //////////////////////////////////
057:
058: /** A graph that contains ontology definition data (tbox) */
059: protected Graph m_tbox;
060:
061: /** Reference to the factory that created this reasoner */
062: protected ReasonerFactory m_factory;
063:
064: /** The original configuration properties, if any */
065: protected Resource m_configuration;
066:
067: /** The URL to use to connect to the external reasoner */
068: protected String m_extReasonerURL = DIGConnection.DEFAULT_REASONER_URL;
069:
070: /** The profile of the ontology language we're expecting */
071: protected OntModelSpec m_ontLang = getModelSpec(ProfileRegistry.OWL_LANG);
072:
073: /** The axioms that provide additional triples based on the language we're processing */
074: protected Model m_axioms = null;
075:
076: // Constructors
077: //////////////////////////////////
078:
079: /**
080: * <p>Construct a DIG reasoner, that can generate inference graphs binding
081: * an external DIG inference engine (e.g. Racer) to a given source graph.<p>
082: * @param tbox Optional schema to bind to this reasoner instance. Unlike other Jena
083: * reasoners, pre-binding a tbox to a DIG reasoner does not allow any
084: * efficiencies to be exploited.
085: * @param factory The reasoner factory that created this reasoner
086: * @param configuration Optional resource to which is attached configuration
087: * parameters for this reasoner
088: */
089: public DIGReasoner(Graph tbox, ReasonerFactory factory,
090: Resource configuration) {
091: m_tbox = tbox;
092: m_factory = factory;
093: m_configuration = configuration;
094:
095: configure(configuration);
096: }
097:
098: // External signature methods
099: //////////////////////////////////
100:
101: /**
102: * <p>Bind a schema, or tbox, to this DIG reasoner. This does not have any efficiency
103: * value in DIG reasoners, since we must re-load the entire tbox into each new instance
104: * of a DIG inference graph.<p>
105: * @param tbox The graph containing the ontology (tbox) data
106: * @return A new DIG reasoner containing the tbox data
107: * @see com.hp.hpl.jena.reasoner.Reasoner#bindSchema(com.hp.hpl.jena.graph.Graph)
108: */
109: public Reasoner bindSchema(Graph tbox) {
110: return new DIGReasoner(tbox, m_factory, m_configuration);
111: }
112:
113: /**
114: * <p>Bind a schema, or tbox, to this DIG reasoner. This does not have any efficiency
115: * value in DIG reasoners, since we must re-load the entire tbox into each new instance
116: * of a DIG inference graph.<p>
117: * @param tbox A model wrapping the graph containing the ontology (tbox) data
118: * @return A new DIG reasoner containing the tbox data
119: * @see com.hp.hpl.jena.reasoner.Reasoner#bindSchema(com.hp.hpl.jena.graph.Graph)
120: */
121: public Reasoner bindSchema(Model tbox) {
122: return bindSchema(tbox.getGraph());
123: }
124:
125: /**
126: * <p>Bind the given data graph to any existing t-box schema that we have, and answer
127: * the resulting inference graph.</p>
128: * @param data A graph containing the source data
129: * @return A new inference graph that will apply the DIG reasoner to the combination
130: * of the tbox and data graphs.
131: */
132: public InfGraph bind(Graph data) {
133: return new DIGInfGraph(data, this );
134: }
135:
136: /**
137: * Not available.
138: * @exception UnsupportedOperationException
139: */
140: public void setDerivationLogging(boolean logOn) {
141: throw new UnsupportedOperationException(
142: "DIG reasoner does not support derivation logging");
143: }
144:
145: /**
146: * <p>Answer the capabilities of this reasoner.</p>
147: * @return An RDF model denoting the capabilties of the reasoner
148: */
149: public Model getReasonerCapabilities() {
150: return (m_factory == null) ? null : m_factory.getCapabilities();
151: }
152:
153: /**
154: * <p>Add this reasoner's description to the given configuration model.</p>
155: * @param configSpec A configuration model to add this reasoner's configuration to
156: * @param base The base URI in the given model to which we will attach the configuration
157: * of this reasoner.
158: */
159: public void addDescription(Model configSpec, Resource base) {
160: if (m_configuration != null) {
161: StmtIterator i = m_configuration.listProperties();
162: while (i.hasNext()) {
163: Statement st = i.nextStatement();
164: configSpec.add(base, st.getPredicate(), st.getObject());
165: }
166: }
167: }
168:
169: /**
170: * Determine whether the given property is recognized and treated specially
171: * by this reasoner. This is a convenience packaging of a special case of getCapabilities.
172: * @param property the property which we want to ask the reasoner about, given as a Node since
173: * this is part of the SPI rather than API
174: * @return true if the given property is handled specially by the reasoner.
175: */
176: public boolean supportsProperty(Property property) {
177: if (m_factory == null)
178: return false;
179: Model caps = m_factory.getCapabilities();
180: Resource root = caps.getResource(m_factory.getURI());
181: return caps.contains(root, ReasonerVocabulary.supportsP,
182: property);
183: }
184:
185: /**
186: * Set a configuration parameter for the reasoner. The supported parameters
187: * are:
188: * <ul>
189: * <li>PROPderivationLogging - set to true to enable recording all rule derivations</li>
190: * <li>PROPtraceOn - set to true to enable verbose trace information to be sent to the logger INFO channel</li>
191: * </ul>
192: *
193: * @param parameter the property identifying the parameter to be changed
194: * @param value the new value for the parameter, typically this is a wrapped
195: * java object like Boolean or Integer.
196: * @throws IllegalParameterException if the parameter is unknown
197: */
198: public void setParameter(Property parameter, Object value) {
199: if (!doSetParameter(parameter, value)) {
200: throw new IllegalParameterException(
201: "DIGReasoner does not recognize configuration parameter "
202: + parameter);
203: } else {
204: // Record the configuration change
205: if (m_configuration == null) {
206: Model configModel = ModelFactory.createDefaultModel();
207: m_configuration = configModel.createResource();
208: }
209:
210: Util.updateParameter(m_configuration, parameter, value);
211: }
212: }
213:
214: /**
215: * <p>Configure the reasoner using the properties attached to the given config
216: * resource.</p>
217: * @param configuration A configuration resource.
218: */
219: public void configure(Resource configuration) {
220: if (configuration != null) {
221: for (StmtIterator i = configuration.listProperties(); i
222: .hasNext();) {
223: Statement s = i.nextStatement();
224: if (!doSetParameter(s.getPredicate(), s.getObject())) {
225: // we used to throw an exception here, but such is no longer felicitous
226: // TODO consider namespace-based checking
227: }
228: }
229: }
230: }
231:
232: /**
233: * <p>Answer the URL to use when connecting to the external reasoner.</p>
234: * @return The connection URL for the external reasoner as a string
235: */
236: public String getReasonerURL() {
237: return m_extReasonerURL;
238: }
239:
240: /**
241: * <p>Answer the model spec that corresponds to the ontology model type we'll use to
242: * access the terms of the ontology according to language.</p>
243: * @return The appropriate ont model spec
244: */
245: public OntModelSpec getOntLangModelSpec() {
246: return m_ontLang;
247: }
248:
249: /**
250: * <p>Answer the schema (tbox) graph for this reasoner, or null if no schema is defined.</p>
251: * @return The schema graph, or null
252: */
253: public Graph getSchema() {
254: return m_tbox;
255: }
256:
257: /**
258: * <p>Answer the model that contains the given axioms for this reasoner, or null if
259: * not defined.</p>
260: * @return The axioms model
261: */
262: public Model getAxioms() {
263: return m_axioms;
264: }
265:
266: /**
267: * Return the Jena Graph Capabilties that the inference graphs generated
268: * by this reasoner are expected to conform to.
269: */
270: public Capabilities getGraphCapabilities() {
271: if (capabilities == null) {
272: capabilities = new BaseInfGraph.InfCapabilities();
273: }
274: return capabilities;
275: }
276:
277: // Internal implementation methods
278: //////////////////////////////////
279:
280: /**
281: * <p>Set a configuration parameter for the reasoner. The supported parameters
282: * are:</p>
283: * <ul>
284: * <li>{@link ReasonerVocabulary#EXT_REASONER_URL} the URL to use to connect to the external reasoners</li>
285: * <li>{@link ReasonerVocabulary#EXT_REASONER_ONT_LANG} the URI of the ontology language (OWL, DAML, etc) to process</li>
286: * <li>{@link ReasonerVocabulary#EXT_REASONER_AXIOMS} the URL of the ontology axioms model</li>
287: * </ul>
288: *
289: * @param parameter the property identifying the parameter to be changed
290: * @param value the new value for the parameter, typically this is a wrapped
291: * java object like Boolean or Integer.
292: * @return false if the parameter was not known
293: */
294: protected boolean doSetParameter(Property parameter, Object value) {
295: if (parameter.equals(ReasonerVocabulary.EXT_REASONER_URL)) {
296: m_extReasonerURL = (value instanceof Resource) ? ((Resource) value)
297: .getURI()
298: : value.toString();
299: return true;
300: } else if (parameter
301: .equals(ReasonerVocabulary.EXT_REASONER_ONT_LANG)) {
302: String lang = (value instanceof Resource) ? ((Resource) value)
303: .getURI()
304: : value.toString();
305: m_ontLang = getModelSpec(lang);
306: return true;
307: } else if (parameter
308: .equals(ReasonerVocabulary.EXT_REASONER_AXIOMS)) {
309: String axURL = (value instanceof Resource) ? ((Resource) value)
310: .getURI()
311: : value.toString();
312: m_axioms = ModelFactory.createDefaultModel();
313:
314: // if a file URL, try to load it as a stream (which means we can extract from jars etc)
315: if (axURL.startsWith("file:")) {
316: String fileName = axURL.substring(5);
317: InputStream in = null;
318: try {
319: in = FileUtils.openResourceFileAsStream(fileName);
320: m_axioms.read(in, axURL);
321: } catch (FileNotFoundException e) {
322: LogFactory.getLog(getClass()).error(
323: "Could not open DIG axioms " + axURL);
324: } finally {
325: if (in != null) {
326: try {
327: in.close();
328: } catch (IOException ignore) {
329: }
330: }
331: }
332: } else {
333: m_axioms.read(axURL);
334: }
335:
336: return true;
337: } else {
338: return false;
339: }
340: }
341:
342: /**
343: * <p>Answer the ont model spec for the given ontology language</p>
344: * @param lang The ontology language as a URI
345: * @return The correspondig ont model spec to use (should be no reasoner attached)
346: */
347: protected OntModelSpec getModelSpec(String lang) {
348: if (lang.equals(ProfileRegistry.OWL_LANG)
349: || lang.equals(ProfileRegistry.OWL_DL_LANG)
350: || lang.equals(ProfileRegistry.OWL_LITE_LANG)) {
351: return OntModelSpec.OWL_MEM;
352: } else if (lang.equals(ProfileRegistry.DAML_LANG)) {
353: return OntModelSpec.DAML_MEM;
354: } else if (lang.equals(ProfileRegistry.RDFS_LANG)) {
355: return OntModelSpec.RDFS_MEM;
356: } else {
357: throw new IllegalParameterException(
358: "DIG reasoner did not recognise ontology language "
359: + lang);
360: }
361: }
362:
363: //==============================================================================
364: // Inner class definitions
365: //==============================================================================
366:
367: }
368:
369: /*
370: * (c) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
371: * All rights reserved.
372: *
373: * Redistribution and use in source and binary forms, with or without
374: * modification, are permitted provided that the following conditions
375: * are met:
376: * 1. Redistributions of source code must retain the above copyright
377: * notice, this list of conditions and the following disclaimer.
378: * 2. Redistributions in binary form must reproduce the above copyright
379: * notice, this list of conditions and the following disclaimer in the
380: * documentation and/or other materials provided with the distribution.
381: * 3. The name of the author may not be used to endorse or promote products
382: * derived from this software without specific prior written permission.
383: *
384: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
385: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
386: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
387: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
388: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
389: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
390: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
391: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
392: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
393: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
394: */
|