001    /*
002     * Copyright 2002 - 2007 JEuclid, http://jeuclid.sf.net
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    /* $Id: AbstractPartialNodeImpl.java 363 2007-06-29 16:24:32Z maxberger $ */
018    
019    package net.sourceforge.jeuclid.dom;
020    
021    import java.util.List;
022    import java.util.Vector;
023    
024    import org.w3c.dom.DOMException;
025    import org.w3c.dom.Document;
026    import org.w3c.dom.NamedNodeMap;
027    import org.w3c.dom.Node;
028    import org.w3c.dom.UserDataHandler;
029    
030    /**
031     * Partial implementation of org.w3c.dom.Node
032     * <p>
033     * This implements only the functions necessary for MathElements. Feel free to
034     * implement whatever functions you need.
035     * 
036     * @author Max Berger
037     * @version $Revision: 363 $
038     */
039    public abstract class AbstractPartialNodeImpl implements Node {
040    
041        private static final String COULD_NOT_FIND_NODE = "Could not find node: ";
042    
043        private final List<Node> children = new Vector<Node>();
044    
045        private Node parent;
046    
047        /**
048         * @see org.w3c.dom.NodeList
049         */
050        public static class NodeList implements org.w3c.dom.NodeList {
051            private final List<Node> children;
052    
053            /**
054             * default constructor.
055             * 
056             * @param childs
057             *            list of children.
058             */
059            protected NodeList(final List<Node> childs) {
060                this.children = childs;
061            }
062    
063            /** {@inheritDoc} */
064            public final int getLength() {
065                return this.children.size();
066            }
067    
068            /** {@inheritDoc} */
069            public final Node item(final int index) {
070                return this.children.get(index);
071            }
072        }
073    
074        /** {@inheritDoc} */
075        public final String lookupNamespaceURI(final String prefix) {
076            throw new UnsupportedOperationException("lookupNamespaceURI");
077        }
078    
079        /** {@inheritDoc} */
080        public final void normalize() {
081            throw new UnsupportedOperationException("normalize");
082        }
083    
084        /** {@inheritDoc} */
085        public final org.w3c.dom.NodeList getChildNodes() {
086            return new NodeList(this.children);
087        }
088    
089        /** {@inheritDoc} */
090        public final Node getFirstChild() {
091            try {
092                return this.children.get(0);
093            } catch (final IndexOutOfBoundsException e) {
094                return null;
095            }
096        }
097    
098        /** {@inheritDoc} */
099        public final boolean isSameNode(final Node other) {
100            return this.equals(other);
101        }
102    
103        /** {@inheritDoc} */
104        public Node appendChild(final Node newChild) {
105            if (newChild instanceof AbstractPartialNodeImpl) {
106                this.children.add(newChild);
107                ((AbstractPartialNodeImpl) newChild).parent = this;
108                return newChild;
109            } else {
110                throw new IllegalArgumentException(
111                        "Can only add children of type "
112                                + AbstractPartialNodeImpl.class.getName()
113                                + " to " + this.getClass().getName());
114            }
115        }
116    
117        /** {@inheritDoc} */
118        public String getTextContent() {
119            final StringBuilder builder = new StringBuilder();
120            for (final Node n : this.children) {
121                builder.append(n.getTextContent());
122            }
123            return builder.toString();
124        }
125    
126        /** {@inheritDoc} */
127        public void setTextContent(final String newTextContent) {
128            this.children.clear();
129            if (newTextContent != null && newTextContent.length() > 0) {
130                this.children.add(new PartialTextImpl(newTextContent));
131            }
132        }
133    
134        /** {@inheritDoc} */
135        public final Node cloneNode(final boolean deep) {
136            throw new UnsupportedOperationException("cloneNode");
137        }
138    
139        /** {@inheritDoc} */
140        public String getNodeValue() {
141            return null;
142        }
143    
144        /** {@inheritDoc} */
145        public final String getNamespaceURI() {
146            return null;
147        }
148    
149        /** {@inheritDoc} */
150        public final Node getParentNode() {
151            return this.parent;
152        }
153    
154        /** {@inheritDoc} */
155        public final String getBaseURI() {
156            throw new UnsupportedOperationException("getBaseURI");
157        }
158    
159        /** {@inheritDoc} */
160        public final String getPrefix() {
161            throw new UnsupportedOperationException("getPrefix");
162        }
163    
164        /** {@inheritDoc} */
165        public NamedNodeMap getAttributes() {
166            return null;
167        }
168    
169        /** {@inheritDoc} */
170        public final boolean hasChildNodes() {
171            return !this.children.isEmpty();
172        }
173    
174        /** {@inheritDoc} */
175        public final boolean isDefaultNamespace(final String namespaceURI) {
176            throw new UnsupportedOperationException("isDefaultNamespace");
177        }
178    
179        /** {@inheritDoc} */
180        public Node replaceChild(final Node newChild, final Node oldChild) {
181            // TODO: If newChild is already in the tree, it is supposed to be
182            // removed.
183            for (int i = 0; i < this.children.size(); i++) {
184                final Node oldChildAtIndex = this.children.get(i);
185                if (oldChildAtIndex.equals(oldChild)) {
186                    this.children.set(i, newChild);
187                    return oldChildAtIndex;
188                }
189            }
190            throw new DOMException(DOMException.NOT_FOUND_ERR,
191                    AbstractPartialNodeImpl.COULD_NOT_FIND_NODE + oldChild);
192        }
193    
194        /** {@inheritDoc} */
195        public final Node insertBefore(final Node newChild, final Node refChild) {
196            throw new UnsupportedOperationException("insertBefore");
197        }
198    
199        /** {@inheritDoc} */
200        public final boolean isEqualNode(final Node arg) {
201            throw new UnsupportedOperationException("isEqualNode");
202        }
203    
204        /** {@inheritDoc} */
205        public final Node getNextSibling() {
206            Node retval;
207            try {
208                final List<Node> parentsChildren = ((AbstractPartialNodeImpl) this.parent).children;
209                retval = parentsChildren.get(parentsChildren.indexOf(this) + 1);
210            } catch (final NullPointerException ne) {
211                retval = null;
212            } catch (final IndexOutOfBoundsException iobe) {
213                retval = null;
214            }
215            return retval;
216        }
217    
218        /** {@inheritDoc} */
219        public final boolean hasAttributes() {
220            return this.getAttributes().getLength() > 0;
221        }
222    
223        /** {@inheritDoc} */
224        public final short compareDocumentPosition(final Node other) {
225            throw new UnsupportedOperationException("compareDocumentPosition");
226        }
227    
228        /** {@inheritDoc} */
229        public final Node removeChild(final Node oldChild) {
230            for (int i = 0; i < this.children.size(); i++) {
231                final Node oldChildAtIndex = this.children.get(i);
232                if (oldChildAtIndex.equals(oldChild)) {
233                    this.children.remove(i);
234                    return oldChildAtIndex;
235                }
236            }
237            throw new DOMException(DOMException.NOT_FOUND_ERR,
238                    AbstractPartialNodeImpl.COULD_NOT_FIND_NODE + oldChild);
239    
240        }
241    
242        /** {@inheritDoc} */
243        public final Object getFeature(final String feature, final String version) {
244            throw new UnsupportedOperationException("getFeature");
245        }
246    
247        /** {@inheritDoc} */
248        public final Node getLastChild() {
249            final List<Node> theChildren = this.children;
250            final int size = theChildren.size();
251            if (size == 0) {
252                return null;
253            } else {
254                return theChildren.get(size - 1);
255            }
256        }
257    
258        /** {@inheritDoc} */
259        public String getLocalName() {
260            return null;
261        }
262    
263        /** {@inheritDoc} */
264        public final Document getOwnerDocument() {
265            throw new UnsupportedOperationException("getOwnerDocument");
266        }
267    
268        /** {@inheritDoc} */
269        public final Node getPreviousSibling() {
270            throw new UnsupportedOperationException("getPreviousSibling");
271        }
272    
273        /** {@inheritDoc} */
274        public final boolean isSupported(final String feature,
275                final String version) {
276            throw new UnsupportedOperationException("isSupported");
277        }
278    
279        /** {@inheritDoc} */
280        public final String lookupPrefix(final String namespaceURI) {
281            throw new UnsupportedOperationException("lookupPrefix");
282        }
283    
284        /** {@inheritDoc} */
285        public final void setNodeValue(final String nodeValue) {
286            throw new UnsupportedOperationException("setNodeValue");
287        }
288    
289        /** {@inheritDoc} */
290        public final void setPrefix(final String prefix) {
291            throw new UnsupportedOperationException("setPrefix");
292        }
293    
294        /** {@inheritDoc} */
295        public final Object getUserData(final String key) {
296            throw new UnsupportedOperationException("getUserData");
297        }
298    
299        /** {@inheritDoc} */
300        public final Object setUserData(final String key, final Object data,
301                final UserDataHandler handler) {
302            throw new UnsupportedOperationException("setUserData");
303        }
304    
305    }