KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > compiler > ElementTable


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: ElementTable.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.compiler;
25
26 import java.util.ArrayList JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.SortedMap JavaDoc;
32 import java.util.TreeMap JavaDoc;
33
34 import org.enhydra.xml.xmlc.XMLCError;
35 import org.enhydra.xml.xmlc.XMLCException;
36 import org.enhydra.xml.xmlc.dom.XMLCDocument;
37 import org.enhydra.xml.xmlc.metadata.MetaData;
38 import org.w3c.dom.Element JavaDoc;
39 import org.w3c.dom.NamedNodeMap JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41
42 /**
43  * Table of information about each element.
44  */

45 public class ElementTable {
46     /**
47      * Container for document.
48      */

49     private XMLCDocument fXmlcDoc;
50
51     /**
52      * Metadata object associated with document.
53      */

54     private MetaData fMetaData;
55
56     /**
57      * List of all element info objects, indexed by Element object.
58      */

59     private Map JavaDoc fElements = new HashMap JavaDoc();
60
61     /**
62      * Sorted map of ids to element info.
63      */

64     private SortedMap JavaDoc fXmlIds = new TreeMap JavaDoc();
65
66     /**
67      * Sorted map of Java ids to element info.
68      */

69     private SortedMap JavaDoc fJavaIds = new TreeMap JavaDoc();
70
71     /**
72      * Sorted table of element ids that are not legal Java identifiers.
73      * Created when needed.
74      */

75     private SortedMap JavaDoc fInvalidElementIds;
76
77     /**
78      * Is this global-id-attribute mode?
79      */

80     private boolean fGlobalIdAttrMode;
81
82     /**
83      * Table of tag name to id attribute names. Null in
84      * global-id-attribute mode.
85      */

86     private Map JavaDoc fTagName2IdAttrName;
87
88     /**
89      * Table of tag names to Lists of element info objects.
90      * Null in global-id-attribute mode.
91      */

92     private Map JavaDoc fTagName2ElementInfoList;
93
94     /**
95      * The size of the document, in nodes.
96      */

97     private int fDocumentNodeSize;
98
99     /**
100      * Constructor. Builds the table.
101      */

102     public ElementTable(MetaData metaData,
103                         XMLCDocument xmlcDoc) throws XMLCException {
104         fMetaData = metaData;
105         fXmlcDoc = xmlcDoc;
106
107         fGlobalIdAttrMode = (fXmlcDoc.getGlobalIdAttribute() != null);
108         if (!fGlobalIdAttrMode) {
109             fTagName2IdAttrName = new HashMap JavaDoc();
110             fTagName2ElementInfoList = new HashMap JavaDoc();
111         }
112         fDocumentNodeSize = addElements(fXmlcDoc.getDocument());
113     }
114
115     /**
116      * Recursively determine node sizes
117      */

118     private int getRecursiveNodeCount(Node JavaDoc node) {
119         int count = getNodeCount(node);
120         
121         for (Node JavaDoc child = node.getFirstChild(); child != null;
122              child = child.getNextSibling()) {
123             count += getRecursiveNodeCount(child);
124         }
125         return count;
126     }
127
128     /**
129      * Get the size of a single node (but not its children). Does
130      * include attribute sizes.
131      */

132     private int getNodeCount(Node JavaDoc node) {
133         int count = 1; // this node
134
NamedNodeMap JavaDoc attrs = node.getAttributes();
135         if (attrs != null) {
136             int len = attrs.getLength();
137             for (int idx = 0; idx < len; idx++) {
138                 count += getRecursiveNodeCount(attrs.item(idx));
139             }
140         }
141         return count;
142     }
143     
144     /**
145      * Record information for local id-attribute mode.
146      */

147     private void recordLocalIdAttributeInfo(ElementInfo elementInfo,
148                                             Element JavaDoc element) {
149         String JavaDoc tagName = element.getTagName();
150
151         fTagName2IdAttrName.put(tagName, fXmlcDoc.getIdAttrName(element));
152
153         List JavaDoc idElementList = (List JavaDoc)fTagName2ElementInfoList.get(tagName);
154         if (idElementList == null) {
155             idElementList = new ArrayList JavaDoc();
156             fTagName2ElementInfoList.put(tagName, idElementList);
157         }
158         idElementList.add(elementInfo);
159     }
160
161     /**
162      * Add an element to the table.
163      */

164     private void addElement(Element JavaDoc element,
165                             int nodeSize,
166                             int subTreeSize) throws XMLCException {
167         ElementInfo elementInfo
168             = new ElementInfo(element, nodeSize, subTreeSize,
169                               fMetaData, fXmlcDoc);
170
171         // Check that Java id is unique
172
String JavaDoc javaId = elementInfo.getJavaId();
173         if (javaId != null) {
174             //FIXME: Should build list and report at the end.
175
if (fJavaIds.containsKey(javaId)) {
176                 throw new XMLCException("Duplicate element id \"" + elementInfo.getXmlId()
177                                         + "\", id must be unique after first character is capitalized");
178             }
179             fJavaIds.put(javaId, elementInfo);
180         }
181         
182         // Add to lists of all.
183
fElements.put(element, elementInfo);
184
185         // Handle id to element mapping
186
if (elementInfo.hasInvalidJavaId()) {
187             // Remember if this element has an invalid java id
188
if (fInvalidElementIds == null) {
189                 fInvalidElementIds = new TreeMap JavaDoc();
190             }
191             fInvalidElementIds.put(elementInfo.getXmlId(),
192                                    elementInfo);
193         } else {
194             // It has an id, add it to the index.
195
String JavaDoc xmlId = elementInfo.getXmlId();
196             if (xmlId != null) {
197                 fXmlIds.put(xmlId, elementInfo);
198             }
199         }
200
201         if (!fGlobalIdAttrMode) {
202             recordLocalIdAttributeInfo(elementInfo, element);
203         }
204     }
205
206     /**
207      * Recursively walk the DOM and enter all elements.
208      * @return the size, in nodes, of the subtree starting at this
209      * element.
210      */

211     private int addElements(Node JavaDoc node) throws XMLCException {
212         int nodeSize = getNodeCount(node);
213         int childSize = 0;
214         for (Node JavaDoc child = node.getFirstChild(); child != null;
215              child = child.getNextSibling()) {
216             childSize += addElements(child);
217         }
218         if (node instanceof Element JavaDoc) {
219             addElement((Element JavaDoc)node, nodeSize, nodeSize+childSize);
220         }
221         return nodeSize+childSize;
222     }
223
224     /**
225      * Get the XMLCDocument object stored in the table.
226      */

227     public XMLCDocument getXMLCDocument() {
228         return fXmlcDoc;
229     }
230
231     /**
232      * Get the size of the document, in nodes.
233      */

234     public int getDocumentNodeSize() {
235         return fDocumentNodeSize;
236     }
237     
238     /**
239      * Is there only one attribute name for all id attributes?
240      */

241     public boolean isGlobalIdAttrMode() {
242         return fGlobalIdAttrMode;
243     }
244
245
246     /**
247      * Look up an ElementInfo by Element.
248      */

249     public ElementInfo getElementInfo(Element JavaDoc element) {
250         ElementInfo info = (ElementInfo)fElements.get(element);
251         if (info == null) {
252             throw new XMLCError("element not found in element info table");
253         }
254         return info;
255     }
256
257     /**
258      * Get a interator of all ElementInfo objects.
259      */

260     public Iterator JavaDoc getElements() {
261         return fElements.values().iterator();
262     }
263
264     /**
265      * Get an iterator of all ElementInfo objects that have Java ids.
266      */

267     public Iterator JavaDoc getJavaIdElements() {
268         return fJavaIds.values().iterator();
269     }
270
271     /**
272      * Get an iterator of ElementInfo entries by tag name.
273      * Only valid in local-id-attribute mode.
274      */

275     public Iterator JavaDoc getElementsByTagName(String JavaDoc tagName) {
276         return ((List JavaDoc)fTagName2ElementInfoList.get(tagName)).iterator();
277     }
278
279     /**
280      * Get all tag names that were found in local-id-attribute mode.
281      * Returns null in global-id-attribute mode.
282      */

283     public Iterator JavaDoc getTagNames() {
284         if (fGlobalIdAttrMode) {
285             return null; // Not kept for global.
286
} else {
287             return fTagName2IdAttrName.keySet().iterator();
288         }
289     }
290
291     /**
292      * Get the id-attribute name for a tag.
293      */

294     public String JavaDoc getIdAttributeName(String JavaDoc tagName) {
295         //FXIME: still needed??
296
return (String JavaDoc)fTagName2IdAttrName.get(tagName);
297     }
298
299     /**
300      * Get an sorted iterator of element ids that are not legal Java
301      * identifiers, or null if all ids were legal.
302      */

303     public Iterator JavaDoc getInvalidElementIds() {
304         if (fInvalidElementIds != null) {
305             return fInvalidElementIds.keySet().iterator();
306         } else {
307             return null;
308         }
309     }
310 }
311
Popular Tags