EMMA Coverage Report (generated Tue May 18 22:13:27 CDT 2004)
[all classes][org.apache.velocity.anakia]

COVERAGE SUMMARY FOR SOURCE FILE [NodeList.java]

nameclass, %method, %block, %line, %
NodeList.java67%  (2/3)21%  (8/39)11%  (46/425)12%  (12/99)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NodeList100% (1/1)19%  (7/37)11%  (43/399)12%  (11/91)
NodeList (): void 0%   (0/1)0%   (0/8)0%   (0/3)
NodeList (Document): void 0%   (0/1)0%   (0/4)0%   (0/2)
NodeList (Element): void 0%   (0/1)0%   (0/4)0%   (0/2)
NodeList (Object): void 0%   (0/1)0%   (0/21)0%   (0/6)
add (Object): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
add (int, Object): void 0%   (0/1)0%   (0/6)0%   (0/2)
addAll (Collection): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
addAll (int, Collection): boolean 0%   (0/1)0%   (0/6)0%   (0/1)
clear (): void 0%   (0/1)0%   (0/4)0%   (0/2)
clone (): Object 0%   (0/1)0%   (0/8)0%   (0/3)
cloneNodes (): void 0%   (0/1)0%   (0/37)0%   (0/10)
contains (Object): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
containsAll (Collection): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
equals (Object): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
getList (): List 0%   (0/1)0%   (0/3)0%   (0/1)
hashCode (): int 0%   (0/1)0%   (0/4)0%   (0/1)
indexOf (Object): int 0%   (0/1)0%   (0/5)0%   (0/1)
isEmpty (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
lastIndexOf (Object): int 0%   (0/1)0%   (0/5)0%   (0/1)
listIterator (): ListIterator 0%   (0/1)0%   (0/4)0%   (0/1)
listIterator (int): ListIterator 0%   (0/1)0%   (0/5)0%   (0/1)
remove (Object): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
remove (int): Object 0%   (0/1)0%   (0/5)0%   (0/1)
removeAll (Collection): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
retainAll (Collection): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
selectNodes (String): NodeList 0%   (0/1)0%   (0/10)0%   (0/1)
set (int, Object): Object 0%   (0/1)0%   (0/6)0%   (0/1)
subList (int, int): List 0%   (0/1)0%   (0/9)0%   (0/1)
toArray (Object []): Object [] 0%   (0/1)0%   (0/5)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/141)0%   (0/28)
NodeList (List, boolean): void 100% (1/1)75%  (15/20)80%  (4/5)
<static initializer> 100% (1/1)100% (6/6)100% (1/1)
NodeList (List): void 100% (1/1)100% (5/5)100% (2/2)
get (int): Object 100% (1/1)100% (5/5)100% (1/1)
iterator (): Iterator 100% (1/1)100% (4/4)100% (1/1)
size (): int 100% (1/1)100% (4/4)100% (1/1)
toArray (): Object [] 100% (1/1)100% (4/4)100% (1/1)
     
class NodeList$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class NodeList$AttributeXMLOutputter100% (1/1)50%  (1/2)12%  (3/26)12%  (1/8)
output (Attribute, Writer): void 0%   (0/1)0%   (0/23)0%   (0/7)
NodeList$AttributeXMLOutputter (): void 100% (1/1)100% (3/3)100% (1/1)

