KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > schema2beansdev > TreeBuilder


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.schema2beansdev;
21
22 import java.util.*;
23 import java.io.*;
24
25 import org.netbeans.modules.schema2beans.*;
26
27 //******************************************************************************
28
// BEGIN_NOI18N
29
// This class does not (and will not) cantain strings that need to be localized.
30
//******************************************************************************
31

32 /**
33  *
34  * This class implements the Document Definition handler in order to build
35  * the internal tree representation of the DD DTD.
36  *
37  */

38 public class TreeBuilder implements DocDefHandler, TreeParser, HasPrefixGuesser {
39     // root element of the DTD graph
40
GraphNode rootNode;
41     String JavaDoc docRoot;
42     GenBeans.Config config;
43     
44     // Current parsing pointers
45
private Stack curParentGroupStack = new Stack();
46     private GraphLink curParentGroup;
47     
48     // Global value of the type currently parsed (ELEMENT, ATTLIST, COMMENT)
49
private Stack curElementTypeStack = new Stack();
50     private int curElementType;
51     
52     // Current parsed attribute (<!ATTLIST element)
53
private Stack curAttrStack = new Stack();
54     private AttrProp curAttr;
55     
56     private PrefixGuesser prefixGuesser;
57
58     void pushLevel() {
59         curParentGroupStack.push(curParentGroup);
60         curElementTypeStack.push(new Integer JavaDoc(curElementType));
61         curAttrStack.push(curAttr);
62     }
63
64     void popLevel() {
65         curParentGroup = (GraphLink) curParentGroupStack.pop();
66         curElementType = ((Integer JavaDoc) curElementTypeStack.pop()).intValue();
67         curAttr = (AttrProp) curAttrStack.pop();
68     }
69     
70     //
71
// Where the element nodes (GraphNode objects) are stored during
72
// the graph construction. We use this hash table to make sure that
73
// an element GraphNode is created only once (unicity on the name).
74
// This table is also useful to get the list of all the nodes.
75
//
76
Map nameHash; // Map<String, GraphNode>
77

78     private String JavaDoc defaultNamespace = null;
79     
80     
81     TreeBuilder(GenBeans.Config config) {
82         this.nameHash = new HashMap();
83         this.curAttr = null;
84         this.config = config;
85     }
86     
87     /**
88      * Called once, when the DTD is started to be parsed.
89      * Create the GraphNode root element.
90      *
91      * @param root root elemement name of the document (as the DOCTYPE
92      * specifies in the XML document)
93      */

94     public void startDocument(String JavaDoc root) {
95         if (DDLogFlags.debug) {
96             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
97                             DDLogFlags.DBG_DTD, 1,
98                             DDLogFlags.STARTDOC, root);
99
100             config.messageOut.println("Building the schema object graph.");
101         }
102         this.docRoot = root;
103     }
104     
105     /**
106      * Called when the DTD parsing is over.
107      *
108      * At this time, the DTD object graph is entirely built. The method
109      * checks the consitency of the built graph, and cleans things up a bit.
110      *
111      */

112     public void endDocument() {
113         if (DDLogFlags.debug) {
114             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
115                             DDLogFlags.DBG_DTD, 1,
116                             DDLogFlags.ENDDOC);
117     
118             config.messageOut.println("schema Object graph built.");
119         }
120     
121         // Remove the starter groupings
122
for (Iterator it = nameHash.values().iterator(); it.hasNext(); ) {
123             GraphNode node = (GraphNode)it.next();
124             GraphLink l = node.getGraphLink();
125             if (l == null || l.name != null || l.getSibling() != null
126                 || l.isSequenceOr() || l.getGroupInstance() != Common.TYPE_1)
127                 continue;
128             GraphLink firstChild = l.getFirstChild();
129             if (firstChild != null && firstChild.getSibling() != null)
130                 continue;
131             if (DDLogFlags.debug)
132                 config.messageOut.println("Removing starter group: "+l);
133             node.setGraphLink(firstChild);
134         }
135
136         //
137
// We're done building the tree graph
138
// It's time now to generate the beans
139
//
140
try {
141             findRootNode();
142         } catch (Schema2BeansException e) {
143             throw new Schema2BeansRuntimeException(e);
144         }
145     
146         if (DDLogFlags.debug) {
147             config.messageOut.println(this.dump());
148         }
149     }
150     
151     /**
152      * Either create the GraphNode for the element named name, or
153      * get it from the hash table. This method can be called either
154      * by the startElement() method (an element definition has been
155      * found in the DTD) or by the element() method (an element is
156      * referenced by another one).
157      *
158      * @param name name of the element as the DTD parser reads it
159      * @param original true if the element definition has been
160      * read, false if we are just asking to reference the element.
161      * This parameter allows to check than an element is not
162      * defined twice and is at least defined once.
163      * @return the unique GraphNode object of the named element
164      */

