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    package groovy.util.slurpersupport;
018    
019    import java.util.Iterator;
020    import java.util.Map;
021    
022    import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
023    
024    import groovy.lang.Closure;
025    
026    /**
027     * @author John Wilson
028     */
029    
030    public class FilteredNodeChildren extends NodeChildren {
031        private final Closure closure;
032    
033        public FilteredNodeChildren(final GPathResult parent, final Closure closure, final Map namespaceTagHints) {
034            super(parent, parent.name, namespaceTagHints);
035            this.closure = closure;
036        }
037    
038        public Iterator iterator() {
039            return new Iterator() {
040            final Iterator iter = FilteredNodeChildren.this.parent.iterator();
041            Object next = null;
042    
043                public boolean hasNext() {
044                    while (this.iter.hasNext()) {
045                    final Object childNode = this.iter.next();
046                    
047                        if (closureYieldsTrueForNode(childNode)) {
048                            this.next = childNode;
049                            return true;
050                        }
051                    }
052                    
053                    return false;
054                }
055    
056                public Object next() {
057                    return this.next;
058                }
059    
060                public void remove() {
061                    throw new UnsupportedOperationException();
062                }
063            };
064        }
065    
066        public Iterator nodeIterator() {
067            return new NodeIterator(this.parent.nodeIterator()) {
068                protected Object getNextNode(final Iterator iter) {
069                    while (iter.hasNext()) {
070                    final Object node = iter.next();
071                    
072                        if (closureYieldsTrueForNode(new NodeChild((Node) node, FilteredNodeChildren.this.parent, FilteredNodeChildren.this.namespaceTagHints))) {
073                            return node;
074                        }
075                    }
076                    return null;
077                }
078            };
079        }
080    
081        private boolean closureYieldsTrueForNode(Object childNode) {
082            return DefaultTypeTransformation.castToBoolean(FilteredNodeChildren.this.closure.call(new Object[]{childNode}));
083        }
084    
085    }