Translating a DOM to Other Collections

We've examined a simple Collections example, now we move on and examine how we can model the DOM as a Collection.

DOM to Array

The simplest way to provide the DOM as an array is to extend the ArrayList class. Listing 6.2 shows a very simple class that extends ArrayList and takes a document and a tag and creates an array collection, which can then be used anywhere a collection can be used.

The example itself is simple enough: Import java.util and then define the class to extend ArrayList (line 6). We then populate the array in the constructor as shown in lines 8–20. We can then use the class like any other collection and lines 33–39 simply exercise our new DOM-based collection.

Tip

A little trick you can use to test a class is to define a normal static main method and then use that method to create an instance of your class. Any class that can stand alone can be tested this way. DOMArray.java is written this way and avoids the need for a separate class for testing and debugging.


Code Listing 6.2. DOMArray.java—Converting DOM to an Array
 1: package sams.chp6;
 2: import java.io.*;
 3: import java.util.*;
 4: import org.w3c.dom.*;
 5:
 6: public class DOMArray extends ArrayList
 7: {
 8:     public DOMArray (Document parent,String tag)
 9:     {
10:         NodeList elements = parent.getElementsByTagName( tag);
11:         if ( elements.getLength()== 0)
12:         {
13:             return;
14:         }
15:         for (int i = 0; i < elements.getLength(); i++)
16:         {
17:             Element anElement = (Element) elements.item(i);
18:             this.add(anElement);
19:         }  // end for
20:     }
21:     public static void main (String argv [])
22:     {
23:         if (argv.length != 2)
24:         {
25:             System.err.println("Usage: java sams.chp6.DOMArray filename tag");
26:             System.exit(1);
27:         }
28:         Document document;
29:         try
30:         {
31:             document = XMLUtil.openDocument(argv[0]);
32:             System.out.println("Document successfully created!");
33:             DOMArray test = new DOMArray(document, argv[1]);
34:             Iterator it = test.iterator();
35:             while (it.hasNext())
36:             {
37:                 Element e = (Element) it.next();
38:                 XMLUtil.displayNodeInfo("",e);
39:             }
40:
41:         }
42:         catch (Exception e)
43:         {
44:             System.out.println( "Unexpected exception reading document!" +e);
45:             System.exit (0);
46:         }
47:         System.exit (0);
48:     }
49: }

DOM as a List

Another type of collection is a list, which is simply an ordered group of elements that can contain duplicates. Listing 6.3 goes beyond the simple DOMArray we implemented in listing 6.2 and provides a base implementation of almost every method in the AbstractList interface. For a complete definition of all the methods in an AbstractList, see the JDK documentation. Most of the class is self-explanatory; however, the Iterator interator() method bears some explanation.

As we've already seen, iterators are like enumerations and allow us to move forward through the contents of a collection. However, iterator is only an interface and we are required to provide an implementation. In the case of DOMList, we do not want to expose the underlying mechanisms behind our implementation. That would compromise the framework concepts and principles. But we do need to know how the DOMList does its work in order to provide an appropriate implementation. Lines 108–129 of DOMList define an inner class, DOMIterator, which implements the iterator interface, taking advantage of the underlying workings of DOMList but hiding its implementation.

Note

If you're unfamiliar with inner classes you should read Chapter 3, Section 5 of <ShamelessPlug> Java 2 and JavaScript for C and C++ Programmers by M. Daconta, A. Saganich and E. Monk, J. Wiley and Sons, publisher.</ShamelessPlug>


