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.Closure;
021    import groovy.lang.GroovyObject;
022    import groovy.lang.GroovyRuntimeException;
023    
024    import java.io.IOException;
025    import java.io.Writer;
026    import java.util.Iterator;
027    import java.util.Map;
028    
029    import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
030    
031    /**
032     * @author John Wilson
033     */
034    
035    public class NodeChild extends GPathResult {
036        private final Node node;
037    
038        public NodeChild(final Node node, final GPathResult parent, final String namespacePrefix, final Map namespaceTagHints) {
039            super(parent, node.name(), namespacePrefix, namespaceTagHints);
040            this.node = node;
041        }
042    
043        public NodeChild(final Node node, final GPathResult parent, final Map namespaceTagHints) {
044            this(node, parent, "*", namespaceTagHints);
045        }
046    
047        public int size() {
048            return 1;
049        }
050    
051        public String text() {
052            return this.node.text();
053        }
054    
055        public GPathResult parents() {
056            // TODO Auto-generated method stub
057            throw new GroovyRuntimeException("parents() not implemented yet");
058        }
059    
060        public Iterator iterator() {
061            return new Iterator() {
062                private boolean hasNext = true;
063    
064                public boolean hasNext() {
065                    return this.hasNext;
066                }
067    
068                public Object next() {
069                    try {
070                        return (this.hasNext) ? NodeChild.this : null;
071                    } finally {
072                        this.hasNext = false;
073                    }
074                }
075    
076                public void remove() {
077                    throw new UnsupportedOperationException();
078                }
079            };
080        }
081    
082        public Iterator nodeIterator() {
083            return new Iterator() {
084                private boolean hasNext = true;
085    
086                public boolean hasNext() {
087                    return this.hasNext;
088                }
089    
090                public Object next() {
091                    try {
092                        return (this.hasNext) ? NodeChild.this.node : null;
093                    } finally {
094                        this.hasNext = false;
095                    }
096                }
097    
098                public void remove() {
099                    throw new UnsupportedOperationException();
100                }
101            };
102        }
103    
104        public Object getAt(final int index) {
105            if (index == 0) {
106                return node;
107            } else {
108                throw new ArrayIndexOutOfBoundsException(index);
109            }
110        }
111    
112        public Map attributes() {
113            return this.node.attributes();
114        }
115    
116        public Iterator childNodes() {
117            return this.node.childNodes();
118        }
119    
120        public GPathResult find(final Closure closure) {
121            if (DefaultTypeTransformation.castToBoolean(closure.call(new Object[]{this.node}))) {
122                return this;
123            } else {
124                return new NoChildren(this, "", this.namespaceTagHints);
125            }
126        }
127    
128        public GPathResult findAll(final Closure closure) {
129            return find(closure);
130        }
131    
132        public void build(final GroovyObject builder) {
133            this.node.build(builder, this.namespaceMap, this.namespaceTagHints);
134        }
135    
136        public Writer writeTo(final Writer out) throws IOException {
137            return this.node.writeTo(out);
138        }
139    
140        protected void replaceNode(final Closure newValue) {
141            this.node.replaceNode(newValue, this);
142        }
143    
144        protected void replaceBody(final Object newValue) {
145            this.node.replaceBody(newValue);
146        }
147    
148        protected void appendNode(final Object newValue) {
149            this.node.appendNode(newValue, this);
150        }
151    }