1 package org.apache.velocity.anakia;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import org.jdom.Element;
23 import org.jdom.Namespace;
24 import org.jdom.output.XMLOutputter;
25 import java.util.List;
26
27 /**
28 * A JDOM {@link Element} that is tailored for Anakia needs. It has
29 * {@link #selectNodes(String)} method as well as a {@link #toString()} that
30 * outputs the XML serialized form of the element. This way it acts in much the
31 * same way as a single-element {@link NodeList} would.
32 *
33 * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
34 * @version $Id: AnakiaElement.java 463298 2006-10-12 16:10:32Z henning $
35 */
36 public class AnakiaElement extends Element
37 {
38 /**
39 * Version Id for serializable
40 */
41 private static final long serialVersionUID = 8429597252274491314L;
42
43 private static final XMLOutputter DEFAULT_OUTPUTTER = new XMLOutputter();
44
45 static
46 {
47 DEFAULT_OUTPUTTER.getFormat().setLineSeparator(System.getProperty("line.separator"));
48 }
49
50 /**
51 * <p>
52 * This will create a new <code>AnakiaElement</code>
53 * with the supplied (local) name, and define
54 * the <code>{@link Namespace}</code> to be used.
55 * If the provided namespace is null, the element will have
56 * no namespace.
57 * </p>
58 *
59 * @param name <code>String</code> name of element.
60 * @param namespace <code>Namespace</code> to put element in.
61 */
62 public AnakiaElement(String name, Namespace namespace)
63 {
64 super(name, namespace);
65 }
66
67 /**
68 * <p>
69 * This will create an <code>AnakiaElement</code> in no
70 * <code>{@link Namespace}</code>.
71 * </p>
72 *
73 * @param name <code>String</code> name of element.
74 */
75 public AnakiaElement(String name)
76 {
77 super(name);
78 }
79
80 /**
81 * <p>
82 * This will create a new <code>AnakiaElement</code> with
83 * the supplied (local) name, and specifies the URI
84 * of the <code>{@link Namespace}</code> the <code>Element</code>
85 * should be in, resulting it being unprefixed (in the default
86 * namespace).
87 * </p>
88 *
89 * @param name <code>String</code> name of element.
90 * @param uri <code>String</code> URI for <code>Namespace</code> element
91 * should be in.
92 */
93 public AnakiaElement(String name, String uri)
94 {
95 super(name, uri);
96 }
97
98 /**
99 * <p>
100 * This will create a new <code>AnakiaElement</code> with
101 * the supplied (local) name, and specifies the prefix and URI
102 * of the <code>{@link Namespace}</code> the <code>Element</code>
103 * should be in.
104 * </p>
105 *
106 * @param name <code>String</code> name of element.
107 * @param prefix The prefix of the element.
108 * @param uri <code>String</code> URI for <code>Namespace</code> element
109 * should be in.
110 */
111 public AnakiaElement(String name, String prefix, String uri)
112 {
113 super(name, prefix, uri);
114 }
115
116 /**
117 * Applies an XPath expression to this element and returns the resulting
118 * node list. In order for this method to work, your application must have
119 * access to <a href="http://code.werken.com">werken.xpath</a> library
120 * classes. The implementation does cache the parsed format of XPath
121 * expressions in a weak hash map, keyed by the string representation of
122 * the XPath expression. As the string object passed as the argument is
123 * usually kept in the parsed template, this ensures that each XPath
124 * expression is parsed only once during the lifetime of the template that
125 * first invoked it.
126 * @param xpathExpression the XPath expression you wish to apply
127 * @return a NodeList representing the nodes that are the result of
128 * application of the XPath to the current element. It can be empty.
129 */
130 public NodeList selectNodes(String xpathExpression)
131 {
132 return new NodeList(XPathCache.getXPath(xpathExpression).applyTo(this), false);
133 }
134
135 /**
136 * Returns the XML serialized form of this element, as produced by the default
137 * {@link XMLOutputter}.
138
139 * @return The XML serialized form of this element, as produced by the default
140 * {@link XMLOutputter}.
141 */
142
143 public String toString()
144 {
145 return DEFAULT_OUTPUTTER.outputString(this);
146 }
147
148 /**
149 * <p>
150 * This returns the full content of the element as a NodeList which
151 * may contain objects of type <code>String</code>, <code>Element</code>,
152 * <code>Comment</code>, <code>ProcessingInstruction</code>,
153 * <code>CDATA</code>, and <code>EntityRef</code>.
154 * The List returned is "live" in document order and modifications
155 * to it affect the element's actual contents. Whitespace content is
156 * returned in its entirety.
157 * </p>
158 *
159 * @return a <code>List</code> containing the mixed content of the
160 * element: may contain <code>String</code>,
161 * <code>{@link Element}</code>, <code>{@link org.jdom.Comment}</code>,
162 * <code>{@link org.jdom.ProcessingInstruction}</code>,
163 * <code>{@link org.jdom.CDATA}</code>, and
164 * <code>{@link org.jdom.EntityRef}</code> objects.
165 */
166 public List getContent()
167 {
168 return new NodeList(super.getContent(), false);
169 }
170
171 /**
172 * <p>
173 * This returns a <code>NodeList</code> of all the child elements
174 * nested directly (one level deep) within this element, as
175 * <code>Element</code> objects. If this target element has no nested
176 * elements, an empty List is returned. The returned list is "live"
177 * in document order and changes to it affect the element's actual
178 * contents.
179 * </p>
180 * <p>
181 * This performs no recursion, so elements nested two levels
182 * deep would have to be obtained with:
183 * <pre>
184 * <code>
185 * Iterator itr = currentElement.getChildren().iterator();
186 * while (itr.hasNext()) {
187 * Element oneLevelDeep = (Element)nestedElements.next();
188 * List twoLevelsDeep = oneLevelDeep.getChildren();
189 * // Do something with these children
190 * }
191 * </code>
192 * </pre>
193 * </p>
194 *
195 * @return list of child <code>Element</code> objects for this element
196 */
197 public List getChildren()
198 {
199 return new NodeList(super.getChildren(), false);
200 }
201
202 /**
203 * <p>
204 * This returns a <code>NodeList</code> of all the child elements
205 * nested directly (one level deep) within this element with the given
206 * local name and belonging to no namespace, returned as
207 * <code>Element</code> objects. If this target element has no nested
208 * elements with the given name outside a namespace, an empty List
209 * is returned. The returned list is "live" in document order
210 * and changes to it affect the element's actual contents.
211 * </p>
212 * <p>
213 * Please see the notes for <code>{@link #getChildren()}</code>
214 * for a code example.
215 * </p>
216 *
217 * @param name local name for the children to match
218 * @return all matching child elements
219 */
220 public List getChildren(String name)
221 {
222 return new NodeList(super.getChildren(name));
223 }
224
225 /**
226 * <p>
227 * This returns a <code>NodeList</code> of all the child elements
228 * nested directly (one level deep) within this element with the given
229 * local name and belonging to the given Namespace, returned as
230 * <code>Element</code> objects. If this target element has no nested
231 * elements with the given name in the given Namespace, an empty List
232 * is returned. The returned list is "live" in document order
233 * and changes to it affect the element's actual contents.
234 * </p>
235 * <p>
236 * Please see the notes for <code>{@link #getChildren()}</code>
237 * for a code example.
238 * </p>
239 *
240 * @param name local name for the children to match
241 * @param ns <code>Namespace</code> to search within
242 * @return all matching child elements
243 */
244 public List getChildren(String name, Namespace ns)
245 {
246 return new NodeList(super.getChildren(name, ns));
247 }
248
249 /**
250 * <p>
251 * This returns the complete set of attributes for this element, as a
252 * <code>NodeList</code> of <code>Attribute</code> objects in no particular
253 * order, or an empty list if there are none.
254 * The returned list is "live" and changes to it affect the
255 * element's actual attributes.
256 * </p>
257 *
258 * @return attributes for the element
259 */
260 public List getAttributes()
261 {
262 return new NodeList(super.getAttributes());
263 }
264 }