001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.jxpath.ri.model.dom;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.commons.jxpath.ri.model.NodeIterator;
023import org.apache.commons.jxpath.ri.model.NodePointer;
024import org.w3c.dom.Attr;
025import org.w3c.dom.Document;
026import org.w3c.dom.NamedNodeMap;
027import org.w3c.dom.Node;
028
029/**
030 * An iterator of namespaces of a DOM Node.
031 *
032 * @author Dmitri Plotnikov
033 * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
034 */
035public class DOMNamespaceIterator implements NodeIterator {
036    private NodePointer parent;
037    private List attributes;
038    private int position = 0;
039
040    /**
041     * Create a new DOMNamespaceIterator.
042     * @param parent parent pointer
043     */
044    public DOMNamespaceIterator(NodePointer parent) {
045        this.parent = parent;
046        attributes = new ArrayList();
047        collectNamespaces(attributes, (Node) parent.getNode());
048    }
049
050    /**
051     * Collect namespaces from attribute nodes.
052     * @param attributes attribute list
053     * @param node target node
054     */
055    private void collectNamespaces(List attributes, Node node) {
056        Node parent = node.getParentNode();
057        if (parent != null) {
058            collectNamespaces(attributes, parent);
059        }
060        if (node.getNodeType() == Node.DOCUMENT_NODE) {
061            node = ((Document) node).getDocumentElement();
062        }
063        if (node.getNodeType() == Node.ELEMENT_NODE) {
064            NamedNodeMap map = node.getAttributes();
065            int count = map.getLength();
066            for (int i = 0; i < count; i++) {
067                Attr attr = (Attr) map.item(i);
068                String prefix = DOMNodePointer.getPrefix(attr);
069                String name = DOMNodePointer.getLocalName(attr);
070                if ((prefix != null && prefix.equals("xmlns"))
071                    || (prefix == null && name.equals("xmlns"))) {
072                    attributes.add(attr);
073                }
074            }
075        }
076    }
077
078    public NodePointer getNodePointer() {
079        if (position == 0) {
080            if (!setPosition(1)) {
081                return null;
082            }
083            position = 0;
084        }
085        int index = position - 1;
086        if (index < 0) {
087            index = 0;
088        }
089        String prefix = "";
090        Attr attr = (Attr) attributes.get(index);
091        String name = attr.getPrefix();
092        if (name != null && name.equals("xmlns")) {
093            prefix = DOMNodePointer.getLocalName(attr);
094        }
095        return new NamespacePointer(parent, prefix, attr.getValue());
096    }
097
098    public int getPosition() {
099        return position;
100    }
101
102    public boolean setPosition(int position) {
103        this.position = position;
104        return position >= 1 && position <= attributes.size();
105    }
106}