165     private static final int CREATE = 1;
166     private static final int GET = 2;
167     private static final int REFERENCE = 3;
168     private GraphNode getGraphNode(String JavaDoc uniqueName, String JavaDoc name, int mode) throws Schema2BeansException {
169         //String uniqueName = name;
170
uniqueName = name;
171         
172         // Find out if we already know about it
173
GraphNode node = (GraphNode)this.nameHash.get(uniqueName);
174     
175         if (node != null) {
176             // We know about it
177
if (false && node.isCreated() && (mode == CREATE)) {
178                 throw new Schema2BeansException(Common.getMessage("DuplicateElement_msg", uniqueName));
179             }
180         }
181         else {
182             //
183
// First time we hear about this element. Create the GraphNode
184
// Object and its GraphLink link. The purpose of this GraphLink
185
// object is to hold the siblings/children links for this node.
186
// This GraphLink does _not_ reference the element.
187
// (graphLink.element = null).
188
//
189
node = new GraphNode(name, uniqueName);
190             node.setGraphLink(new GraphLink(null));
191             this.nameHash.put(uniqueName, node);
192             //System.out.println("Created new GraphNode: "+node);
193
}
194     
195         //
196
// Called to get the original: mark it. If we are later called again
197
// to get the original that means we have two element definition in
198
// the DTD and we can throw an exception (see above).
199
// Called to get a reference: increment the node usage. The root
200
// of the node is never referenced and will keep a refCount=0.
201
//
202
if (mode == CREATE)
203             node.setCreated(true);
204         else
205             if (mode == REFERENCE)
206                 node.incrRefCount();
207     
208         return node;
209     }
210     
211     
212     /**
213      * Called each time a DTD <!element definition is read.
214      *
215      * @param name the name of the element
216      * @param typeName is the name to use for the attribute
217      * @param type the type (as a constant) of the element (for example
218      * ELEMENT or ATTLIST)
219      */

220     public void startElement(String JavaDoc uniqueName,
221                              String JavaDoc typeName, int type) {
222     
223         if (DDLogFlags.debug) {
224             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
225                             DDLogFlags.DBG_DTD, 1,
226                             DDLogFlags.STARTELT,
227                             uniqueName + " - " + typeName + " - " + typeToString(type));
228         }
229         pushLevel();
230
231         // Keep track of what we are building over all the method calls
232
this.curElementType = type;
233     
234         //
235
// For now, ignore comments
236
//
237
try {
238             if (type == Common.ELEMENT) {
239                 // Get the node and start building beneath it
240
GraphNode node = getGraphNode(uniqueName, typeName,
241                                               CREATE);
242                 curParentGroup = node.getGraphLink();
243             } else if (type == Common.ATTLIST) {
244                 // Get the node and add this attribute
245
GraphNode node = getGraphNode(uniqueName, typeName,
246                                               GET);
247                 curAttr = new AttrProp(typeName);
248                 node.addAttribute(curAttr);
249             }
250         } catch (Schema2BeansException e) {
251             throw new Schema2BeansRuntimeException(e);
252         }
253     }
254     
255     public boolean doesElementExist(String JavaDoc typeName) {
256         return nameHash.containsKey(typeName);
257     }
258     
259     /**
260      * Done with an element
261      */

