001: /******************************************************************
002: * File: BRWRule.java
003: * Created by: Dave Reynolds
004: * Created on: 22-Jan-2003
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: BRWRule.java,v 1.13 2008/01/02 12:06:44 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.reasoner.rdfsReasoner1;
010:
011: import com.hp.hpl.jena.reasoner.*;
012: import com.hp.hpl.jena.graph.*;
013: import com.hp.hpl.jena.vocabulary.*;
014: import com.hp.hpl.jena.util.iterator.*;
015:
016: import java.util.*;
017:
018: /**
019: * Datastructure to hold a trivial backward rewrite rule.
020: *
021: * <p>The rules take the form "pattern <- pattern" where the pattern
022: * is is a triple pattern with variables. The head pattern uses the
023: * variables s/p/o to refer to the subject/predicate/object parts of the
024: * body pattern. Similarly, the body pattern uses s/p/o to refer to
025: * the corresponding parts of the query being processed.</p>
026: *
027: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
028: * @version $Revision: 1.13 $ on $Date: 2008/01/02 12:06:44 $
029: */
030: public class BRWRule {
031:
032: /** The head of the rule */
033: protected TriplePattern head;
034:
035: /** The body of the rule */
036: protected TriplePattern body;
037:
038: /**
039: * Constructor
040: */
041: public BRWRule(TriplePattern head, TriplePattern body) {
042: this .head = head;
043: this .body = body;
044: }
045:
046: /**
047: * Factory method that builds a rule instance by parsing
048: * a simple string representation of the form:
049: * <pre>
050: * ?s prop foo <- ?a ns:prop _
051: * </pre>
052: * Variables are either _ or ?x, uri's are either simple strings (no spaces)
053: * or qnames. The prefix in qnames are restricted to rdf and rdfs.
054: * Minimal error checking.
055: */
056: public static BRWRule makeRule(String rulespec) {
057: StringTokenizer tokenizer = new StringTokenizer(rulespec);
058: try {
059: Node headS = parseNode(tokenizer.nextToken());
060: Node headP = parseNode(tokenizer.nextToken());
061: Node headO = parseNode(tokenizer.nextToken());
062: TriplePattern head = new TriplePattern(headS, headP, headO);
063: if (!tokenizer.nextToken().equals("<-"))
064: throw new NoSuchElementException();
065: Node bodyS = parseNode(tokenizer.nextToken());
066: Node bodyP = parseNode(tokenizer.nextToken());
067: Node bodyO = parseNode(tokenizer.nextToken());
068: TriplePattern body = new TriplePattern(bodyS, bodyP, bodyO);
069: return new BRWRule(head, body);
070: } catch (NoSuchElementException e) {
071: throw new ReasonerException("Illegal BRWRule: " + rulespec);
072: }
073: }
074:
075: /**
076: * Use the rule to implement the given query. This will
077: * instantiate the rule against the query, run the new query
078: * against the whole reasoner+rawdata again and then rewrite the
079: * results from that query according the rule.
080: * @param query the query being processed
081: * @param infGraph the parent infGraph that invoked us, will be called recursively
082: * @param data the raw data graph which gets passed back to the reasoner as part of the recursive invocation
083: * @param firedRules set of rules which have already been fired and should now be blocked
084: * @return a ExtendedIterator which aggregates the matches and rewrites them
085: * according to the rule
086: */
087: public ExtendedIterator execute(TriplePattern query,
088: InfGraph infGraph, Finder data, HashSet firedRules) {
089: TriplePattern iBody = instantiate(body, query);
090: BRWRule iRule = new BRWRule(head, iBody);
091: if (firedRules.contains(iRule)) {
092: // No additional answers to be found
093: return NullIterator.instance;
094: }
095: firedRules.add(iRule);
096: Iterator it = ((RDFSInfGraph) infGraph).findNested(iBody, data,
097: firedRules);
098: firedRules.remove(iRule);
099: return new RewriteIterator(it, iRule);
100: }
101:
102: /**
103: * Return true if this rule is a a complete solution to the given
104: * query and the router need look no further
105: */
106: public boolean completeFor(TriplePattern query) {
107: return false;
108: }
109:
110: /**
111: * instantiate a triple pattern against a query/value
112: */
113: protected static TriplePattern instantiate(TriplePattern pattern,
114: TriplePattern query) {
115: return new TriplePattern(instantiate(pattern.getSubject(),
116: query), instantiate(pattern.getPredicate(), query),
117: instantiate(pattern.getObject(), query));
118: }
119:
120: /**
121: * instantiate a rule body element against a query
122: */
123: protected static Node instantiate(Node elt, TriplePattern query) {
124: if (elt.isVariable()) {
125: String var = elt.getName(); // interned so can use simple equality test
126: if (var.equals("s"))
127: return query.getSubject();
128: if (var.equals("p"))
129: return query.getPredicate();
130: if (var.equals("o"))
131: return query.getObject();
132: }
133: return elt;
134: }
135:
136: /**
137: * instantiate a rule body element against a query ground value
138: */
139: protected static Node instantiate(Node elt, Triple value) {
140: if (elt.isVariable()) {
141: String var = elt.getName(); // interned so can use simple equality test
142: if (var.equals("s"))
143: return value.getSubject();
144: if (var.equals("p"))
145: return value.getPredicate();
146: if (var.equals("o"))
147: return value.getObject();
148: }
149: return elt;
150: }
151:
152: /**
153: * Assistant method to makeRule than parses a token as a node.
154: */
155: public static Node parseNode(String token) {
156: if (token.startsWith("?")) {
157: return Node.createVariable(token.substring(1));
158: } else if (token.equals("_")) {
159: return Node.createVariable("*");
160: } else if (token.indexOf(':') != -1) {
161: int split = token.indexOf(':');
162: String nsPrefix = token.substring(0, split);
163: String localname = token.substring(split + 1);
164: if (nsPrefix.equalsIgnoreCase("rdf")) {
165: return Node.createURI(RDF.getURI() + localname);
166: } else if (nsPrefix.equalsIgnoreCase("rdfs")) {
167: return Node.createURI(RDFS.getURI() + localname);
168: } else {
169: return Node.createURI(token);
170: }
171: } else {
172: return Node.createURI(token);
173: }
174: }
175:
176: /**
177: * Printable string form
178: */
179: public String toString() {
180: return head.toString() + " <- " + body.toString();
181: }
182:
183: /**
184: * Returns the body.
185: * @return TriplePattern
186: */
187: public TriplePattern getBody() {
188: return body;
189: }
190:
191: /**
192: * Returns the head.
193: * @return TriplePattern
194: */
195: public TriplePattern getHead() {
196: return head;
197: }
198:
199: /** Equality override */
200: public boolean equals(Object o) {
201: return o instanceof BRWRule && head.equals(((BRWRule) o).head)
202: && body.equals(((BRWRule) o).body);
203: }
204:
205: /** hash function override */
206: public int hashCode() {
207: return (head.hashCode() >> 1) ^ body.hashCode();
208: }
209:
210: /**
211: * Inner class. This implements an iterator that uses the rule to rewrite any
212: * results from the supplied iterator according to the rule.
213: */
214: static class RewriteIterator extends WrappedIterator {
215: /** The head of the rewrite rule */
216: TriplePattern head;
217:
218: /**
219: * Constructor
220: * @param underlying the iterator whose results are to be rewritten
221: * @param rule the BRWRule which defines the rewrite
222: */
223: public RewriteIterator(Iterator underlying, BRWRule rule) {
224: super (underlying);
225: this .head = rule.head;
226: }
227:
228: /**
229: * @see Iterator#next()
230: */
231: public Object next() {
232: Triple value = (Triple) super .next();
233: return new Triple(instantiate(head.getSubject(), value),
234: instantiate(head.getPredicate(), value),
235: instantiate(head.getObject(), value));
236: }
237: }
238:
239: }
240:
241: /*
242: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
243: All rights reserved.
244:
245: Redistribution and use in source and binary forms, with or without
246: modification, are permitted provided that the following conditions
247: are met:
248:
249: 1. Redistributions of source code must retain the above copyright
250: notice, this list of conditions and the following disclaimer.
251:
252: 2. Redistributions in binary form must reproduce the above copyright
253: notice, this list of conditions and the following disclaimer in the
254: documentation and/or other materials provided with the distribution.
255:
256: 3. The name of the author may not be used to endorse or promote products
257: derived from this software without specific prior written permission.
258:
259: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
260: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
261: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
262: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
263: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
264: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
266: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
267: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269: */
|