/*
 * Copyright 2005 John G. Wilson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package groovy.util.slurpersupport;

import java.util.Iterator;
import java.util.Map;

import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;

import groovy.lang.Closure;

/**
 * @author John Wilson
 */

public class FilteredNodeChildren extends NodeChildren
{
    private final Closure closure;

    public FilteredNodeChildren(final GPathResult parent, final Closure closure, final Map namespaceTagHints) {
        super(parent, parent.name, namespaceTagHints);
        this.closure = closure;
    }

    public Iterator iterator() {
        return new Iterator()
        {
            final Iterator iter = FilteredNodeChildren.this.parent.iterator();

            public boolean hasNext() {
                return this.iter.hasNext();
            }

            public Object next() {
                while (iter.hasNext()) {
                    final Object childNode = iter.next();
                    if (closureYieldsTrueForNode(childNode)) {
                        return childNode;
                    }
                }
                return null;
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

    public Iterator nodeIterator() {
        return new NodeIterator(this.parent.nodeIterator())
        {
            protected Object getNextNode(final Iterator iter) {
                while (iter.hasNext()) {
                    final Object node = iter.next();
                    if (closureYieldsTrueForNode(new NodeChild((Node) node, FilteredNodeChildren.this.parent, FilteredNodeChildren.this.namespaceTagHints))) {
                        return node;
                    }
                }
                return null;
            }
        };
    }

    private boolean closureYieldsTrueForNode(Object childNode) {
        return DefaultTypeTransformation.castToBoolean(FilteredNodeChildren.this.closure.call(new Object[]{childNode}));
    }

}

@@ -872,17 +872,17 @@
 Children
-%0A
+ 
 %7B%0A    pr
@@ -1179,31 +1179,19 @@
 erator()
-%0A        %7B%0A    
+ %7B%0A
         
@@ -1257,29 +1257,24 @@
 ator();%0A
-%0A    
         
 public b
@@ -1269,92 +1269,27 @@
     
-public boolean hasNext() %7B%0A                return this.iter.hasNext();%0A            %7D
+Object next = null;
 %0A%0A  
@@ -1305,24 +1305,28 @@
  public 
-Object n
+boolean hasN
 ext() %7B%0A
@@ -1340,32 +1340,37 @@
          while (
+this.
 iter.hasNext()) 
@@ -1363,36 +1363,32 @@
 er.hasNext()) %7B%0A
-    
                 
@@ -1408,24 +1408,29 @@
 childNode = 
+this.
 iter.next();
@@ -1422,32 +1422,49 @@
 is.iter.next();%0A
+                %0A
                 
@@ -1534,22 +1534,27 @@
         
-return
+this.next =
  childNo
@@ -1581,55 +1581,194 @@
     
-%7D%0A                %7D%0A                return null
+    return true;%0A                    %7D%0A                %7D%0A                %0A                return false;%0A            %7D%0A%0A            public Object next() %7B%0A                return this.next
 ;%0A  
@@ -2002,24 +2002,16 @@
 rator())
-%0A       
  %7B%0A     
@@ -2118,36 +2118,32 @@
                 
-    
 final Object nod
@@ -2151,32 +2151,49 @@
  = iter.next();%0A
+                %0A
                 

Fix a problem with a trailing null value when enumerating a Filtered Node