KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > TriplePattern


1 /******************************************************************
2  * File: TriplePattern.java
3  * Created by: Dave Reynolds
4  * Created on: 18-Jan-03
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * [See end of file]
8  * $Id: TriplePattern.java,v 1.24 2005/02/21 12:16:17 andy_seaborne Exp $
9  *****************************************************************/

10 package com.hp.hpl.jena.reasoner;
11
12 import java.util.Map JavaDoc;
13
14 import com.hp.hpl.jena.graph.*;
15 import com.hp.hpl.jena.reasoner.rulesys.ClauseEntry;
16 import com.hp.hpl.jena.reasoner.rulesys.Functor;
17 import com.hp.hpl.jena.reasoner.rulesys.Node_RuleVariable;
18 import com.hp.hpl.jena.util.CollectionFactory;
19 import com.hp.hpl.jena.vocabulary.RDF;
20 import com.hp.hpl.jena.vocabulary.RDFS;
21
22 /**
23  * Datastructure which defines a triple pattern as used in simple
24  * rules and in find interfaces.
25  * <p>
26  * Wildcards are recorded by using Node_RuleVariable entries rather than
27  * nulls because they can be named. If a null is specified that is
28  * converted to a variable of name "". Note that whilst some engines might simply
29  * require Node_Variables the forward engine requires variables represented using
30  * the more specialized subclass - Node_RuleVariable.</p>
31  * <p>
32  * It would make more sense to have TriplePattern subclass Triple
33  * but that is final for some strange reason.</p>
34  *
35  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
36  * @version $Revision: 1.24 $ on $Date: 2005/02/21 12:16:17 $
37  */

