001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.xpath;
030:
031: import com.caucho.log.Log;
032: import com.caucho.xpath.pattern.AbstractPattern;
033: import com.caucho.xpath.pattern.NodeIterator;
034:
035: import org.w3c.dom.Node;
036:
037: import java.util.Iterator;
038: import java.util.logging.Logger;
039:
040: /**
041: * A node selection pattern. Patterns represent compiled XPath node selectors.
042: * They can be used to find nodes, select nodes, and test if a node matches
043: * a pattern.
044: *
045: * <p>There are two types of patterns: select patterns and match patterns.
046: * <p>Select patterns match a node relative to another node.
047: * <code>find</code> and <code>select</code> use select patterns.
048: * <p>Match patterns match a node in isolation. <code>isMatch</code> uses
049: * match patterns.
050: */
051: public class Pattern {
052: protected final static Logger log = Log.open(Pattern.class);
053:
054: private AbstractPattern pattern;
055:
056: Pattern(AbstractPattern pattern) {
057: this .pattern = pattern;
058: }
059:
060: /**
061: * Returns the first node matching the pattern. The pattern should
062: * be a select pattern.
063: *
064: * @param node node represented by '.' and start of match.
065: *
066: * @return first matching node
067: */
068: public Node find(Node node) throws XPathException {
069: if (node == null)
070: throw new NullPointerException();
071:
072: Env env = XPath.createEnv();
073: // XXX: doesn't make sense for a match to have a context?
074: //env.setCurrentNode(node);
075: //env.setContextNode(node);
076:
077: Iterator iter = pattern.select(node, env);
078:
079: Node value = null;
080: if (iter.hasNext())
081: value = (Node) iter.next();
082:
083: XPath.freeEnv(env);
084:
085: return value;
086: }
087:
088: /**
089: * Returns the first node matching the pattern. The pattern should
090: * be a select pattern.
091: *
092: * @param node node represented by '.' and start of match.
093: * @param env variable environment.
094: *
095: * @return first matching node
096: */
097: public Node find(Node node, ExprEnvironment env)
098: throws XPathException {
099: if (node == null)
100: throw new NullPointerException();
101:
102: if (env instanceof Env) {
103: Env globalEnv = (Env) env;
104:
105: // XXX: doesn't make sense for a match to have a context?
106: //globalEnv.setCurrentNode(node);
107: //globalEnv.setContextNode(node);
108: }
109:
110: Iterator iter = pattern.select(node, env);
111:
112: Node value = null;
113: if (iter.hasNext())
114: value = (Node) iter.next();
115:
116: return value;
117: }
118:
119: /**
120: * Selects all nodes matching the pattern. The pattern should be a
121: * select pattern.
122: *
123: * @param node node represented by '.' and start of match.
124: *
125: * @return iterator of matching nodes
126: */
127: public NodeIterator select(Node node) throws XPathException {
128: if (node == null)
129: throw new NullPointerException();
130:
131: Env env = XPath.createEnv();
132:
133: env.setCurrentNode(node);
134:
135: NodeIterator iter = pattern.select(node, env);
136:
137: XPath.freeEnv(env);
138:
139: return iter;
140: }
141:
142: /**
143: * Selects all nodes matching the pattern. The pattern should be a
144: * select pattern.
145: *
146: * @param context node represented by '.' and start of match.
147: * @param env variable environment.
148: *
149: * @return iterator of matching nodes
150: */
151: public NodeIterator select(Node node, ExprEnvironment env)
152: throws XPathException {
153: if (node == null)
154: throw new NullPointerException();
155:
156: if (env instanceof Env) {
157: Env globalEnv = (Env) env;
158: globalEnv.setCurrentNode(node);
159: globalEnv.setContextNode(node);
160: }
161:
162: return pattern.select(node, env);
163: }
164:
165: /**
166: * Test if the node matches the pattern. The pattern should be a
167: * match pattern.
168: *
169: * @param node node to test
170: *
171: * @return true if the pattern matches.
172: */
173: public boolean isMatch(Node node) throws XPathException {
174: Env env = XPath.createEnv();
175:
176: // XXX: doesn't make sense for a match to have a context?
177: //env.setCurrentNode(node);
178: //env.setContextNode(node);
179:
180: boolean value = pattern.match(node, env);
181:
182: XPath.freeEnv(env);
183:
184: return value;
185: }
186:
187: /**
188: * Test if the node matches the pattern. The pattern should be a
189: * match pattern.
190: *
191: * @param node node to test
192: * @param env variable environment.
193: *
194: * @return true if the pattern matches.
195: */
196: public boolean isMatch(Node node, ExprEnvironment env)
197: throws XPathException {
198: return pattern.match(node, env);
199: }
200:
201: /**
202: * Returns the underlying pattern implementation.
203: */
204: public AbstractPattern getPattern() {
205: return pattern;
206: }
207:
208: public String toString() {
209: return pattern.toString();
210: }
211: }
|