262     public void endElement() {
263         if (DDLogFlags.debug) {
264             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
265                             DDLogFlags.DBG_DTD, 1,
266                             DDLogFlags.ENDELT);
267         }
268     
269         if (curElementType == Common.ATTLIST) {
270             curAttr.validate();
271         } else if (curElementType == Common.ELEMENT) {
272             //System.out.println("endElement: curParentGroup="+curParentGroup);
273
}
274     
275         curElementType = Common.NONE;
276         popLevel();
277     }
278     
279     /**
280      * Called each time a character | is found.
281      */

282     public void character(char c) {
283         //System.out.println("character: c="+c+" curParentGroup="+curParentGroup);
284
if (this.curElementType == Common.ELEMENT) {
285             if (c == '|')
286                 curParentGroup.setSequence(Common.SEQUENCE_OR);
287         }
288         else
289             if (this.curElementType == Common.ATTLIST) {
290                 if (c == '|') {
291                     this.curAttr.checkEnum();
292                 }
293             }
294     }
295     
296     /**
297      * Called for each word found in a DTD definition. This can be a
298      * comment, element or attlist definition. For example, this method is
299      * called for each name element found within the scope of an element
300      * (<!element (element1, element2, ...)>. The first element name doesn't
301      * generate a call to this method (@see startElement).
302      *
303      * This is where the subtree of the element definition is built.
304      * The element to add might be a child or sibling to the previous
305      * element. If the element is preceded by a '(', this is child
306      * (@see startGroupElements), otherwise the element is a sibling.
307      *
308      * @param name the name of the element defined within the <!element ...>
309      * declaration.
310      * @param instance has one of the three values: TYPE_0_1,
311      * TYPE_1, TYPE_0_N, TYPE_1_N
312      *
313      */