38 public class TriplePattern implements ClauseEntry {
39
40     /** The subject element of the pattern */
41     protected Node subject;
42     
43     /** The predicate element of the pattern */
44     protected Node predicate;
45     
46     /** The object element of the pattern */
47     protected Node object;
48     
49     /**
50      * Constructor - builds a pattern from three nodes,
51      * use Node_RuleVariables as variables, use a variable
52      * with an empty name as a wildcard, can also use null
53      * as a wildcard.
54      */

55     public TriplePattern(Node subject, Node predicate, Node object) {
56         this.subject = normalize(subject);
57         this.predicate = normalize(predicate);
58         this.object = normalize(object);
59     }
60     
61     /**
62      * Constructor - builds a pattern from a standard triple match.
63      * Node that any filter part of the triple match will not be
64      * represented within the pattern and will need to be checked
65      * for separately.
66      */

67     public TriplePattern(TripleMatch match) {
68         this.subject = normalize(match.getMatchSubject());
69         this.predicate = normalize(match.getMatchPredicate());
70         this.object = normalize(match.getMatchObject());
71     }
72     
73     /**
74      * Constructor - builds a dgenerate pattern from a simple triple.
75      * This would be much easier if we merged Triples and TriplePatterns!
76      */

77     public TriplePattern(Triple match) {
78         this.subject = normalize(match.getSubject());
79         this.predicate = normalize(match.getPredicate());
80         this.object = normalize(match.getObject());
81     }
82     
83     /**
84      * Returns the object.
85      * @return Node
86      */

87     public Node getObject() {
88         return object;
89     }
90
91     /**
92      * Returns the predicate.
93      * @return Node
94      */

95     public Node getPredicate() {
96         return predicate;
97     }
98
99     /**
100      * Returns the subject.
101      * @return Node
102      */

103     public Node getSubject() {
104         return subject;
105     }
106
107     /**
108      * Return the triple pattern as a triple match
109      */

110     public TripleMatch asTripleMatch() {
111         return Triple.createMatch(toMatch(subject),
112                                         toMatch(predicate),
113                                         toMatch(object));
114     }
115
116     /**
117      * Return the triple pattern as a triple
118      */

119     public Triple asTriple() {
120         return new Triple(subject,predicate, object);
121     }
122     
123     /**
124      * Compare two patterns for compatibility - i.e. potentially unifiable.
125      * Two patterns are "compatible" in the sense we mean here
126      * if all their ground terms match. A variable in either pattern
127      * can match a ground term or a variable in the other. We are not,
128      * currently, checking for multiple occurances of the same variable.
129      * Functor-valued object literals are treated as a special case which
130      * are only checked for name/arity matching.
131      */

132     public boolean compatibleWith(TriplePattern pattern) {
133         boolean ok = subject.isVariable() || pattern.subject.isVariable() || subject.equals(pattern.subject);
134         if (!ok) return false;
135         ok = predicate.isVariable() || pattern.predicate.isVariable() || predicate.equals(pattern.predicate);
136         if (!ok) return false;
137         if (object.isVariable() || pattern.object.isVariable()) return true;
138         // Left with checking compatibility of ground literals
139
if (Functor.isFunctor(object) && Functor.isFunctor(pattern.object)) {
140             Functor functor = (Functor)object.getLiteral().getValue();
141             Functor pFunctor = (Functor)pattern.object.getLiteral().getValue();
142             return (functor.getName().equals(pFunctor.getName())
143                             && functor.getArgs().length == pFunctor.getArgs().length);
144         } else {
145             return object.sameValueAs(pattern.object);
146         }
147     }
148     
149     /**
150      * Test if a pattern is just a variant of this pattern. I.e. it is the same
151      * up to variable renaming. This takes into account multiple occurances
152      * of the same variable.
153      */

154     public boolean variantOf(TriplePattern pattern) {
155         Map JavaDoc vmap = CollectionFactory.createHashedMap();
156         if ( ! variantOf(subject, pattern.subject, vmap) ) return false;
157         if ( ! variantOf(predicate, pattern.predicate, vmap) ) return false;
158         if (Functor.isFunctor(object) && Functor.isFunctor(pattern.object)) {
159             Functor functor = (Functor)object.getLiteral().getValue();
160             Functor pFunctor = (Functor)pattern.object.getLiteral().getValue();
161             if ( ! functor.getName().equals(pFunctor.getName()) ) return false;
162             Node[] args = functor.getArgs();
163             Node[] pargs = pFunctor.getArgs();
164             if ( args.length != pargs.length ) return false;
165             for (int i = 0; i < args.length; i++) {
166                 if ( ! variantOf(args[i], pargs[i], vmap) ) return false;
167             }
168             return true;
169         } else {
170             return variantOf(object, pattern.object, vmap);
171         }
172     }
173     
174     /**
175      * Test if one node is a variant of another give a table of variable matches.
176      */

177     private boolean variantOf(Node n, Node p, Map JavaDoc vmap) {
178         if (n instanceof Node_RuleVariable) {
179             if (p instanceof Node_RuleVariable) {
180                 Object JavaDoc nMatch = vmap.get(n);
181                 if (nMatch == null) {
182                     // First match of these pairs
183
vmap.put(n, p);
184                     return true;
185                 } else {
186                     return nMatch == p;
187                 }
188             } else {
189                 return false;
190             }
191         } else {
192             return n.sameValueAs(p);
193         }
194     }
195     
196     /**
197      * Check a pattern to see if it is legal, used to exclude backchaining goals that
198      * could never be satisfied. A legal pattern cannot have literals in the subject or
199      * predicate positions and is not allowed nested functors in the object.
200      */

201     public boolean isLegal() {
202         if (subject.isLiteral() || predicate.isLiteral()) return false;
203         if (Functor.isFunctor(subject)) return false;
204         if (Functor.isFunctor(object)) {
205             Node[] args = ((Functor)object.getLiteral().getValue()).getArgs();
206             for (int i = 0; i < args.length; i++) {
207                 if (Functor.isFunctor(args[i])) return false;
208             }
209         }
210         return true;
211     }
212     
213     /**
214      * Compare two patterns and return true if arg is a more
215      * specific (more grounded) version of this one.
216      * Does not handle functors.
217      */

218     public boolean subsumes(TriplePattern arg) {
219         return (subject.isVariable() || subject.equals(arg.subject))
220             && (predicate.isVariable() || predicate.equals(arg.predicate))
221             && (object.isVariable() || object.equals(arg.object));
222     }
223     
224     /**
225      * Test if the pattern is ground, contains no variables.
226      */

227     public boolean isGround() {
228         if (subject.isVariable() || predicate.isVariable() || object.isVariable()) return false;
229         if (Functor.isFunctor(object)) {
230             return ((Functor)object.getLiteral().getValue()).isGround();
231         }
232         return true;
233     }
234     
235     /**
236      * Printable string
237      */

238     public String JavaDoc toString() {
239         return simplePrintString(subject) +
240                 " @" + simplePrintString(predicate) +
241                 " " + simplePrintString(object);
242     }
243     
244     /**
245      * Simplified printable name for a triple
246      */

247     public static String JavaDoc simplePrintString(Triple t) {
248         return simplePrintString(t.getSubject()) +
249                 " @" + simplePrintString(t.getPredicate()) +
250                 " " + simplePrintString(t.getObject());
251     }
252
253     /**
254      * Simplified printable name for a node
255      */

256     public static String JavaDoc simplePrintString(Node n) {
257         if (n instanceof Node_URI) {
258             String JavaDoc uri = n.getURI();
259             int split = uri.lastIndexOf('#');
260             if (split == -1) {
261                 split = uri.lastIndexOf('/');
262                 if (split == -1) split = -1;
263             }
264             String JavaDoc ns = uri.substring(0, split+1);
265             String JavaDoc prefix = "";
266             if (ns.equals(RDF.getURI())) {
267                 prefix = "rdf:";
268             } else if (ns.equals(RDFS.getURI())) {
269                 prefix = "rdfs:";
270             }
271             return prefix + uri.substring(split+1);
272         } else {
273             return n.toString();
274         }
275     }
276             
277     /**
278      * Convert any null wildcards to Node_RuleVariable wildcards.
279      */

280     private static Node normalize(Node node) {
281         if (node == null || node == Node.ANY) return Node_RuleVariable.WILD;
282 // if (node == null) return Node.ANY;
283
return node;
284     }
285             
286     /**
287      * Convert any Node_RuleVariable wildcards to null. This loses
288      * the variable named but is used when converting a singleton
289      * pattern to a TripleMtch
290      */

291     private static Node toMatch(Node node) {
292         return node.isVariable() ? null : node;
293     }
294     
295     /**
296      * Equality override - used so that TriplePattern variants (same to within variable renaming) test as equals
297      */

298     public boolean equals(Object JavaDoc o) {
299 // return o instanceof TriplePattern &&
300
// subject.equals(((TriplePattern)o).subject) &&
301
// predicate.equals(((TriplePattern)o).predicate) &&
302
// object.equals(((TriplePattern)o).object);
303
return o instanceof TriplePattern &&
304                 nodeEqual(subject, ((TriplePattern)o).subject) &&
305                 nodeEqual(predicate, ((TriplePattern)o).predicate) &&
306                 nodeEqual(object, ((TriplePattern)o).object);
307     }
308     
309     /** Helper - equality override on nodes */
310     private boolean nodeEqual(Node n1, Node n2) {
311         if ((n1 instanceof Node_RuleVariable) && (n2 instanceof Node_RuleVariable)) {
312             return true;
313         } else {
314             return n1.equals(n2);
315         }
316     }
317         
318     /** hash function override */
319     public int hashCode() {
320         int hash = 0;
321         if (!(subject instanceof Node_RuleVariable)) hash ^= (subject.hashCode() >> 1);
322         if (!(predicate instanceof Node_RuleVariable)) hash ^= predicate.hashCode();
323         if (!(object instanceof Node_RuleVariable)) hash ^= (object.hashCode() << 1);
324         return hash;
325 // return (subject.hashCode() >> 1) ^ predicate.hashCode() ^ (object.hashCode() << 1);
326
}
327     
328     /**
329      * Compare triple patterns, taking into account variable indices.
330      * The equality function ignores differences between variables.
331      */

332     public boolean sameAs(Object JavaDoc o) {
333         if (! (o instanceof TriplePattern) ) return false;
334         TriplePattern other = (TriplePattern) o;
335         return Node_RuleVariable.sameNodeAs(subject, other.subject) && Node_RuleVariable.sameNodeAs(predicate, other.predicate) && Node_RuleVariable.sameNodeAs(object, other.object);
336     }
337     
338 }
339
340 /*
341     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
342     All rights reserved.
343
344     Redistribution and use in source and binary forms, with or without
345     modification, are permitted provided that the following conditions
346     are met:
347
348     1. Redistributions of source code must retain the above copyright
349        notice, this list of conditions and the following disclaimer.
350
351     2. Redistributions in binary form must reproduce the above copyright
352        notice, this list of conditions and the following disclaimer in the
353        documentation and/or other materials provided with the distribution.
354
355     3. The name of the author may not be used to endorse or promote products
356        derived from this software without specific prior written permission.
357
358     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
359     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
360     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
361     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
362     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
363     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
364     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
365     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
366     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
367     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368 */

369
370
Popular Tags