001: /******************************************************************
002: * File: BaseRule.java
003: * Created by: Dave Reynolds
004: * Created on: 26-Jan-03
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: BaseFRule.java,v 1.10 2008/01/02 12:06:43 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.reasoner.transitiveReasoner.TransitiveReasoner;
013: import com.hp.hpl.jena.graph.*;
014:
015: import java.util.*;
016:
017: /**
018: * Base class for forward rules. Holds a head pattern (which will
019: * be matched against the triple store) and an array of body patterns.
020: * The body patterns can be instantiated following a successful head
021: * match and then processed be descendant class.
022: *
023: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
024: * @version $Revision: 1.10 $ on $Date: 2008/01/02 12:06:43 $
025: */
026: public class BaseFRule {
027:
028: /** The head triple pattern */
029: protected TriplePattern head;
030:
031: /** The body triple patterns */
032: protected TriplePattern[] body;
033:
034: /**
035: * Constructor
036: */
037: public BaseFRule(TriplePattern head, TriplePattern[] body) {
038: this .head = head;
039: this .body = body;
040: }
041:
042: /**
043: * Constructor
044: */
045: public BaseFRule(String spec) {
046: List patterns = parseTripleSequence(spec);
047: head = (TriplePattern) patterns.get(0);
048: body = new TriplePattern[patterns.size() - 1];
049: for (int i = 1; i < patterns.size(); i++) {
050: body[i - 1] = (TriplePattern) patterns.get(i);
051: }
052: }
053:
054: /**
055: * Match the rule against a single triple.
056: * Instantiating the variables then firing the consequent action.
057: */
058: public void bindAndFire(Triple value, RDFSInfGraph reasoner) {
059: // special case filter of reflexive subClass/subProp cases
060: // somewhat hacky doing it here ...
061: if ((value.getPredicate().equals(
062: TransitiveReasoner.subPropertyOf) || value
063: .getPredicate().equals(TransitiveReasoner.subClassOf))
064: && value.getSubject().equals(value.getObject())) {
065: // skip this case
066: return;
067: }
068: Map bindings = new HashMap();
069: matchNode(value.getSubject(), head.getSubject(), bindings);
070: matchNode(value.getPredicate(), head.getPredicate(), bindings);
071: matchNode(value.getObject(), head.getObject(), bindings);
072: // Instantiate the body
073: TriplePattern[] newBody = new TriplePattern[body.length];
074: for (int i = 0; i < body.length; i++) {
075: newBody[i] = new TriplePattern(instantiate(body[i]
076: .getSubject(), bindings), instantiate(body[i]
077: .getPredicate(), bindings), instantiate(body[i]
078: .getObject(), bindings));
079: }
080: fire(newBody, reasoner);
081: }
082:
083: /**
084: * Called when the rule fires.
085: * Subclasses should override.
086: */
087: void fire(TriplePattern[] body, RDFSInfGraph reasoner) {
088: }
089:
090: /**
091: * Match a single node pair and add any new variable binding
092: */
093: static void matchNode(Node valueNode, Node patternNode, Map bindings) {
094: if (patternNode.isVariable()) {
095: bindings.put(patternNode.getName(), valueNode);
096: }
097: }
098:
099: /**
100: * Instantiate a node using the bindings
101: */
102: static Node instantiate(Node elt, Map bindings) {
103: if (elt.isVariable()) {
104: Node result = (Node) bindings.get(elt.getName());
105: if (result != null)
106: return result;
107: }
108: return elt;
109: }
110:
111: /**
112: * Assistant method to parse a string into a triple
113: */
114: public static Triple parseTriple(String spec) {
115: StringTokenizer tokenizer = new StringTokenizer(spec);
116: try {
117: Node s = BRWRule.parseNode(tokenizer.nextToken());
118: Node p = BRWRule.parseNode(tokenizer.nextToken());
119: Node o = BRWRule.parseNode(tokenizer.nextToken());
120: return new Triple(s, p, o);
121: } catch (NoSuchElementException e) {
122: throw new ReasonerException("Illegal triple: " + spec);
123: }
124: }
125:
126: /**
127: * Assistant method to parse a token stream into a triple pattern
128: */
129: private static TriplePattern parseTriplePattern(
130: StringTokenizer tokenizer) {
131: try {
132: Node s = BRWRule.parseNode(tokenizer.nextToken());
133: Node p = BRWRule.parseNode(tokenizer.nextToken());
134: Node o = BRWRule.parseNode(tokenizer.nextToken());
135: return new TriplePattern(s, p, o);
136: } catch (NoSuchElementException e) {
137: throw new ReasonerException("Illegal triple in rule");
138: }
139: }
140:
141: /**
142: * Assistant method to parse a string into a sequence oftriple patterns.
143: * The patterns may be separated by "<-", "->" or "|" strings.
144: * @return a list of TriplePatterns
145: */
146: public static List parseTripleSequence(String spec) {
147: StringTokenizer tokenizer = new StringTokenizer(spec);
148: List triples = new ArrayList();
149: while (tokenizer.hasMoreElements()) {
150: triples.add(parseTriplePattern(tokenizer));
151: if (tokenizer.hasMoreElements()) {
152: String sep = tokenizer.nextToken();
153: if (!sep.equals("|") && !sep.equals("->")
154: && !sep.equals("<-")) {
155: throw new ReasonerException("Illegal FRUle spec: "
156: + spec);
157: }
158: }
159: }
160: return triples;
161: }
162:
163: /**
164: * Returns the head.
165: * @return TriplePattern
166: */
167: public TriplePattern getHead() {
168: return head;
169: }
170:
171: }
172:
173: /*
174: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
175: All rights reserved.
176:
177: Redistribution and use in source and binary forms, with or without
178: modification, are permitted provided that the following conditions
179: are met:
180:
181: 1. Redistributions of source code must retain the above copyright
182: notice, this list of conditions and the following disclaimer.
183:
184: 2. Redistributions in binary form must reproduce the above copyright
185: notice, this list of conditions and the following disclaimer in the
186: documentation and/or other materials provided with the distribution.
187:
188: 3. The name of the author may not be used to endorse or promote products
189: derived from this software without specific prior written permission.
190:
191: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
192: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
193: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
194: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
195: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
196: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
197: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
198: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
199: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
200: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
201: */
|