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: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.compiler.model;
020:
021: import org.w3c.dom.Element;
022: import org.w3c.dom.NodeList;
023: import org.w3c.dom.Node;
024: import org.w3c.dom.Attr;
025: import org.w3c.dom.Text;
026:
027: import java.util.ArrayList;
028:
029: public abstract class XmlElementSupport {
030: private String _comment;
031:
032: public void setComment(String comment) {
033: _comment = comment;
034: }
035:
036: public final void writeXML(XmlModelWriter xw, Element element) {
037: if (_comment != null) {
038: xw.addComment(element, ' ' + _comment + ' ');
039: }
040: writeToElement(xw, element);
041: }
042:
043: protected abstract void writeToElement(XmlModelWriter xw,
044: Element element);
045:
046: protected final void setElementAttributeMayBeEmpty(Element element,
047: String attrName, String value) {
048: if (value != null) {
049: String existingAttr = getElementAttribute(element, attrName);
050: if (existingAttr == null || existingAttr.length() == 0) {
051: element.setAttribute(attrName, value);
052: }
053: }
054: }
055:
056: protected final void setElementAttribute(Element element,
057: String attrName, String value) {
058: if (value != null && value.length() > 0) {
059: String existingAttr = getElementAttribute(element, attrName);
060: if (existingAttr == null || existingAttr.length() == 0) {
061: element.setAttribute(attrName, value);
062: }
063: }
064: }
065:
066: protected final void setElementAttribute(Element element,
067: String attrName, Boolean value) {
068: if (value != null) {
069: String existingAttr = getElementAttribute(element, attrName);
070: if (existingAttr == null || existingAttr.length() == 0) {
071: element.setAttribute(attrName, value.toString());
072: }
073: }
074: }
075:
076: /**
077: * Gets the attribute value, or <code>null</code> (unlike <code>Element.getAttribute</code>).
078: */
079: protected String getElementAttribute(Element element,
080: String attrName) {
081: Attr attr = element.getAttributeNode(attrName);
082: return attr != null ? attr.getValue() : null;
083: }
084:
085: protected final void setElementAttribute(Element element,
086: String attrName, boolean value) {
087: if (value) {
088: String existingAttr = getElementAttribute(element, attrName);
089: if (existingAttr == null) {
090: element.setAttribute(attrName, Boolean.toString(value));
091: }
092: }
093: }
094:
095: protected final Element findChildElement(XmlModelWriter xw,
096: Element parent, String childName) {
097: return findChildElement(xw, parent, childName, null, null,
098: false, null);
099: }
100:
101: protected final Element findChildElement(XmlModelWriter xw,
102: Element parent, String childName,
103: boolean createIfNotPresent, String[] createOrder) {
104: return findChildElement(xw, parent, childName, null, null,
105: createIfNotPresent, createOrder);
106: }
107:
108: protected final Element findChildElementWithChildText(
109: XmlModelWriter xw, Element parent, String childName,
110: String childSubElementName, String textValue,
111: boolean createIfNotPresent, String[] createOrder) {
112: Element[] matchingChildren = getChildElements(parent, childName);
113:
114: for (int i = 0; i < matchingChildren.length; i++) {
115: Element childSubElement = findChildElement(xw,
116: matchingChildren[i], childSubElementName, false,
117: createOrder);
118: if (childSubElement != null) {
119: String text = getTextContent(childSubElement);
120: if (textValue.equals(text)) {
121: return childSubElement;
122: }
123: }
124: }
125:
126: if (createIfNotPresent) {
127: Element newChild = xw.addElement(parent, childName);
128: xw.addElementWithText(newChild, childSubElementName,
129: textValue);
130: return newChild;
131: }
132:
133: return null;
134: }
135:
136: protected final Element findChildElement(XmlModelWriter xw,
137: Element parent, String childName, String keyAttributeName,
138: String keyAttributeValue) {
139: return findChildElement(xw, parent, childName,
140: keyAttributeName, keyAttributeValue, false, null);
141: }
142:
143: /**
144: * Find a child element by name, and optionally add it if it isn't present.
145: *
146: * @param xw the XmlModelWriter
147: * @param parent the parent element
148: * @param childName the name of the desired child element
149: * @param keyAttributeName the name of a key attribute in the child element by which to restrict the search.
150: * May be <code>null</code>, in which case there is no restriction.
151: * @param keyAttributeValue the value of a key attribute in the child element by which to restrict the search.
152: * Only used if <code>keyAttributeName</code> is not <code>null</code>. This value may be
153: * <code>null</code>, which means that the target node must have a null value.
154: * @param createIfNotPresent if <code>true</code>, the node will be created if it's not present.
155: * @param createOrder an array of Strings that describes the order of insertion. May be <code>null</code>, in
156: * which case a newly-created node is appended to the parent.
157: * @return the node.
158: */
159: protected final Element findChildElement(XmlModelWriter xw,
160: Element parent, String childName, String keyAttributeName,
161: String keyAttributeValue, boolean createIfNotPresent,
162: String[] createOrder) {
163: NodeList childNodes = parent.getChildNodes();
164:
165: for (int i = 0; i < childNodes.getLength(); ++i) {
166: Node node = childNodes.item(i);
167:
168: if (node instanceof Element) {
169: Element childElement = (Element) node;
170:
171: if (childName.equals(childElement.getTagName())) {
172: // If there's no target key attribute to match, just return the element.
173: if (keyAttributeName == null) {
174: return childElement;
175: }
176:
177: // Return the element if the key attribute values match (or if both are null).
178: String childElementAttributeValue = getElementAttribute(
179: childElement, keyAttributeName);
180: if ((keyAttributeValue == null && childElementAttributeValue == null)
181: || (keyAttributeValue != null && keyAttributeValue
182: .equals(childElementAttributeValue))) {
183: return childElement;
184: }
185: }
186: }
187: }
188:
189: if (createIfNotPresent) {
190: Element newChild = xw.getDocument()
191: .createElement(childName);
192: Node insertBefore = null;
193:
194: if (createOrder != null) {
195: for (int i = 0; i < createOrder.length; i++) {
196: String nodeName = createOrder[i];
197: if (nodeName.equals(childName)) {
198: while (++i < createOrder.length) {
199: insertBefore = findChildElement(xw, parent,
200: createOrder[i], false, null);
201: if (insertBefore != null) {
202: break;
203: }
204: }
205: break;
206: }
207: }
208: }
209:
210: if (insertBefore != null) {
211: parent.insertBefore(newChild, insertBefore);
212: } else {
213: parent.appendChild(newChild);
214: }
215:
216: if (keyAttributeName != null && keyAttributeValue != null) {
217: newChild.setAttribute(keyAttributeName,
218: keyAttributeValue);
219: }
220: return newChild;
221: }
222:
223: return null;
224: }
225:
226: protected Element[] getChildElements(Element element,
227: String nameFilter) {
228: NodeList children = element.getChildNodes();
229: ArrayList list = new ArrayList(children.getLength());
230: for (int i = 0; i < children.getLength(); ++i) {
231: Node node = children.item(i);
232: if (node instanceof Element) {
233: if (nameFilter == null
234: || nameFilter.equals(((Element) node)
235: .getTagName())) {
236: list.add(node);
237: }
238: }
239: }
240:
241: return (Element[]) list.toArray(new Element[list.size()]);
242: }
243:
244: public static boolean isWhiteSpace(String s) {
245: for (int j = 0; j < s.length(); ++j) {
246: if (!Character.isWhitespace(s.charAt(j))) {
247: return false;
248: }
249: }
250:
251: return true;
252: }
253:
254: public static String getTextContent(Element element) // TODO: move to a utils class, so XmlModelWriter is independentf
255: {
256: NodeList children = element.getChildNodes();
257: String retVal = null;
258:
259: for (int i = 0, len = children.getLength(); i < len; ++i) {
260: Node child = children.item(i);
261: if (!(child instanceof Text)) {
262: return null;
263: }
264: String text = child.getNodeValue();
265: if (!isWhiteSpace(text)) {
266: if (retVal != null) {
267: return null;
268: }
269: retVal = text;
270: }
271: }
272:
273: return retVal;
274: }
275: }
|