001: /*
002: * Copyright 2006-2007 The Scriptella Project Team.
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: package scriptella.configuration;
017:
018: import org.w3c.dom.Document;
019: import org.w3c.dom.Element;
020: import org.w3c.dom.Node;
021: import org.w3c.dom.NodeList;
022: import scriptella.expression.PropertiesSubstitutor;
023:
024: import java.net.URL;
025: import java.util.ArrayList;
026: import java.util.List;
027: import java.util.Set;
028:
029: /**
030: * Represents XML element
031: *
032: * @author Fyodor Kupolov
033: * @version 1.0
034: */
035: public class XmlElement {
036: private Element element;
037: private URL documentUrl;
038: private PropertiesSubstitutor substitutor;
039:
040: public XmlElement(Element element, URL documentUrl,
041: PropertiesSubstitutor substitutor) {
042: this .element = element;
043: this .documentUrl = documentUrl;
044: this .substitutor = substitutor;
045: }
046:
047: public XmlElement(Element element, XmlElement parent) {
048: this (element, parent.documentUrl, parent.substitutor);
049: }
050:
051: public String getTagName() {
052: return element.getTagName();
053: }
054:
055: public Element getElement() {
056: return element;
057: }
058:
059: public URL getDocumentUrl() {
060: return documentUrl;
061: }
062:
063: protected List<XmlElement> getChildren() {
064: return asList(element.getChildNodes());
065: }
066:
067: public String getXPath() {
068: List<String> l = new ArrayList<String>();
069: Node cur = element;
070: StringBuilder tmp = new StringBuilder();
071:
072: while (!(cur instanceof Document)) {
073: int pos = 1;
074: Node sib = cur;
075: final String curTagName = ((Element) cur).getTagName();
076:
077: while (sib != null) {
078: sib = sib.getPreviousSibling();
079:
080: if ((sib != null) && sib instanceof Element) {
081: Element ee = (Element) sib;
082:
083: if (curTagName.equals(ee.getTagName())) {
084: pos++;
085: }
086: }
087: }
088:
089: tmp.setLength(0);
090: tmp.append(curTagName);
091: cur = cur.getParentNode();
092: if (!(cur instanceof Document)) {
093: tmp.append('[');
094: tmp.append(pos);
095: tmp.append(']');
096: }
097: l.add(tmp.toString());
098:
099: }
100:
101: StringBuilder res = new StringBuilder(100);
102:
103: for (int i = l.size() - 1; i >= 0; i--) {
104: res.append('/');
105: res.append(l.get(i));
106: }
107:
108: return res.toString();
109: }
110:
111: public List<XmlElement> getChildren(final String name) {
112: List<XmlElement> res = new ArrayList<XmlElement>();
113: Node node = element.getFirstChild();
114:
115: while (node != null) {
116: if (node instanceof Element) {
117: if (name.equals(((Element) node).getTagName())) {
118: res.add(new XmlElement((Element) node, this ));
119: }
120: }
121:
122: node = node.getNextSibling();
123: }
124:
125: return res;
126: }
127:
128: public List<XmlElement> getChildren(final Set<String> names) {
129: List<XmlElement> res = new ArrayList<XmlElement>();
130: Node node = element.getFirstChild();
131:
132: while (node != null) {
133: if (node instanceof Element) {
134: if (names.contains(((Element) node).getTagName())) {
135: res.add(new XmlElement((Element) node, this ));
136: }
137: }
138:
139: node = node.getNextSibling();
140: }
141:
142: return res;
143: }
144:
145: public XmlElement getChild(final String name) {
146: Node node = element.getFirstChild();
147:
148: while (node != null) {
149: if (node instanceof Element) {
150: if (name.equals(((Element) node).getTagName())) {
151: return new XmlElement((Element) node, this );
152: }
153: }
154:
155: node = node.getNextSibling();
156: }
157:
158: return null;
159: }
160:
161: protected List<XmlElement> asList(final NodeList list) {
162: List<XmlElement> result = new ArrayList<XmlElement>();
163: Node node = element.getFirstChild();
164:
165: while (node != null) {
166: if (node instanceof Element) {
167: result.add(new XmlElement((Element) node, this ));
168: }
169:
170: node = node.getNextSibling();
171: }
172:
173: return result;
174: }
175:
176: /**
177: * Gets the value of attribute.
178: * <p>Additionally property {@link #expandProperties(String) expansion} is performed.
179: * @param attribute attribute name.
180: * @return value of the attribute or null if attribute is absent or has empty value.
181: */
182: public String getAttribute(final String attribute) {
183: final String a = element.getAttribute(attribute);
184:
185: return ((a != null) && (a.length() == 0)) ? null
186: : expandProperties(a);
187: }
188:
189: /**
190: * Returns the value of boolean attribute.
191: * @param attribute attribute name.
192: * @param defaultValue default value to use if attribute value unspecified.
193: * @see #getAttribute(String)
194: */
195: protected boolean getBooleanAttribute(final String attribute,
196: final boolean defaultValue) {
197: final String a = getAttribute(attribute);
198:
199: if (a == null) {
200: return defaultValue;
201: }
202:
203: if ("true".equalsIgnoreCase(a) || "1".equalsIgnoreCase(a)
204: || "on".equalsIgnoreCase(a)
205: || "yes".equalsIgnoreCase(a)) {
206: return true;
207: }
208:
209: if ("false".equalsIgnoreCase(a) || "0".equalsIgnoreCase(a)
210: || "off".equalsIgnoreCase(a)
211: || "no".equalsIgnoreCase(a)) {
212: return false;
213: }
214:
215: throw new ConfigurationException("Unrecognized value '" + a
216: + "' of boolean attribute " + attribute
217: + ". Valid values: yes/no, true/false, 1/0, on/off",
218: this );
219: }
220:
221: /**
222: * Expands properties in a string.
223: * @param s string to expand properties.
224: * @return string with substituted properties.
225: */
226: public String expandProperties(final String s) {
227: return substitutor.substitute(s);
228: }
229:
230: }
|