Code Listing 6.3. DOMList.java—Converting DOM to a List
  1: package sams.chp6;
  2:
  3: import java.io.*;
  4: import java.util.*;
  5: import org.w3c.dom.*;
  6:
  7: public class DOMList extends AbstractList
                          implements Cloneable, Serializable
  8: {
  9:
 10:     private transient Document parent;
 11:     private transient Object elementData[];
 12:     private int size;
 13:    
 14:     private void inRangeCheck(int pos)
 15:     {
 16:     if (pos >= size || pos < 0)
 17:         throw new IndexOutOfBoundsException(
 18:            "Position: "+pos+", DOMList size: "+size);
 19:     }
 20:    
 21:     public DOMList (Document parent,String tag)
 22:     {
 23:         super();
 24:         this.parent = parent;
 25:         NodeList elements = parent.getElementsByTagName( tag );
 26:         if ( elements.getLength()== 0)
 27:         {
 28:             size=0;
 29:             return;
 30:         }
 31:         elementData= new Object[elements.getLength()];
 32:         for (int i = 0; i < elements.getLength(); i++)
 33:         {
 34:             Element anElement = (Element) elements.item(i);
 35:             elementData[i] = anElement;
 36: 
 37:         }  // end for
 38:     }
 39:     public int size()
 40:     {
 41:         return size;
 42:     }
 43:     public boolean isEmpty()
 44:     {
 45:         return size == 0;
 46:     }
 47:       public void add(int index, Object element)
 48:        {
 49:         throw new UnsupportedOperationException( "DOMList does not support add(int
,element) operation" );
 50:     }
 51:       public boolean add(Object element)
 52:        {
 53:         throw new UnsupportedOperationException( "DOMList does not support add
(element) operation" );
 54:     }
 55:     public Object get(int position)
 56:     {
 57:         inRangeCheck(position);
 58:         return elementData[position];
 59:     }
 60:     public Object set(int position, Object element)
 61:     {
 62:         inRangeCheck(position);
 63:         throw new UnsupportedOperationException( "DOMList does not support set(int
,element) operation" );
 64:     }
 65:     public Object remove(int position)
 66:     {
 67:         inRangeCheck(position);
 68:         throw new UnsupportedOperationException( "DOMList does not support remove
(int) operation" );
 69:     }
 70:     public int indexOf(Object elem)
 71:     {
 72:         if (elem == null)
 73:             return -1;
 74:         else
 75:         {
 76:             for (int i = 0; i < size; i++)
 77:             if (elem.equals(elementData[i]))
 78:                 return i;
 79:         }
 80:         return -1;
 81:     }
 82:     public int lastIndexOf(Object elem)
 83:     {
 84:         if (elem == null)
 85:             return -1;
 86:         else
 87:         {
 88:             for (int i = size-1; i >= 0; i--)
 89:                 if (elem.equals(elementData[i]))
 90:                     return i;
 91:         }
 92:         return -1;
 93:     }
 94:
 95:     public void clear()
 96:     {
 97:         throw new UnsupportedOperationException( "DOMList does not support clear
 operation" );
 98:     }
 99:     public boolean addAll(int index, Collection c)
100:     {
101:         throw new UnsupportedOperationException( "DOMList does not support addAll(int
, Collection) operation" );
102:     }
103:
104:     public Iterator iterator()
105:     {
106:         return new DOMIterator();
107:     }
108:     private class DOMIterator implements Iterator
109:     {
110:         Object[] table = DOMList.this.elementData;
111:         int length = elementData.length;
112:         int pos = 0;
113:         DOMIterator() { } ;
114:
115:         public boolean hasNext()
116:         {
117:             if (pos < length)
118:                 return true;
119:             return false;
120:         }
121:
122:         public Object next()
123:         {
124:             if (pos >= length)
125:                 throw new NoSuchElementException();
126:             pos++;
127:             return table[pos-1];
128:
129:         }
130:
131:         public void remove()
132:         {
133:             throw new UnsupportedOperationException( "DOMIterator does not support
 remove() operation" );
134:         }
135:     }
136:    
137:     public static void main (String argv [])
138:     {
139:         if (argv.length != 2)
140:         {
141:
142:             System.err.println( "Usage: java sams.chp6.DOMArray filename tag");
143:             System.exit(1);
144:         }
145:
146:         Document document;
147:         try
148:         {
149:             document = XMLUtil.openDocument(argv[0]);
150:             System.out.println("Document successfully created!");
151:
152:             DOMList test = new DOMList(document, argv[1]);
153:             Iterator it = test.iterator();
154:             while (it.hasNext())
155:             {
156:                 Element e = (Element) it.next();
157:                 XMLUtil.displayNodeInfo("",e);
158:             }
159:
160:         }
161:         catch (Exception e)
162:         {
163:             System.out.println( "Unexpected exception reading document!" +e);
164:             System.exit (0);
165:         }
166:         System.exit (0);
167:
168:     }
169:
170: }

Sorting a DOM

We briefly examined the elements of sorting in Listing 6.1. Since the Collections algorithms are polymorphic we should be able to apply them to our DOM-based collections. However, we still need appropriate Comparator methods. Listing 6.4 gives three such methods, each of which can be applied to DOM elements to provide an appropriate ordering. Listing 6.5 then exercises our newly created Comparator methods.

Code Listing 6.4. DOMCollectionUtilities.java—Comparator Methods
 1: package sams.chp6;
 2:
 3: import org.w3c.dom.*;
 4: import java.util.Comparator;
 5:
 6: public class DOMCollectionUtilities
 7: {
 8:     static class StringElementComparator implements Comparator
 9:     {
10:         public int compare (Object e1, Object e2)
11:         {
12:             if ( !( e1 instanceof Element)
13:                  || !( e2 instanceof Element)
14:                 )
15:                 return 0;
16:             Element element1 = (Element) e1;
17:             Element element2 = (Element) e2;
18:             String content1 = element1.getNodeName();
19:             String content2 = element2.getNodeName();
20:             if (element1.getNodeType() == org.w3c.dom.Node.TEXT_NODE &&
21:                 element2.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
22:             {
23:                 content1 = element1.getNodeValue();
24:                 content2 = element2.getNodeValue();
25:             }        
26:             return (content1.compareTo(content2));
27:         }
28:     }
29:
30:     static class IntegerElementComparator implements Comparator
31:     {
32:         public int compare (Object e1, Object e2)
33:         {
34:             if ( !( e1 instanceof Element)
35:                  || !( e2 instanceof Element)
36:                 ) 
37:                 return 0;
38:             Element element1 = (Element) e1;
39:             Element element2 = (Element) e2;
40:            
41:             // we can only compare convert text elements to integers
42:             if (element1.getNodeType() != org.w3c.dom.Node.TEXT_NODE ||
43:                 element2.getNodeType() != org.w3c.dom.Node.TEXT_NODE)
44:                 return 0;
45:
46:             String content1 = element1.getNodeValue();
47:             String content2 = element2.getNodeValue();
48:            
49:             return new Integer(content1).compareTo(new Integer(content2));
50:             }
51:     }
52:
53:     static class FloatElementComparator implements Comparator
54:     {
55:         public int compare (Object e1, Object e2)
56:         {
57:             if ( !( e1 instanceof Element)
58:                  || !( e2 instanceof Element)
59:                 )
60:                 return 0;
61:             Element element1 = (Element) e1;
62:             Element element2 = (Element) e2;
63:            
64:             // we can only compare convert text elements to float
65:             if (element1.getNodeType() != org.w3c.dom.Node.TEXT_NODE ||
66:                 element2.getNodeType() != org.w3c.dom.Node.TEXT_NODE)
67:                 return 0;
68:
69:             String content1 = element1.getNodeValue();
70:             String content2 = element2.getNodeValue();
71:            
72:             return new Float(content1).compareTo(new Float(content2));
73:             }
74:     }
75: }

Code Listing 6.5. TestDOMList.java—DOMList Test Driver
 1: package sams.chp6;
 2:
 3: import java.io.*;
 4: import java.util.*;
 5: import org.w3c.dom.*;
 6:
 7: public class TestDOMList
 8: {
 9:     public static void main (String argv [])
10:     {
11:         if (argv.length < 2)
12:         {
13:             System.err.println(
14:   "Usage: java sams.chp8.DOMArray filename tag [comparison method]" );
15:             System.exit(1);
16:         }
17:         Document document;
18:         try
19:         {
20:             document = XMLUtil.openDocument(argv[0]);
21:             System.out.println("Document successfully created!");
22:             DOMList test = new DOMList(document, argv[1]);
23:             if (argv.length == 3)
24:             {    
25:                 String which = argv[2];
26:                 System.out.println("Attempting to sort by "+ which);
27:                 Comparator c = null;
28:                 if (which.equals("int"))
29:                     c = new
30:                DOMCollectionUtilities.IntegerElementComparator();
31:                 else if (which.equals("float"))
32:                     c = new
33:                DOMCollectionUtilities.FloatElementComparator();
34:                 else if (which.equals("string"))
35:                     c = new
36:                DOMCollectionUtilities.StringElementComparator();
37:                 if ( null != c)
38:                     Collections.sort(test,c);
39:             }
40:             Iterator it = test.iterator();
41:             while (it.hasNext())
42:             {
43:                 Element e = (Element) it.next();
44:                 XMLUtil.displayNodeInfo("",e);
45:             }
46:         }         catch (Exception e)
47:         {
48:             System.out.println( "Unexpected exception reading document!" +e);
49:             System.exit (0);
50:         }
51:         System.exit (0);
52:     }
53: }

TestDOMList.java makes use of the Comparator methods we defined and shows, on lines 27–38, another example of employing custom Comparator methods. The CD version of Listing 6.5 goes slightly farther than the one displayed here in the text and adds a listIterator method, which is required by the generic Collections.sort() method. ListIterators are much like Iterators but allow for both backward and forward list traversal. Interested readers can see a complete implementation of ListIterator.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.91.153