314     public void element(String JavaDoc uniqueName, String JavaDoc typeName,
315                         String JavaDoc attrName, String JavaDoc attrNamespace,
316                         int instance, boolean externalType,
317                         String JavaDoc defaultValue) {
318         if (DDLogFlags.debug) {
319             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
320                             DDLogFlags.DBG_DTD, 1,
321                             DDLogFlags.ELEMENT,
322                             attrName + " : " + typeName + instanceToString(instance, false));
323         }
324         try {
325             if (curElementType == Common.NONE && !externalType) {
326                 if (DDLogFlags.debug)
327                     System.out.println("Top element def for "+attrName);
328                 GraphNode attrNode = getGraphNode(uniqueName, attrName, CREATE);
329                 GraphNode node = getGraphNode(uniqueName, typeName, REFERENCE);
330                 attrNode.setAlias(node);
331             } else if (curElementType == Common.ELEMENT) {
332                 // Get the element reference
333
GraphNode node = getGraphNode(uniqueName, typeName, REFERENCE);
334         
335                 GraphLink link = new GraphLink(attrName, attrNamespace);
336                 link.setDefaultValue(defaultValue);
337                 //System.out.println("curParentGroup="+curParentGroup+" curParentGroup.sibling="+curParentGroup.getSibling());
338
curParentGroup.addChild(link);
339                 link.element = node;
340                 link.setElementInstance(instance);
341
342                 if (externalType)
343                     node.setJavaType(typeName);
344                 //System.out.println("Created new GraphLink: "+link+" link.parent="+link.parent+" link.sibling="+link.sibling);
345
} else if (curElementType == Common.ATTLIST) {
346                 // If the current attribute is completly built, signal the
347
// Parser by throwing the exception.
348
if (this.curAttr.isComplete())
349                     throw new DocDefParser.MissingEndOfEltException(curAttr.getPropertyName());
350         
351                 if (defaultValue != null)
352                     this.curAttr.setDefaultValue(defaultValue);
353                 this.curAttr.addValue(attrName, attrNamespace);
354                 if (externalType)
355                     curAttr.setJavaType(typeName);
356             }
357         } catch (Schema2BeansException e) {
358             throw new Schema2BeansRuntimeException(e);
359         }
360     }
361     public void element(String JavaDoc uniqueName, String JavaDoc typeName, int instance) {
362         element(uniqueName, typeName, typeName, null, instance, false, null);
363     }
364
365     public void addExtraDataNode(String JavaDoc uniqueName, String JavaDoc typeName, Object JavaDoc data) throws Schema2BeansException {
366         //System.out.println("** addExtraDataNode: typeName="+typeName+" data="+data);
367
GraphNode node = getGraphNode(uniqueName, typeName, GET);
368         node.addExtraData(data);
369     }
370
371     public void addExtraDataCurLink(Object JavaDoc data) {
372         //System.out.println("** addExtraDataCurLink: data="+data+" curParentGroup.name="+((curParentGroup == null) ? "curParentGroup null" : curParentGroup.name));
373
if (curElementType == Common.ATTLIST) {
374             //System.out.println("curElementType == Common.ATTLIST, curAttr="+curAttr);
375
if (curAttr != null)
376                 curAttr.addExtraData(data);
377         } else {
378             //System.out.println("lastChild="+curParentGroup.getLastChild());
379
if (curParentGroup != null && curParentGroup.getLastChild() != null) {
380                 curParentGroup.getLastChild().extraData.add(data);
381             }
382         }
383     }
384
385     public void addExtraDataNode(String JavaDoc uniqueName, String JavaDoc typeName, Object JavaDoc[] data) throws Schema2BeansException {
386         //System.out.println("** addExtraDataNode: typeName="+typeName+" data="+data);
387
GraphNode node = getGraphNode(uniqueName, typeName, GET);
388         if (data != null)
389             for (int i=0; i < data.length; i++)
390                 node.addExtraData(data[i]);
391     }
392
393     public void setUnion(String JavaDoc uniqueName, String JavaDoc typeName, boolean value) throws Schema2BeansException {
394         GraphNode node = getGraphNode(uniqueName, typeName, GET);
395         node.setUnion(value);
396     }
397
398     public void addExtraDataCurLink(Object JavaDoc[] data) {
399         //System.out.println("** addExtraDataCurLink: data="+data+" curParentGroup.name="+((curParentGroup == null) ? "curParentGroup null" : curParentGroup.name));
400
if (curElementType == Common.ATTLIST) {
401             //System.out.println("curElementType == Common.ATTLIST, curAttr="+curAttr);
402
if (curAttr != null && data != null)
403                 for (int i=0; i < data.length; i++)
404                     curAttr.addExtraData(data[i]);
405         } else {
406             //System.out.println("lastChild="+curParentGroup.getLastChild());
407
if (curParentGroup != null && curParentGroup.getLastChild() != null) {
408                 if (data != null)
409                     for (int i=0; i < data.length; i++)
410                         curParentGroup.getLastChild().extraData.add(data[i]);
411             }
412         }
413     }
414
415     public void nillable(boolean value) {
416         //System.out.println("nillable="+value);
417
if (curParentGroup != null && curParentGroup.getLastChild() != null)
418             curParentGroup.getLastChild().setNillable(value);
419         /*
420         else
421             System.err.println("no parent group for nillable");
422         */

423     }
424     
425     public void setAbstract(String JavaDoc uniqueName, String JavaDoc name, boolean value) {
426         //System.out.println("Setting javaType of "+name+" to "+javaType);
427
if (this.curElementType == Common.ATTLIST) {
428         } else {
429             // Get the element reference
430
GraphNode node;
431             try {
432                 node = getGraphNode(uniqueName, name, GET);
433             } catch (Schema2BeansException e) {
434                 throw new Schema2BeansRuntimeException(e);
435             }
436             node.setAbstract(value);
437         }
438     }
439     
440     /**
441      * set an extended property on a GraphNode
442      */

443     public void setExtendedProperty(String JavaDoc uniqueName, String JavaDoc typeName, String JavaDoc propertyName,
444                                     Object JavaDoc value) throws Schema2BeansException {
445         GraphNode node = getGraphNode(uniqueName, typeName, GET);
446         node.setExtendedProperty(propertyName, value);
447     }
448
449     /**
450      * Called to request that the graph node named name be of a certain
451      * Java class. If the current element type is an attribute, then
452      * we set the javaType of that attribute instead.
453      * @param javaType is the name of a Java class (eg, "java.lang.Integer", or "int").
454      */

