001    /*
002    // $Id: //open/util/resgen/src/org/eigenbase/xom/wrappers/W3CDOMWrapper.java#5 $
003    // Package org.eigenbase.xom is an XML Object Mapper.
004    // Copyright (C) 2005-2005 The Eigenbase Project
005    // Copyright (C) 2005-2005 Disruptive Tech
006    // Copyright (C) 2005-2005 LucidEra, Inc.
007    // Portions Copyright (C) 2001-2005 Kana Software, Inc. and others.
008    //
009    // This library is free software; you can redistribute it and/or modify it
010    // under the terms of the GNU Lesser General Public License as published by the
011    // Free Software Foundation; either version 2 of the License, or (at your
012    // option) any later version approved by The Eigenbase Project.
013    //
014    // This library is distributed in the hope that it will be useful,
015    // but WITHOUT ANY WARRANTY; without even the implied warranty of
016    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017    // GNU Lesser General Public License for more details.
018    //
019    // You should have received a copy of the GNU Lesser General Public License
020    // along with this library; if not, write to the Free Software
021    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022    //
023    // dsommerfield, 16 July, 2001
024    */
025    
026    package org.eigenbase.xom.wrappers;
027    
028    import org.eigenbase.xom.*;
029    import org.w3c.dom.CharacterData;
030    import org.w3c.dom.*;
031    
032    /**
033     * This implementation of DOMWrapper wraps any w3c DOM-compliant java
034     * XML Parser.
035     */
036    public class W3CDOMWrapper implements DOMWrapper {
037    
038        final Node node;
039        private final Locator locator;
040    
041        /**
042         * W3CDOMWrapper parses XML based on a Node.  The Node may be either an
043         * Element or some form of text node.
044         *
045         * @param node DOM Node
046         * @param locator Callback to find location of node. May be null.
047         */
048        public W3CDOMWrapper(Node node, Locator locator)
049        {
050            this.node = node;
051            this.locator = locator;
052        }
053    
054        /**
055         * Map the Node's type to DOMWrapper's simplified concept of type.
056         */
057        public int getType()
058        {
059            int nodeType = node.getNodeType();
060            switch (nodeType) {
061            case Node.ELEMENT_NODE:
062                return ELEMENT;
063            case Node.COMMENT_NODE:
064                return COMMENT;
065            case Node.CDATA_SECTION_NODE:
066                return CDATA;
067            case Node.TEXT_NODE:
068                return FREETEXT;
069            default:
070                return UNKNOWN;
071            }
072        }
073    
074        /**
075         * Retrieve the tag name directly.  Return null immediately if not an
076         * element.
077         **/
078        public String getTagName()
079        {
080            if (getType() != ELEMENT) {
081                return null;
082            }
083            return ((Element)node).getTagName();
084        }
085    
086        /**
087         * Return the attribute.  Return null if the attribute isn't defined,
088         * or if not an element.  This behavior differs from the underlying DOM,
089         * which returns an empty string for undefined attributes.
090         */
091        public String getAttribute(String attrName)
092        {
093            if (getType() != ELEMENT) {
094                return null;
095            }
096            String attrVal = ((Element)node).getAttribute(attrName);
097            if (attrVal == null || attrVal.length() == 0) {
098                return null;
099            } else {
100                return attrVal;
101            }
102        }
103    
104        // implement DOMWrapper
105        public String[] getAttributeNames()
106        {
107            NamedNodeMap map = node.getAttributes();
108            int count = map.getLength();
109            String[] attributeNames = new String[count];
110            for (int i = 0; i < count; i++) {
111                attributeNames[i] = map.item(i).getLocalName();
112            }
113            return attributeNames;
114        }
115    
116        /**
117         * Recursively unwrap and create the contained text.  If the node is a
118         * comment, return the comment text; but ignore comments inside elements.
119         **/
120        public String getText()
121        {
122            if (node instanceof Comment) {
123                return ((Comment)node).getData();
124            } else {
125                StringBuffer sbuf = new StringBuffer();
126                appendNodeText(node, sbuf);
127                return sbuf.toString();
128            }
129        }
130    
131        // implement DOMWrapper
132        public String toXML()
133        {
134            boolean onlyElements = false;
135            return XOMUtil.wrapperToXml(this, onlyElements);
136        }
137    
138        /**
139         * Helper to collect all Text nodes into a buffer.
140         */
141        private static void appendNodeText(Node node, StringBuffer sbuf)
142        {
143            if (node instanceof Comment) {
144                // ignore it
145            } else if (node instanceof CharacterData) {
146                // Text
147                sbuf.append(((CharacterData)node).getData());
148            } else if (node instanceof Element) {
149                NodeList nodeList = node.getChildNodes();
150                for (int i = 0; i < nodeList.getLength(); i++) {
151                    appendNodeText(nodeList.item(i), sbuf);
152                }
153            }
154        }
155    
156        /**
157         * Retrieve all children, and build an array of W3CDOMWrappers around
158         * each child that is of TEXT or ELEMENT type to return.
159         */
160        public DOMWrapper[] getChildren()
161        {
162            if (getType() != ELEMENT) {
163                return new DOMWrapper[0];
164            }
165            NodeList nodeList = node.getChildNodes();
166    
167            // Count the elements that are TEXT or ELEMENTs.
168            int count = 0;
169            for (int i = 0; i < nodeList.getLength(); i++) {
170                Node nextNode = nodeList.item(i);
171                if (nextNode instanceof Element || nextNode instanceof Text) {
172                    count++;
173                }
174            }
175    
176            // Create and populate the array
177            DOMWrapper[] ret = new DOMWrapper[count];
178            count = 0;
179            for (int i = 0; i < nodeList.getLength(); i++) {
180                Node nextNode = nodeList.item(i);
181                if (nextNode instanceof Element || nextNode instanceof Text) {
182                    ret[count++] = new W3CDOMWrapper(nextNode, locator);
183                }
184            }
185    
186            // Done.
187            return ret;
188        }
189    
190        /**
191         * Retrieve all children, and build an array of W3CDOMWrappers around
192         * each ELEMENT child.
193         */
194        public DOMWrapper[] getElementChildren()
195        {
196            if (getType() != ELEMENT) {
197                return new DOMWrapper[0];
198            }
199            NodeList nodeList = node.getChildNodes();
200    
201            // Count the elements that are TEXT or ELEMENTs.
202            int count = 0;
203            for (int i = 0; i < nodeList.getLength(); i++) {
204                Node nextNode = nodeList.item(i);
205                if (nextNode instanceof Element) {
206                    count++;
207                }
208            }
209    
210            // Create and populate the array
211            DOMWrapper[] ret = new DOMWrapper[count];
212            count = 0;
213            for (int i = 0; i < nodeList.getLength(); i++) {
214                Node nextNode = nodeList.item(i);
215                if (nextNode instanceof Element) {
216                    ret[count++] = new W3CDOMWrapper(nextNode, locator);
217                }
218            }
219    
220            // Done.
221            return ret;
222        }
223    
224        public Location getLocation()
225        {
226            return locator.getLocation(this);
227        }
228    }
229    
230    // End W3CDOMWrapper.java