001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: XmlFormatModelNode.java 4255 2007-01-10 10:08:54Z lzheng $
023: */
024: package com.bostechcorp.cbesb.common.util.xfm;
025:
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030: import java.util.Vector;
031:
032: import javax.xml.namespace.QName;
033:
034: import org.eclipse.xsd.XSDCompositor;
035:
036: /**
037: * Document this please.
038: *
039: * The XmlFormatModelNode class represents the format definition for a XSD or MDL element.
040: *
041: * @author elu
042: *
043: */
044: // TODO: refractor the name to FormatModelNode since this is for XML and MDL
045: public class XmlFormatModelNode {
046:
047: public static int TYPE_NORMAL = 0;
048: public static int TYPE_ANY = 1;
049: public static int TYPE_ANYTYPE = 2;
050: private int sequnceNumber = 1;
051: private int allNumber = 1;
052: private int choiceNumber = 1;
053: private int anyNumber = 1;
054: private int groupNumber = 1;
055:
056: // keep the information of its children in a list
057: private Vector<XmlFormatModelNode> list = new Vector<XmlFormatModelNode>();
058:
059: // for performance purpose, maintain a map for the namme of node and its value to load the format tree faster
060: private HashMap<String, XmlFormatModelNode> map = new HashMap<String, XmlFormatModelNode>();
061:
062: // the attribute list for the current node
063: // TODO : the attributeFormDefault is still not supported right
064: // private Vector<String> attributeList = new Vector<String>();
065: private Vector<QName> attributeList = new Vector<QName>();
066:
067: // the name of the first element that reference this type
068: private String name = "";
069:
070: // the namespace URI for the first element reference the type
071: // TODO : we need to test this case when there are two elements with different namespace URI
072: // and reference to same type
073: private String namespaceURI;
074:
075: // we need to do special processing for the "choice"
076: private int anonymousType = -1;
077:
078: // this canBeRootElement is not used in XML Schema. Since MDL requires it, we have to put it here
079: private boolean canBeRootElement = true;
080:
081: // Point to the parent node
082: private XmlFormatModelNode parent = null;
083:
084: // the index of the current XmlFormatModelNode in the its parent node
085: int index = -1;
086: private int minOccurs = 1;
087: private int maxOccurs = 1;
088:
089: // private boolean elementQualified=true;
090:
091: // private boolean attributeQualified=false;
092: /**
093: * It store the original name.For example, the name maybe A{0}, but the original name
094: * is A;
095: */
096: private String originalName;
097: /**
098: * When content is detected in the schema that contains non-unique element names
099: * at the same level, the affected elements should be renamed to make them
100: * unique. This can be done by appending an index within curly braces to
101: * the name. Since curly braces are not legal XML characters, it should be
102: * clear that the addition to the name was made by Chainbuilder.
103: * For example, the above schema would appear as the following in the
104: * format model:example5
105: * + A{0}
106: * + B
107: * + A{1}
108: *
109: */
110: private int nameIndex = -1;
111:
112: private int type = TYPE_NORMAL;
113:
114: public XmlFormatModelNode() {
115:
116: }
117:
118: public XmlFormatModelNode(String name, String namespaceURI) {
119: this .name = name;
120: this .namespaceURI = namespaceURI;
121: }
122:
123: public XmlFormatModelNode(String name, String namespaceURI,
124: boolean elementQualified, boolean attributeQualified) {
125: this (name, namespaceURI);
126: // this.elementQualified = elementQualified;
127: // this.attributeQualified=attributeQualified;
128:
129: }
130:
131: public XmlFormatModelNode(String name, String namespaceURI,
132: int anonymousType) {
133: this (name, namespaceURI);
134: this .anonymousType = anonymousType;
135:
136: }
137:
138: public XmlFormatModelNode(XmlFormatModelNode node) {
139: this (node.getName(), node.getNamespaceURI());
140: this .anonymousType = node.getAnonymousType();
141: // this.elementQualified=node.elementQualified;
142: // this.attributeQualified=node.attributeQualified;
143: this .canBeRootElement = node.canBeRootElement;
144:
145: node.addChildrenTo(this );
146:
147: }
148:
149: public String getName() {
150: return name;
151: }
152:
153: /**
154: * Copy the entire stucture in current XmlFormatModelNodel into 'tar' (target)
155: * @param tar : target object
156: */
157: public void addChildrenTo(XmlFormatModelNode tar) {
158:
159: List childNodesList = getList();
160: for (int i = 0; i < childNodesList.size(); i++) {
161: XmlFormatModelNode n = (XmlFormatModelNode) childNodesList
162: .get(i);
163: tar.addChild(n);
164: }
165: for (Iterator it = this .getAttributeList().iterator(); it
166: .hasNext();) {
167: // String attr=(String)it.next();
168: QName attr = (QName) it.next();
169: if (!tar.getAttributeList().contains(attr))
170: tar.getAttributeList().add(attr);
171: }
172: copyNumberTo(tar);
173: }
174:
175: /**
176: * Copy the sequnceNumber,choiceNumber, allNumber,... in current XmlFormatModelNodel into 'tar' (target)
177: * @param tar : target object
178: */
179: public void copyNumberTo(XmlFormatModelNode tar) {
180: if (this .sequnceNumber > tar.sequnceNumber)
181: tar.sequnceNumber = this .sequnceNumber;
182: if (this .allNumber > tar.allNumber)
183: tar.allNumber = this .allNumber;
184: if (this .anyNumber > tar.anyNumber)
185: tar.anyNumber = this .anyNumber;
186: if (this .choiceNumber > tar.choiceNumber)
187: tar.choiceNumber = this .choiceNumber;
188: if (this .groupNumber > tar.groupNumber)
189: tar.groupNumber = this .groupNumber;
190: }
191:
192: public List getList() {
193: return list;
194: }
195:
196: //public XmlFormatModelNode addElement(String key, XmlFormatModelNode child) {
197:
198: // XmlFormatModelNode n = new XmlFormatModelNode(key, child);
199: // return this.addElement(n);
200: // }
201: public void addElement(XmlFormatModelNode node) {
202:
203: String name = node.getName();
204: if (map.containsKey(name)) {
205: XmlFormatModelNode oldNode = map.get(name);
206: oldNode.setName(name + "{0}");
207: oldNode.setOriginalName(name);
208: oldNode.setNameIndex(0);
209: map.remove(name);
210: map.put(oldNode.getName(), oldNode);
211: node.setName(name + "{1}");
212: node.setOriginalName(name);
213: node.setNameIndex(1);
214: } else if (map.containsKey(name + "{0}")) {
215: int i = 1;
216: while (map.containsKey(name + "{" + i + "}")) {
217: i++;
218: }
219: node.setName(name + "{" + i + "}");
220: node.setOriginalName(name);
221: node.setNameIndex(i);
222:
223: }
224:
225: addChild(node);
226:
227: }
228:
229: public void addAnonymousElement(XmlFormatModelNode node) {
230:
231: if (node.isAnonymous()) {
232:
233: String nodeName = "";
234: if (node.getAnonymousType() == AnonymousConstants.TYPE_SEQUENCE) {
235: nodeName = AnonymousConstants.SEQUENCE + "_"
236: + String.valueOf(sequnceNumber++);
237: } else if (node.getAnonymousType() == AnonymousConstants.TYPE_ALL) {
238: nodeName = AnonymousConstants.ALL + "_"
239: + String.valueOf(allNumber++);
240:
241: } else if (node.getAnonymousType() == AnonymousConstants.TYPE_CHOICE) {
242:
243: nodeName = AnonymousConstants.CHOICE + "_"
244: + String.valueOf(choiceNumber++);
245: } else if (node.getAnonymousType() == AnonymousConstants.TYPE_GROUP) {
246: nodeName = AnonymousConstants.GROUP + "_"
247: + String.valueOf(groupNumber++);
248: }
249: node.setName(nodeName);
250:
251: } else if (node.getName().equals("any")) {
252: String nodeName = "any_" + String.valueOf(anyNumber++);
253: node.setName(nodeName);
254: }
255: addChild(node);
256:
257: }
258:
259: public void addAnyElement(XmlFormatModelNode node) {
260:
261: String nodeName = "any_" + String.valueOf(anyNumber++);
262: node.setName(nodeName);
263:
264: addChild(node);
265:
266: }
267:
268: private void addChild(XmlFormatModelNode node) {
269:
270: node.index = list.size();
271: list.add(node);
272: map.put(node.getKey(), node);
273: node.setParent(this );
274:
275: }
276:
277: public XmlFormatModelNode getNode(String key) {
278: XmlFormatModelNode nn = (XmlFormatModelNode) map.get(key);
279:
280: return nn;
281: }
282:
283: public XmlFormatModelNode getChild(String key) {
284: return getNode(key);
285: }
286:
287: public int size() {
288: return list.size();
289: }
290:
291: // add by J
292: public List<QName> getAttributeList() {
293: return attributeList;
294: }
295:
296: public String toString() {
297: StringBuffer result = new StringBuffer();
298: String tabs = "";
299: recurseToString(this , tabs, result);
300: return result.toString();
301: }
302:
303: private void recurseToString(XmlFormatModelNode fn, String tabs,
304: StringBuffer result) {
305: for (Iterator i = fn.list.iterator(); i.hasNext();) {
306: XmlFormatModelNode nn = (XmlFormatModelNode) i.next();
307: result.append(nn.name + "\n");
308: if (nn != null)
309: recurseToString(nn, tabs + " ", result);
310: }
311: }
312:
313: public Map<QName, String> toElementMap() {
314: Map<QName, String> elementMap = new HashMap<QName, String>();
315: recurseToElementMap(this , elementMap);
316: return elementMap;
317: }
318:
319: private void recurseToElementMap(XmlFormatModelNode fn,
320: Map<QName, String> elementMap) {
321: for (Iterator i = fn.list.iterator(); i.hasNext();) {
322: XmlFormatModelNode nn = (XmlFormatModelNode) i.next();
323: QName key = new QName(fn.getNamespaceURI(), nn.name);
324: if (!elementMap.containsKey(key)) {
325: elementMap.put(key, nn.name);
326: if (nn != null)
327: recurseToElementMap(nn, elementMap);
328: }
329: }
330: }
331:
332: // /**
333: // * The NamedNode contains a key which is the name of node displayed on the format tree and a child XMLFormatModeNode object
334: // *
335: // * @author elu
336: // *
337: // */
338: // public class NamedNode {
339: // // the element name displayed in the format tree
340: // String key;
341: //
342: // // the index of the current NamedNode in the its parent node
343: // int index = -1;
344: // private int minOccurs = 1;
345: // /**
346: // * This is the flag of the maxOccurs attribute of node. It is used to show a
347: // * different icon for this type of node. If the maxOccurs is bigger than "1"
348: // * or equals "unbounded", the isRepeatable is true. Otherwise, the
349: // * isRepeatable is false;
350: // */
351: // private boolean isRepeatable = false;
352: //
353: // private boolean elementQualified=true;
354: //
355: // private boolean attributeQualified=true;
356: //
357: //
358: // // the XMLFormatModelNode object of this NamedNode points to
359: // // TODO : we need to refractor from "child" to "selfXfmNode"
360: // XmlFormatModelNode selfXfmMode;
361: //
362: // public NamedNode(String key, XmlFormatModelNode selfXfmMode) {
363: // this.key = key;
364: // this.selfXfmMode = selfXfmMode;
365: // }
366: // public NamedNode(String name, String namespaceURI) {
367: // this.key = name;
368: // this.selfXfmMode = new XmlFormatModelNode(namespaceURI);
369: // }
370: //
371: // public boolean isRepeatable() {
372: // return this.isRepeatable;
373: // }
374: //
375: // public void setRepeatable(boolean isRepeatable) {
376: // this.isRepeatable = isRepeatable;
377: // }
378: //
379: // public String getKey() {
380: // return key;
381: // }
382: //
383: // public XmlFormatModelNode getSelXfmNode() {
384: // return selfXfmMode;
385: // }
386: //
387: // public boolean canBeRootElement() {
388: // return this.getSelXfmNode().canBeRootElement();
389: // }
390: //
391: // public List getAttribute() {
392: // return getAttributeList();
393: // }
394: //
395: // public int getIndex() {
396: // return index;
397: // }
398: //
399: // public void setIndex(int index) {
400: // this.index = index;
401: // }
402: //
403: // public int getMinOccurs() {
404: // return minOccurs;
405: // }
406: //
407: // public void setMinOccurs(int minOccurs) {
408: // this.minOccurs = minOccurs;
409: // }
410: // public boolean isElementQualified() {
411: // return elementQualified;
412: // }
413: // public void setElementQualified(boolean qualified) {
414: // this.elementQualified = qualified;
415: // }
416: // public boolean isAttributeQualified() {
417: // return attributeQualified;
418: // }
419: // public void setAttributeQualified(boolean attributeQualified) {
420: // this.attributeQualified = attributeQualified;
421: // }
422: //
423: //
424: // }
425:
426: public String getTopNodeName() {
427: String hasChildFirstNodeName = null;
428: for (Iterator i = this .list.iterator(); i.hasNext();) {
429: XmlFormatModelNode nn = (XmlFormatModelNode) i.next();
430: if (nn.list.size() != 0) {
431: hasChildFirstNodeName = nn.getKey();
432: break;
433: }
434: }
435: return hasChildFirstNodeName;
436: }
437:
438: public String getNamespaceURI() {
439: return namespaceURI;
440: }
441:
442: public void setNamespaceURI(String namespaceURI) {
443: this .namespaceURI = namespaceURI;
444: }
445:
446: public boolean canBeRootElement() {
447: return canBeRootElement;
448: }
449:
450: public void setCanBeRootElement(boolean canBeRootElement) {
451: this .canBeRootElement = canBeRootElement;
452: }
453:
454: public boolean isAnonymous() {
455: return this .anonymousType > -1;
456: }
457:
458: public XmlFormatModelNode getParent() {
459: return parent;
460: }
461:
462: public void setParent(XmlFormatModelNode parent) {
463: this .parent = parent;
464: }
465:
466: public int getAnonymousType() {
467: return anonymousType;
468: }
469:
470: public void setAnonymousType(int anonymousType) {
471: this .anonymousType = anonymousType;
472: }
473:
474: // public boolean isElementQualified() {
475: // return elementQualified;
476: // }
477: //
478: // public void setElementQualified(boolean elementQualified) {
479: // this.elementQualified = elementQualified;
480: // }
481:
482: public int getIndex() {
483: return index;
484: }
485:
486: public void setIndex(int index) {
487: this .index = index;
488: }
489:
490: /**
491: * This is the flag of the maxOccurs attribute of node. It is used to show a
492: * different icon for this type of node. If the maxOccurs is bigger than "1"
493: * or equals "unbounded", the isRepeatable is true. Otherwise, the
494: * isRepeatable is false;
495: */
496:
497: public boolean isRepeatable() {
498: return this .maxOccurs > 1 || this .maxOccurs == -1;
499: }
500:
501: public String getKey() {
502: return name;
503: }
504:
505: public int getMinOccurs() {
506: return minOccurs;
507: }
508:
509: public void setMinOccurs(int minOccurs) {
510: this .minOccurs = minOccurs;
511: }
512:
513: public boolean isCanBeRootElement() {
514: return canBeRootElement;
515: }
516:
517: public void setList(Vector<XmlFormatModelNode> list) {
518: this .list = list;
519: }
520:
521: public void setName(String name) {
522: this .name = name;
523: }
524:
525: // public boolean isAttributeQualified() {
526: // return attributeQualified;
527: // }
528: //
529: // public void setAttributeQualified(boolean attributeQualified) {
530: // this.attributeQualified = attributeQualified;
531: // }
532:
533: public int getNameIndex() {
534: return nameIndex;
535: }
536:
537: public void setNameIndex(int nameIndex) {
538: this .nameIndex = nameIndex;
539: }
540:
541: public String getOriginalName() {
542: if (this .nameIndex > -1)
543: return this .originalName;
544: else
545: return this .name;
546: }
547:
548: public void setOriginalName(String originalName) {
549: this .originalName = originalName;
550: }
551:
552: public int getType() {
553: return type;
554: }
555:
556: public void setType(int type) {
557: this .type = type;
558: }
559:
560: public int getMaxOccurs() {
561: return maxOccurs;
562: }
563:
564: public void setMaxOccurs(int maxOccurs) {
565: this .maxOccurs = maxOccurs;
566: }
567:
568: public boolean isOptional() {
569: return this .minOccurs == 0;
570: }
571:
572: }
|