001: /*
002: (c) Copyright 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: All rights reserved - see end of file.
004: $Id: QueryNode.java,v 1.13 2008/01/02 12:07:56 andy_seaborne Exp $
005: */
006: package com.hp.hpl.jena.graph.query;
007:
008: import java.util.Set;
009:
010: import com.hp.hpl.jena.graph.Node;
011: import com.hp.hpl.jena.shared.BrokenException;
012:
013: /**
014: A QueryNode is a wrapped node that has been processed against
015: some variable-binding map to discover (a) what kind of node it is
016: and (b) what index in the binding map it has.
017: <p>
018: There are five sub-classes of QueryNode
019:
020: <ul>
021: <li>Fixed - a concrete node, with pseudo-index NO_INDEX
022: <li>Bind - a variable node's first, binding, appearance
023: <li>JustBound - a variable node's bound appearance in the same
024: [triple] context as its binding appearance
025: <li>Bound - a variable node's bound appearance
026: <li>Any - Node.ANY (or, in principle, a free variable)
027: </ul>
028:
029: @author hedgehog
030: */
031: public abstract class QueryNode {
032: /**
033: Internal exception to throw if, against all chance, something that
034: shouldn't be involved in a match <i>is</i>.
035: @author kers
036: */
037: public class MustNotMatchException extends BrokenException {
038: public MustNotMatchException(String message) {
039: super (message);
040: }
041: }
042:
043: /**
044: Fake index value to use when no index makes sense; we choose a value
045: that will fail any array-bound check if it happens to be used anyway.
046: */
047: public static final int NO_INDEX = -1;
048:
049: /**
050: The Node value on which this QueryNode is based.
051: */
052: public final Node node;
053:
054: /**
055: The index value allocated to this query node; NO_INDEX except for a
056: variable node, in which case it is the allocated index in the domain
057: object.
058: */
059: public final int index;
060:
061: protected QueryNode(Node node) {
062: this (node, NO_INDEX);
063: }
064:
065: protected QueryNode(Node node, int index) {
066: this .node = node;
067: this .index = index;
068: }
069:
070: /**
071: Return a handy string representation for debugging purposes. Not for
072: machine consumption.
073: */
074: public String toString() {
075: return node.toString() + "[" + index + "]";
076: }
077:
078: /**
079: Answer true iff this node is "frozen", ie its value is fixed, when it
080: is encountered; that is, it is not a Bind or JustBound node.
081: */
082: public boolean isFrozen() {
083: return true;
084: }
085:
086: /**
087: Answer a Node value to use when this QueryValue is used to select
088: objects in a Graph::find() operation; for concrete nodes, that very
089: node, for variables their current value (ANY if not bound).
090: */
091: public Node finder(Domain d) {
092: return Node.ANY;
093: }
094:
095: /**
096: Answer true iff this QueryNode must be used in a triple-match of its
097: owning QueryTriple.
098: */
099: public boolean mustMatch() {
100: return false;
101: }
102:
103: /**
104: Answer true iff this QueryNode matches, in the context of the binding
105: Domain <code>d</code>, the node <code>x</code>.
106: */
107: public boolean match(Domain d, Node x) {
108: throw new MustNotMatchException("QueryNode " + this
109: + " cannot match");
110: }
111:
112: /**
113: Optimisation: the action to be performed when matching a just-bound
114: variable or binding a newly-bound variable, or nothing for any other
115: kind of QueryNode.
116: */
117: public abstract boolean matchOrBind(Domain d, Node x);
118:
119: /**
120: Answer a QueryNode that classifies the argument node <code>n</code>.
121: The factory <code>f</code> is used to create the different QueryNodes,
122: allowing different classifiers to use their own subclasses of QueryNode
123: if they wish. <code>map</code> is the variable-to-index map, and
124: <code>recent</code> is the set of those variables "just" bound, ie,
125: earlier in the same triple.
126: */
127: public static QueryNode classify(QueryNodeFactory f, Mapping map,
128: Set recent, Node n) {
129: if (n.equals(Node.ANY))
130: return f.createAny();
131: if (n.isVariable()) {
132: if (map.hasBound(n)) {
133: if (recent.contains(n))
134: return f.createJustBound(n, map.indexOf(n));
135: else
136: return f.createBound(n, map.indexOf(n));
137: } else {
138: recent.add(n);
139: return f.createBind(n, map.newIndex(n));
140: }
141: }
142: return new Fixed(n);
143: }
144:
145: public static final QueryNodeFactory factory = new QueryNodeFactoryBase();
146:
147: public static class Fixed extends QueryNode {
148: public Fixed(Node n) {
149: super (n);
150: }
151:
152: public Node finder(Domain d) {
153: return node;
154: }
155:
156: public boolean matchOrBind(Domain d, Node x) {
157: return node.matches(x);
158: }
159:
160: public String toString() {
161: return node.toString() + "[fixed]";
162: }
163: }
164:
165: public static class Bind extends QueryNode {
166: public Bind(Node n, int index) {
167: super (n, index);
168: }
169:
170: public boolean mustMatch() {
171: return true;
172: }
173:
174: public boolean isFrozen() {
175: return false;
176: }
177:
178: public boolean match(Domain d, Node value) {
179: d.setElement(index, value);
180: return true;
181: }
182:
183: public boolean matchOrBind(Domain d, Node value) {
184: d.setElement(index, value);
185: return true;
186: }
187:
188: public String toString() {
189: return node.toString() + "[bind " + index + "]";
190: }
191: }
192:
193: public static class JustBound extends QueryNode {
194: public JustBound(Node n, int index) {
195: super (n, index);
196: }
197:
198: public boolean mustMatch() {
199: return true;
200: }
201:
202: public boolean isFrozen() {
203: return false;
204: }
205:
206: public boolean match(Domain d, Node X) {
207: return X.matches(d.getElement(index));
208: }
209:
210: public boolean matchOrBind(Domain d, Node x) {
211: return x.matches(d.getElement(index));
212: }
213:
214: public String toString() {
215: return node.toString() + "[just " + index + "]";
216: }
217: }
218:
219: public static class Bound extends QueryNode {
220: public Bound(Node n, int index) {
221: super (n, index);
222: }
223:
224: public Node finder(Domain d) {
225: return d.getElement(index);
226: }
227:
228: public boolean matchOrBind(Domain d, Node x) {
229: return d.getElement(index).matches(x);
230: }
231:
232: public String toString() {
233: return node.toString() + "[bound " + index + "]";
234: }
235: }
236:
237: public static class Any extends QueryNode {
238: public Any() {
239: super (Node.ANY);
240: }
241:
242: public boolean matchOrBind(Domain d, Node x) {
243: return true;
244: }
245:
246: public String toString() {
247: return "ANY";
248: }
249: }
250: }
251: /*
252: * (c) Copyright 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
253: * All rights reserved.
254: *
255: * Redistribution and use in source and binary forms, with or without
256: * modification, are permitted provided that the following conditions
257: * are met:
258: * 1. Redistributions of source code must retain the above copyright
259: * notice, this list of conditions and the following disclaimer.
260: * 2. Redistributions in binary form must reproduce the above copyright
261: * notice, this list of conditions and the following disclaimer in the
262: * documentation and/or other materials provided with the distribution.
263: * 3. The name of the author may not be used to endorse or promote products
264: * derived from this software without specific prior written permission.
265: *
266: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
267: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
268: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
269: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
270: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
271: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
272: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
273: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
274: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276: */
|