455     public void javaType(String JavaDoc uniqueName, String JavaDoc name, String JavaDoc javaType) {
456         //System.out.println("Setting javaType of "+name+" to "+javaType);
457
if (this.curElementType == Common.ATTLIST) {
458             curAttr.setJavaType(javaType);
459         } else {
460             // Get the element reference
461
GraphNode node;
462             try {
463                 node = getGraphNode(uniqueName, name, GET);
464             } catch (Schema2BeansException e) {
465                 throw new Schema2BeansRuntimeException(e);
466             }
467             node.setJavaType(javaType);
468             node.setCreated(false);
469         }
470     }
471     
472     public void setExtension(String JavaDoc uniqueName, String JavaDoc typeName, String JavaDoc extendsName) throws Schema2BeansException {
473         if (curElementType == Common.ATTLIST) {
474         } else {
475             GraphNode node;
476             GraphNode extendsNode;
477             try {
478                 node = getGraphNode(uniqueName, typeName, GET);
479                 extendsNode = getGraphNode(null, extendsName, REFERENCE);
480             } catch (Schema2BeansException e) {
481                 throw new Schema2BeansRuntimeException(e);
482             }
483             node.setExtension(extendsNode);
484         }
485     }
486
487     /**
488      * Called when a parenthese is found, meaning that the following
489      * elements (element() calls) should be considered as semantically
490      * grouped.
491      *
492      * Creates a child GraphLink from the current link to group
493      * all the further elements of this group. If any propriety
494      * is defined for this group (as *, ? or + or |) this will be set later
495      * on the current link (as the parent of any of the elements graph link
496      * objects).
497      */

498     public void startGroupElements() {
499         if (DDLogFlags.debug) {
500             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
501                             DDLogFlags.DBG_DTD, 5,
502                             DDLogFlags.STARTGRP);
503         }
504     
505         // A new parenthese in the parsing makes a new GraphLink.
506
if (this.curElementType == Common.ELEMENT) {
507             GraphLink link = new GraphLink(null);
508             curParentGroup.addChild(link);
509             curParentGroup = link;
510             //System.out.println("curParentGroup="+curParentGroup);
511
}
512         else {
513             if (this.curElementType == Common.ATTLIST)
514                 this.curAttr.setEnum(true);
515         }
516     }
517     
518     /**
519      * We are done creating the elements of a same group,
520      * set the current link to the parent of the group.
521      * This will allow either to start creating siblings (if element()
522      * is called) or go the next parent level (if this same method
523      * is called again).
524      */

