001: /*
002: * Copyright 2005 John G. Wilson
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017:
018: package groovy.util.slurpersupport;
019:
020: import groovy.lang.Buildable;
021: import groovy.lang.Closure;
022: import groovy.lang.GroovyObject;
023: import groovy.lang.GroovyRuntimeException;
024:
025: import java.io.IOException;
026: import java.io.Writer;
027: import java.util.Iterator;
028: import java.util.Map;
029:
030: import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
031:
032: /**
033: * @author John Wilson
034: */
035:
036: class NodeChildren extends GPathResult {
037: private int size = -1;
038:
039: /**
040: * @param parent
041: * @param name
042: * @param namespacePrefix
043: * @param namespaceTagHints
044: */
045: public NodeChildren(final GPathResult parent, final String name,
046: final String namespacePrefix, final Map namespaceTagHints) {
047: super (parent, name, namespacePrefix, namespaceTagHints);
048: }
049:
050: /**
051: * @param parent
052: * @param name
053: * @param namespaceTagHints
054: */
055: public NodeChildren(final GPathResult parent, final String name,
056: final Map namespaceTagHints) {
057: this (parent, name, "*", namespaceTagHints);
058: }
059:
060: /**
061: * @param parent
062: * @param namespaceTagHints
063: */
064: public NodeChildren(final GPathResult parent,
065: final Map namespaceTagHints) {
066: this (parent, "*", namespaceTagHints);
067: }
068:
069: public Iterator childNodes() {
070: return new Iterator() {
071: private final Iterator iter = NodeChildren.this .parent
072: .childNodes();
073: private Iterator childIter = nextChildIter();
074:
075: /* (non-Javadoc)
076: * @see java.util.Iterator#hasNext()
077: */
078: public boolean hasNext() {
079: return this .childIter != null;
080: }
081:
082: /* (non-Javadoc)
083: * @see java.util.Iterator#next()
084: */
085: public Object next() {
086: while (this .childIter != null) {
087: try {
088: if (this .childIter.hasNext()) {
089: return this .childIter.next();
090: }
091: } finally {
092: if (!this .childIter.hasNext()) {
093: this .childIter = nextChildIter();
094: }
095: }
096: }
097:
098: return null;
099: }
100:
101: /* (non-Javadoc)
102: * @see java.util.Iterator#remove()
103: */
104: public void remove() {
105: throw new UnsupportedOperationException();
106: }
107:
108: private Iterator nextChildIter() {
109: while (this .iter.hasNext()) {
110: final Node node = (Node) this .iter.next();
111:
112: if (NodeChildren.this .name.equals(node.name())) {
113: final Iterator result = node.childNodes();
114:
115: if (result.hasNext()) {
116: if ("*"
117: .equals(NodeChildren.this .namespacePrefix)
118: || (""
119: .equals(NodeChildren.this .namespacePrefix) && ""
120: .equals(node.namespaceURI()))
121: || node
122: .namespaceURI()
123: .equals(
124: NodeChildren.this .namespaceMap
125: .get(NodeChildren.this .namespacePrefix))) {
126: return result;
127: }
128: }
129: }
130: }
131:
132: return null;
133: }
134: };
135: }
136:
137: public Iterator iterator() {
138: return new Iterator() {
139: final Iterator iter = nodeIterator();
140:
141: public boolean hasNext() {
142: return this .iter.hasNext();
143: }
144:
145: public Object next() {
146: return new NodeChild((Node) this .iter.next(),
147: NodeChildren.this .parent,
148: NodeChildren.this .namespaceTagHints);
149: }
150:
151: public void remove() {
152: throw new UnsupportedOperationException();
153: }
154: };
155: }
156:
157: public Iterator nodeIterator() {
158: if ("*".equals(this .name)) {
159: return this .parent.childNodes();
160: } else {
161: return new NodeIterator(this .parent.childNodes()) {
162: /* (non-Javadoc)
163: * @see org.codehaus.groovy.sandbox.util.slurpersupport.NodeIterator#getNextNode(java.util.Iterator)
164: */
165: protected Object getNextNode(Iterator iter) {
166: while (iter.hasNext()) {
167: final Node node = (Node) iter.next();
168:
169: if (NodeChildren.this .name.equals(node.name())) {
170: if ("*"
171: .equals(NodeChildren.this .namespacePrefix)
172: || (""
173: .equals(NodeChildren.this .namespacePrefix) && ""
174: .equals(node.namespaceURI()))
175: || node
176: .namespaceURI()
177: .equals(
178: NodeChildren.this .namespaceMap
179: .get(NodeChildren.this .namespacePrefix))) {
180: return node;
181: }
182: }
183: }
184:
185: return null;
186: }
187: };
188: }
189: }
190:
191: public GPathResult parents() {
192: // TODO Auto-generated method stub
193: throw new GroovyRuntimeException(
194: "parents() not implemented yet");
195: }
196:
197: public synchronized int size() {
198: if (this .size == -1) {
199: final Iterator iter = iterator();
200:
201: this .size = 0;
202: while (iter.hasNext()) {
203: iter.next();
204: this .size++;
205: }
206: }
207:
208: return this .size;
209: }
210:
211: public String text() {
212: final StringBuffer buf = new StringBuffer();
213: final Iterator iter = nodeIterator();
214:
215: while (iter.hasNext()) {
216: buf.append(((Node) iter.next()).text());
217: }
218:
219: return buf.toString();
220: }
221:
222: public GPathResult find(final Closure closure) {
223: final Iterator iter = iterator();
224:
225: while (iter.hasNext()) {
226: final Object node = iter.next();
227:
228: if (DefaultTypeTransformation.castToBoolean(closure
229: .call(new Object[] { node }))) {
230: return (GPathResult) node;
231: }
232: }
233:
234: return new NoChildren(this , this .name, this .namespaceTagHints);
235: }
236:
237: public GPathResult findAll(final Closure closure) {
238: return new FilteredNodeChildren(this , closure,
239: this .namespaceTagHints);
240: }
241:
242: public void build(final GroovyObject builder) {
243: final Iterator iter = nodeIterator();
244:
245: while (iter.hasNext()) {
246: final Object next = iter.next();
247:
248: if (next instanceof Buildable) {
249: ((Buildable) next).build(builder);
250: } else {
251: ((Node) next).build(builder, this .namespaceMap,
252: this .namespaceTagHints);
253: }
254: }
255: }
256:
257: /* (non-Javadoc)
258: * @see groovy.lang.Writable#writeTo(java.io.Writer)
259: */
260: public Writer writeTo(final Writer out) throws IOException {
261: final Iterator iter = nodeIterator();
262:
263: while (iter.hasNext()) {
264: ((Node) iter.next()).writeTo(out);
265: }
266:
267: return out;
268: }
269:
270: protected void replaceNode(final Closure newValue) {
271: final Iterator iter = iterator();
272:
273: while (iter.hasNext()) {
274: final NodeChild result = (NodeChild) iter.next();
275: result.replaceNode(newValue);
276: }
277: }
278:
279: protected void replaceBody(final Object newValue) {
280: final Iterator iter = iterator();
281:
282: while (iter.hasNext()) {
283: final NodeChild result = (NodeChild) iter.next();
284: result.replaceBody(newValue);
285: }
286: }
287:
288: protected void appendNode(final Object newValue) {
289: final Iterator iter = iterator();
290:
291: while (iter.hasNext()) {
292: final NodeChild result = (NodeChild) iter.next();
293: result.appendNode(newValue);
294: }
295: }
296: }
|