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