525     public void endGroupElements(int instance) {
526         if (DDLogFlags.debug) {
527             TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
528                             DDLogFlags.DBG_DTD, 5,
529                             DDLogFlags.ENDGRP,
530                             instanceToString(instance, false));
531         }
532     
533         if (curElementType == Common.ELEMENT) {
534             curParentGroup.setGroupInstance(instance);
535             //System.out.println("curParentGroup="+curParentGroup+" instance="+instance);
536
curParentGroup = curParentGroup.getParent();
537         }
538         else
539             if (this.curElementType == Common.ATTLIST)
540                 this.curAttr.setEnum(false);
541     }
542
543     public void setDefaultNamespace(String JavaDoc ns) {
544         defaultNamespace = ns;
545     }
546
547     public String JavaDoc getDefaultNamespace() {
548         return defaultNamespace;
549     }
550     
551     private void findRootNode() throws Schema2BeansException {
552         //
553
// Find out who's the root of the graph
554
// The root of the graph is the graph node that has not been
555
// referenced. We might find zero, one or several nodes that
556
// could be the root:
557
// 0: throw an exception
558
// 1: use the node as the root (check with doc root if specified)
559
// 1-n: use the doc root value if specified or ask
560
// for the node to use.
561
//
562
Iterator it = this.nameHash.keySet().iterator();
563         GraphNode node;
564         int count = 0;
565         List list = new ArrayList();
566     
567         while (it.hasNext()) {
568             String JavaDoc uniqueName = (String JavaDoc) it.next();
569             node = (GraphNode) nameHash.get(uniqueName);
570             if (DDLogFlags.debug) {
571                 System.out.println("refCount="+node.getRefCount()+" created="+node.isCreated()+" javaType="+node.getJavaType()+" uniqueName="+uniqueName+" node="+node);
572             }
573             if (node.isCreated() && node.getRefCount() == 0) {
574                 count++;
575                 list.add(node);
576             }
577         }
578
579         if (count > 1) {
580             // Attempt to find 1 that is most qualified
581
int highestPoints = 0;
582             GraphNode highestNode = null;
583             int tieCount = 0;
584             for (Iterator highit = list.iterator(); highit.hasNext(); ) {
585                 int points = 0;
586                 node = (GraphNode) highit.next();
587                 if (node.getAlias() != null) {
588                     ++points;
589                     if (node.getAlias().getRefCount() == 1)
590                         ++points;
591                 }
592                 // See if the default namespace is the same as this node's.
593
if (defaultNamespace == null ? node.getNamespace() == null : defaultNamespace.equals(node.getNamespace()))
594                     ++points;
595                 GraphLink link = node.getGraphLink();
596                 //System.out.println("link="+link+" link.name="+link.name);
597
if (link != null && !"#PCDATA".equals(link.name)) {
598                     ++points;
599                     GraphLink firstChild = link.getFirstChild();
600                     if (firstChild != null) {
601                         ++points;
602                         if (firstChild.getSibling() != null)
603                             ++points;
604                         if (firstChild.getFirstChild() != null)
605                             ++points;
606                     }
607                     GraphLink sibling = link.getSibling();
608                     if (sibling != null) {
609                         ++points;
610                         if (sibling.getSibling() != null)
611                             ++points;
612                         if (sibling.getFirstChild() != null)
613                             ++points;
614                     }
615                 }
616                 //System.out.println("points="+points+" node="+node);
617
if (points > highestPoints) {
618                     highestPoints = points;
619                     highestNode = node;
620                     tieCount = 0;
621                 } else if (points == highestPoints) {
622                     ++tieCount;
623                 }
624             }
625             if (tieCount == 0 && highestNode != null) {
626                 count = 1;
627                 list.clear();
628                 list.add(highestNode);
629             }
630         }
631
632         if (count == 1) {
633             this.rootNode = (GraphNode)list.get(0);
634             // Only one element not referenced in the graph
635
if (this.docRoot != null) {
636                 if (!this.docRoot.equals(this.rootNode.getName())) {
637                     String JavaDoc str = "Mismatch between doc root name specified (" +
638                         this.docRoot +
639                         ") and the root name found in the DTD graph (" +
640                         this.rootNode.getName() +")";
641                     throw new IllegalStateException JavaDoc(str);
642                 }
643             }
644         } else if (count == 0) {
645             this.rootNode = null;
646             if (docRoot != null) {
647                 it = this.nameHash.values().iterator();
648                 while (it.hasNext()) {
649                     node = (GraphNode)it.next();
650                     if (docRoot.equals(node.getName())) {
651                         rootNode = node;
652                         break;
653                     }
654                 }
655             }
656             if (rootNode == null)
657                 throw new IllegalStateException JavaDoc(Common.getMessage("NoRootElementCandidate"));
658         } else {
659             // List the elements and pick the root (if specified) or ask
660
config.messageOut.println("The following elements could be the root "
661                                       + "of the document:");
662             for (int i=0; i<list.size(); i++) {
663                 GraphNode n = (GraphNode)list.get(i);
664                 config.messageOut.print( (i+1) + ". " + n);
665                 if ((this.docRoot != null)
666                     && (this.docRoot.equals(n.getName()))) {
667
668                     this.rootNode = n;
669                     config.messageOut.println(" <= parameter value");
670                 }
671                 else
672                     config.messageOut.println("");
673             }
674         
675             if (this.rootNode == null) {
676                 // We still don't know - ask for the element to use
677

678                 String JavaDoc errStr = "Could not find the root of the document. "
679                     + "Use the -d option to specify the doc root";
680         
681                 if (config.isAuto()) {
682                     throw new IllegalStateException JavaDoc(errStr);
683                 }
684         
685                 try {
686                     BufferedReader rd =
687                         new BufferedReader(new InputStreamReader(System.in));
688             
689                     config.messageOut.print("Enter the element that should be used "
690                                             + "as the root: ");
691                     String JavaDoc str = rd.readLine();
692             
693                     int i = Integer.parseInt(str)-1;
694             
695                     if (i<0 || i>=list.size()) {
696                         throw new IllegalStateException JavaDoc(errStr);
697                     }
698                     else {
699                         this.rootNode = (GraphNode)list.get(i);
700                     }
701                 }
702                 catch(Exception JavaDoc e) {
703                     TraceLogger.error(e);
704                     throw new Schema2BeansNestedException(errStr, e);
705                 }
706             }
707         }
708     
709         if (DDLogFlags.debug)
710             config.messageOut.println("Using " + this.rootNode.getName()
711                                       + " as the root of the document.");
712     }
713     
714     //
715
static String JavaDoc instanceToString(int instance, boolean bean) {
716         switch (instance) {
717         case Common.TYPE_0_1:
718             if (bean)
719                 return "[0,1]";
720             else
721                 return "?";
722         case Common.TYPE_0_N:
723             if (bean)
724                 return "[0,n]";
725             else
726                 return "*";
727         case Common.TYPE_1_N:
728             if (bean)
729                 return "[1,n]";
730             else
731                 return "+";
732         }
733         return "";
734     }
735     
736     //
737
static String JavaDoc typeToString(int type) {
738         switch (type) {
739         case Common.COMMENT:
740             return "comment";
741         case Common.ELEMENT:
742             return "element";
743         case Common.ATTLIST:
744             return "attlist";
745         }
746         return "unknown value: " + type;
747     }
748     
749     /**
750      * TreeParser interface. This is what the BeanBuilder uses to get
751      * elements of the tree. The goal is to try to keep separated
752      * the object graph implementation from its usage.
753      * Not sure, this is very useful though, since the tree builder
754      * knows the gory details of the graph. Just a gentle way to ask
755      * for the graph.
756      */