1package org.apache.velocity.anakia;
2 
3/*
4 * Copyright 2001,2004 The Apache Software Foundation.
5 * 
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * 
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 * 
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 
19import java.io.Writer;
20import java.io.IOException;
21import java.io.StringWriter;
22import java.util.*;
23import org.jdom.*;
24import org.jdom.output.*;
25 
26/**
27 * Provides a class for wrapping a list of JDOM objects primarily for use in template
28 * engines and other kinds of text transformation tools.
29 * It has a {@link #toString()} method that will output the XML serialized form of the
30 * nodes it contains - again focusing on template engine usage, as well as the
31 * {@link #selectNodes(String)} method that helps selecting a different set of nodes
32 * starting from the nodes in this list. The class also implements the {@link java.util.List}
33 * interface by simply delegating calls to the contained list (the {@link #subList(int, int)}
34 * method is implemented by delegating to the contained list and wrapping the returned
35 * sublist into a <code>NodeList</code>).
36 *
37 * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
38 * @version $Id: NodeList.java,v 1.2.4.1 2004/03/03 23:22:04 geirm Exp $
39 */
40public class NodeList implements List, Cloneable
41{
42    private static final AttributeXMLOutputter DEFAULT_OUTPUTTER = 
43        new AttributeXMLOutputter();
44    
45    /** The contained nodes */
46    private List nodes;
47 
48    /**
49     * Creates an empty node list.
50     */
51    public NodeList()
52    {
53        nodes = new ArrayList();
54    }
55 
56    /**
57     * Creates a node list that holds a single {@link Document} node.
58     */
59    public NodeList(Document document)
60    {
61        this((Object)document);
62    }
63 
64    /**
65     * Creates a node list that holds a single {@link Element} node.
66     */
67    public NodeList(Element element)
68    {
69        this((Object)element);
70    }
71 
72    private NodeList(Object object)
73    {
74        if(object == null)
75        {
76            throw new IllegalArgumentException(
77                "Cannot construct NodeList with null.");
78        }
79        nodes = new ArrayList(1);
80        nodes.add(object);
81    }
82    
83    /**
84     * Creates a node list that holds a list of nodes. 
85     * @param nodes the list of nodes this template should hold. The created 
86     * template will copy the passed nodes list, so changes to the passed list
87     * will not affect the model.
88     */
89    public NodeList(List nodes)
90    {
91        this(nodes, true);
92    }
93    
94    /**
95     * Creates a node list that holds a list of nodes. 
96     * @param nodes the list of nodes this template should hold.
97     * @param copy if true, the created template will copy the passed nodes
98     * list, so changes to the passed list will not affect the model. If false,
99     * the model will reference the passed list and will sense changes in it,
100     * altough no operations on the list will be synchronized.
101     */
102    public NodeList(List nodes, boolean copy)
103    {
104        if(nodes == null)
105        {
106            throw new IllegalArgumentException(
107                "Cannot initialize NodeList with null list");
108        }
109        this.nodes = copy ? new ArrayList(nodes) : nodes;
110    }
111    
112    /**
113     * Retrieves the underlying list used to store the nodes. Note however, that
114     * you can fully use the underlying list through the <code>List</code> interface
115     * of this class itself. You would probably access the underlying list only for
116     * synchronization purposes.
117     */
118    public List getList()
119    {
120        return nodes;
121    }
122 
123    /**
124     * This method returns the string resulting from concatenation of string 
125     * representations of its nodes. Each node is rendered using its XML
126     * serialization format. This greatly simplifies creating XML-transformation
127     * templates, as to output a node contained in variable x as XML fragment,
128     * you simply write ${x} in the template (or whatever your template engine
129     * uses as its expression syntax).
130     */
131    public String toString()
132    {
133        if(nodes.isEmpty())
134        {
135            return "";
136        }
137 
138        StringWriter sw = new StringWriter(nodes.size() * 128);
139        try
140        {
141            for(Iterator i = nodes.iterator(); i.hasNext();)
142            {
143                Object node = i.next();
144                if(node instanceof Element)
145                {
146                    DEFAULT_OUTPUTTER.output((Element)node, sw);
147                }
148                else if(node instanceof Attribute)
149                {
150                    DEFAULT_OUTPUTTER.output((Attribute)node, sw);
151                }
152                else if(node instanceof Text)
153                {
154                    DEFAULT_OUTPUTTER.output((Text)node, sw);
155                }
156                else if(node instanceof Document)
157                {
158                    DEFAULT_OUTPUTTER.output((Document)node, sw);
159                }
160                else if(node instanceof ProcessingInstruction)
161                {
162                    DEFAULT_OUTPUTTER.output((ProcessingInstruction)node, sw);
163                }
164                else if(node instanceof Comment)
165                {
166                    DEFAULT_OUTPUTTER.output((Comment)node, sw);
167                }
168                else if(node instanceof CDATA)
169                {
170                    DEFAULT_OUTPUTTER.output((CDATA)node, sw);
171                }
172                else if(node instanceof DocType)
173                {
174                    DEFAULT_OUTPUTTER.output((DocType)node, sw);
175                }
176                else if(node instanceof EntityRef)
177                {
178                    DEFAULT_OUTPUTTER.output((EntityRef)node, sw);
179                }
180                else
181                {
182                    throw new IllegalArgumentException(
183                        "Cannot process a " + 
184                        (node == null 
185                         ? "null node" 
186                         : "node of class " + node.getClass().getName()));
187                }
188            }
189        }
190        catch(IOException e)
191        {
192            // Cannot happen as we work with a StringWriter in memory
193            throw new Error();
194        }
195        return sw.toString();
196    }
197 
198    /**
199     * Returns a NodeList that contains the same nodes as this node list.
200     * @throws CloneNotSupportedException if the contained list's class does
201     * not have an accessible no-arg constructor.
202     */
203    public Object clone()
204        throws CloneNotSupportedException
205    {
206        NodeList clonedList = (NodeList)super.clone();
207        clonedList.cloneNodes();
208        return clonedList;
209    }
210    
211    private void cloneNodes()
212        throws CloneNotSupportedException
213    {
214        Class listClass = nodes.getClass();
215        try
216        {
217            List clonedNodes = (List)listClass.newInstance();
218            clonedNodes.addAll(nodes);
219            nodes = clonedNodes;
220        }
221        catch(IllegalAccessException e)
222        {
223            throw new CloneNotSupportedException("Cannot clone NodeList since"
224            + " there is no accessible no-arg constructor on class "
225            + listClass.getName());
226        }
227        catch(InstantiationException e)
228        {
229            // Cannot happen as listClass represents a concrete, non-primitive,
230            // non-array, non-void class - there's an instance of it in "nodes"
231            // which proves these assumptions.
232            throw new Error(); 
233        }
234    }
235 
236    /**
237     * Returns the hash code of the contained list.
238     */
239    public int hashCode()
240    {
241        return nodes.hashCode();
242    }
243    
244    /**
245     * Tests for equality with another object.
246     * @param o the object to test for equality
247     * @return true if the other object is also a NodeList and their contained
248     * {@link List} objects evaluate as equals.
249     */
250    public boolean equals(Object o)
251    {
252        return o instanceof NodeList 
253            ? ((NodeList)o).nodes.equals(nodes)
254            : false;
255    }
256    
257    /**
258     * Applies an XPath expression to the node list and returns the resulting
259     * node list. In order for this method to work, your application must have
260     * access to <a href="http://code.werken.com">werken.xpath</a> library
261     * classes. The implementation does cache the parsed format of XPath
262     * expressions in a weak hash map, keyed by the string representation of
263     * the XPath expression. As the string object passed as the argument is
264     * usually kept in the parsed template, this ensures that each XPath
265     * expression is parsed only once during the lifetime of the template that
266     * first invoked it.
267     * @param xpathExpression the XPath expression you wish to apply
268     * @return a NodeList representing the nodes that are the result of
269     * application of the XPath to the current node list. It can be empty.
270     */
271    public NodeList selectNodes(String xpathString)
272    {
273        return new NodeList(XPathCache.getXPath(xpathString).applyTo(nodes), false);
274    }
275 
276// List methods implemented hereafter
277 
278    public boolean add(Object o)
279    {
280        return nodes.add(o);
281    }
282 
283    public void add(int index, Object o)
284    {
285        nodes.add(index, o);
286    }
287 
288    public boolean addAll(Collection c)
289    {
290        return nodes.addAll(c);
291    }
292 
293    public boolean addAll(int index, Collection c)
294    {
295        return nodes.addAll(index, c);
296    }
297 
298    public void clear()
299    {
300        nodes.clear();
301    }
302 
303    public boolean contains(Object o)
304    {
305        return nodes.contains(o);
306    }
307 
308    public boolean containsAll(Collection c)
309    {
310        return nodes.containsAll(c);
311    }
312 
313    public Object get(int index)
314    {
315        return nodes.get(index);
316    }
317 
318    public int indexOf(Object o)
319    {
320        return nodes.indexOf(o);
321    }
322 
323    public boolean isEmpty()
324    {
325        return nodes.isEmpty();
326    }
327 
328    public Iterator iterator()
329    {
330        return nodes.iterator();
331    }
332 
333    public int lastIndexOf(Object o)
334    {
335        return nodes.lastIndexOf(o);
336    }
337 
338    public ListIterator listIterator()
339    {
340        return nodes.listIterator();
341    }
342 
343    public ListIterator listIterator(int index)
344    {
345        return nodes.listIterator(index);
346    }
347 
348    public Object remove(int index)
349    {
350        return nodes.remove(index);
351    }
352 
353    public boolean remove(Object o)
354    {
355        return nodes.remove(o);
356    }
357 
358    public boolean removeAll(Collection c)
359    {
360        return nodes.removeAll(c);
361    }
362 
363    public boolean retainAll(Collection c)
364    {
365        return nodes.retainAll(c);
366    }
367 
368    public Object set(int index, Object o)
369    {
370        return nodes.set(index, o);
371    }
372 
373    public int size()
374    {
375        return nodes.size();
376    }
377 
378    public List subList(int fromIndex, int toIndex)
379    {
380        return new NodeList(nodes.subList(fromIndex, toIndex));
381    }
382 
383    public Object[] toArray()
384    {
385        return nodes.toArray();
386    }
387 
388    public Object[] toArray(Object[] a)
389    {
390        return nodes.toArray(a);
391    }
392 
393    /**
394     * A special subclass of XMLOutputter that will be used to output 
395     * Attribute nodes. As a subclass of XMLOutputter it can use its protected
396     * method escapeAttributeEntities() to serialize the attribute
397     * appropriately.
398     */
399    private static final class AttributeXMLOutputter extends XMLOutputter
400    {
401        public void output(Attribute attribute, Writer out)
402            throws IOException
403        {
404            out.write(" ");
405            out.write(attribute.getQualifiedName());
406            out.write("=");
407            
408            out.write("\"");
409            out.write(escapeAttributeEntities(attribute.getValue()));
410            out.write("\"");            
411        }
412    }
413}

[all classes][org.apache.velocity.anakia]
EMMA 2.0.4015 (stable) (C) Vladimir Roubtsov