757     public GraphNode[] getNodes() {
758         //
759
// Try to give the results back with some order from top to bottom
760
// (right now, it's BFS (Breadth First Search)).
761
//
762
int maxSize = nameHash.values().size();
763         List ret = new ArrayList(maxSize);
764         Map insertedNodes = new HashMap();
765         Map ignoredNodes = new HashMap();
766         getNodesInsertNode(rootNode, ret, insertedNodes, ignoredNodes);
767         getNodes(rootNode.getGraphLink(), ret, insertedNodes, ignoredNodes);
768         if (!config.isRemoveUnreferencedNodes()) {
769             for (Iterator it = nameHash.values().iterator();
770                  it.hasNext(); ) {
771                 GraphNode node = (GraphNode) it.next();
772                 if (!insertedNodes.containsKey(node) && !ignoredNodes.containsKey(node)) {
773                     config.messageOut.println(Common.getMessage("MSG_FoundUnreferencedNode", node.toString()));
774                     ret.add(node);
775                 }
776             }
777         }
778         /*
779             for (int i = 0; i < maxSize; ++i)
780                 System.out.println("ret["+i+"]="+ret[i]);
781         */

782         return (GraphNode[]) ret.toArray(new GraphNode[ret.size()]);
783     }
784
785     private void getNodes(GraphLink l, List ret,
786                           Map insertedNodes, Map ignoredNodes) {
787         Stack linkStack = new Stack();
788         linkStack.push(l);
789         while (!linkStack.isEmpty()) {
790             l = (GraphLink) linkStack.pop();
791             for (; l != null; l = l.getSibling()) {
792                 if (l.element != null) {
793                     if (!insertedNodes.containsKey(l.element)) {
794                         getNodesInsertNode(l.element, ret, insertedNodes, ignoredNodes);
795                         linkStack.push(l.element.getGraphLink());
796                     }
797                 }
798                 linkStack.push(l.getFirstChild());
799             }
800         }
801     }
802
803     private void getNodesInsertNode(GraphNode node, List ret,
804                                     Map insertedNodes, Map ignoredNodes) {
805         if (insertedNodes.containsKey(node)) {
806             //System.out.println("Found a duplicate in my insert journey: "+node);
807
return;
808         }
809         ret.add(node);
810         insertedNodes.put(node, null);
811         if (node.getExtension() != null)
812             getNodesInsertNode(node.getExtension(), ret, insertedNodes, ignoredNodes);
813         GraphNode alias = node.getAlias();
814         if (alias != null && !insertedNodes.containsKey(alias)) {
815             if (alias.getRefCount() <= 1) {
816                 // Only referenced by the thing which has an alias pointer to it.
817
ignoredNodes.put(alias, null);
818             } else {
819                 ret.add(alias);
820                 insertedNodes.put(alias, null);
821             }
822         }
823         return;
824     }
825     
826     public GraphNode getNode(String JavaDoc uniqueName) {
827         return (GraphNode)this.nameHash.get(uniqueName);
828     }
829     
830     public GraphNode getRoot() {
831         return this.rootNode;
832     }
833     
834     private static final String JavaDoc INDENT = " ";
835     
836     static void dumpAttributes(GraphNode elt, StringBuffer JavaDoc str, String JavaDoc indent) {
837         AttrProp[] attrList = elt.getAttributes();
838     
839         for (int i=0; i<attrList.length; i++)
840             str.append(indent + INDENT+"[attr: " + attrList[i] + "]\n");
841     }
842     
843     static void dumpTree(List children, StringBuffer JavaDoc str, String JavaDoc indent, boolean tree) {
844         for (Iterator it = children.iterator(); it.hasNext(); ) {
845             GraphLink l = (GraphLink) it.next();
846             dumpTree(l, str, indent, tree);
847         }
848     }
849     
850     static void dumpTree(GraphLink l, StringBuffer JavaDoc str, String JavaDoc indent, boolean tree) {
851         if (l == null)
852             return;
853         //str.append("dumpTree: l.name="+l.name+" l="+l+"\n");
854
if (l.element != null) {
855             //str.append("dumpTree: l.element="+l.element+"\n");
856
str.append(indent);
857             str.append(l.name + " : "+l.element.toString());
858             str.append(instanceToString(l.getElementInstance(), false) +
859                        "\n");
860         
861             dumpAttributes(l.element, str, indent);
862         
863             if (tree && (l.element.getMarked() == false)) {
864                 l.element.setMarked(true);
865                 dumpTree(l.element.getGraphLink(), str, indent + INDENT +
866                          instanceToString(l.getGroupInstance(), false) +
867                          (l.isSequenceOr()?"| ":" "), tree);
868                 l.element.setMarked(false);
869             }
870         }
871         
872         if (l.isSequenceOr() || (l.getGroupInstance() != Common.TYPE_1)) {
873             str.append(indent+instanceToString(l.getGroupInstance(), false)+
874                        (l.isSequenceOr()?"|\n":"\n"));
875         }
876         
877         dumpTree(l.getChildren(), str, indent + INDENT, tree );
878     }
879
880     //
881
public String JavaDoc dump() {
882         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
883         GraphNode n;
884     
885         str.append("Tree:\n");
886         str.append(this.rootNode.toString());
887         str.append("\n");
888     
889         dumpAttributes(rootNode, str, INDENT);
890         dumpTree(this.rootNode.getGraphLink(), str, INDENT, true);
891     
892         return str.toString();
893     }
894
895     public void setPrefixGuesser(PrefixGuesser guesser) {
896         prefixGuesser = guesser;
897     }
898
899     public PrefixGuesser getPrefixGuesser() {
900         return prefixGuesser;
901     }
902 }
903
904 //******************************************************************************
905
// END_NOI18N
906
// This class does not (and will not) cantain strings that need to be localized.
907
//******************************************************************************
908
Popular Tags