1 19 package org.netbeans.lib.jmi.xmi; 20 21 import java.util.*; 22 23 import org.xml.sax.*; 24 import org.xml.sax.helpers.DefaultHandler ; 25 import org.xml.sax.helpers.AttributesImpl ; 26 import javax.xml.parsers.SAXParserFactory ; 27 import javax.xml.parsers.ParserConfigurationException ; 28 import javax.xml.parsers.SAXParser ; 29 30 import org.netbeans.api.xmi.*; 31 import org.netbeans.lib.jmi.util.DebugException; 32 33 import javax.jmi.reflect.*; 34 import javax.jmi.model.*; 35 import org.netbeans.lib.jmi.util.Logger; 36 37 public abstract class XmiElement { 38 39 protected XmiContext context; 41 protected XmiElement parent; 43 44 public XmiElement (XmiElement parent, XmiContext context) { 45 this.parent = parent; 46 this.context = context; 47 } 48 49 public XmiElement (XmiContext context) { 50 this.context = context; 51 } 52 53 57 public XmiElement startSubElement (String qName, Attributes attrs) { 58 return this; 59 } 60 61 64 public XmiElement endElement (String qName) { 65 return parent; 66 } 67 68 71 public void characters (char buf[], int offset, int len) { 72 return; 74 } 75 76 79 public void receiveValue (Object value) { 80 throw new DebugException ("Unexpected call of receiveValue () method."); 82 } 83 84 88 public static class Document extends XmiElement { 92 93 private String rootElementName; 94 private Content content = null; 95 private XmiElement xmiElement = null; 96 97 public Document (XmiElement parent, XmiContext context, String rootName, Attributes attrs) { 98 super (parent, context); 99 rootElementName = rootName; 100 context.setVersion (attrs); 101 if (context.isXmi20) { 102 content = new Content (this, context); 103 if (!rootElementName.equals (context.xmiNsPrefix + XmiConstants.XMI_ROOT)) { 104 AttributesImpl attrs2 = new AttributesImpl (); 105 for (int x = 0; x < attrs.getLength (); x++) { 106 String name = attrs.getQName (x); 107 if (!(name.equals ("xmlns") || name.startsWith ("xmlns:") || 108 name.equals (context.xmiNsPrefix + XmiConstants.XMI20_VERSION))) { 109 attrs2.addAttribute (null, null, name, null, attrs.getValue (x)); 110 } } xmiElement = content.startSubElement (rootElementName, attrs2); 113 } } } 116 117 public XmiElement startSubElement (String qName, Attributes attrs) { 118 if (context.isXmi20) { 119 if (xmiElement != null) 121 return xmiElement.startSubElement (qName, attrs); 122 else 123 return content.startSubElement (qName, attrs); 124 } else { 125 if (qName.equals (XmiConstants.XMI_CONTENT)) { 126 return new XmiElement.Content (this, context); 127 } else if (qName.equals (XmiConstants.XMI_DIFFERENCE)) { 128 return new XmiElement.Difference (this, context, attrs); 129 } else if (qName.equals (XmiConstants.XMI_HEADER)) { 130 return new XmiElement.Header (this, context); 131 } else { 132 if (context.ignoreUnknownElements()) { 133 return new XmiElement.Dummy(this, context, qName); 134 } else { 135 throw new DebugException("Invalid element name: " + qName); 136 } 137 } 138 } 139 } 140 141 public XmiElement endElement (String qName) { 142 if (qName.equals (rootElementName)) { 143 if (context.isXmi20) { 144 if (xmiElement != null) 145 xmiElement.endElement (qName); 146 content.endElement (qName); 147 } 148 context.finish (); 149 return parent; 150 } 151 return this; 152 } 153 154 } 156 157 161 public static class Header extends XmiElement { 162 163 private int level = 0; 164 private StringBuffer buffer = new StringBuffer (); 165 166 public Header (XmiElement parent, XmiContext context) { 167 super (parent, context); 168 } 169 170 public XmiElement startSubElement (String qName, Attributes attrs) { 171 level++; 172 buffer.append ('<' + qName); 173 int attrsLength = attrs.getLength (); 174 for (int index = 0; index < attrsLength; index++) { 175 String attrName = attrs.getQName (index); 176 String attrValue = attrs.getValue (index); 177 buffer.append (" " + attrName + " = '" + attrValue + "'"); 178 } buffer.append ('>'); 180 return this; 181 } 182 183 public XmiElement endElement (String qName) { 184 if (level == 0) { 185 context.receiveHeader (buffer.toString ()); 186 return parent; 187 } 188 buffer.append ("</" + qName + '>'); 189 level--; 190 return this; 191 } 192 193 public void characters (char buf[], int offset, int len) { 194 buffer.append (buf, offset, len); 195 } 196 197 } 199 public static class Difference extends XmiElement { 203 204 206 private String href; 208 private boolean diffReading; 210 private Diff currentDiff; 212 private HashMap diffs = new HashMap (); 214 private int timeStamp = 1; 215 216 public Difference (XmiElement parent, XmiContext context, Attributes attrs) { 217 super (parent, context); 218 href = attrs.getValue (context.XMI_HREF); 219 if (href == null) 220 throw new DebugException ( 221 "Differences referring to the document they are placed in are not supported." 222 ); 223 diffReading = false; 224 } 225 226 public XmiElement startSubElement (String qName, Attributes attrs) { 227 if (!diffReading) { 228 if (qName.equals (XmiConstants.XMI_DIFFERENCE)) 229 throw new DebugException ("Nested differences are not supported."); 230 int kind = Diff.ADD; 231 if (qName.equals (XmiConstants.XMI_DELETE)) 232 kind = Diff.DELETE; 233 else if (qName.equals (XmiConstants.XMI_REPLACE)) 234 kind = Diff.REPLACE; 235 String localHref = attrs.getValue (context.XMI_HREF); 236 int index = localHref.lastIndexOf ("|"); 237 if (index == -1) 238 index = localHref.lastIndexOf ("#"); 239 String id = localHref.substring (index + 1, localHref.length ()); 240 String posString = attrs.getValue (XmiConstants.XMI_POSITION); 241 int position = 1; if (posString != null) { 243 try { 244 position = Integer.parseInt (posString); 245 } catch (NumberFormatException e) { 246 throw new DebugException ("Differences - bad number format: " + posString); 247 } 248 } if (position < 0) 250 throw new DebugException ("Negative values of xmi.position parameters are not supported: " + posString); 251 currentDiff = new Diff (kind, id, position, timeStamp); 252 timeStamp++; 253 diffReading = true; 254 } else { currentDiff.items.add (new Item (qName, attrs)); 256 } 257 return this; 258 } 259 260 public void characters (char buf[], int offset, int len) { 261 if (diffReading) { 262 currentDiff.items.add (new String (buf, offset, len)); 263 } 264 } 265 266 public XmiElement endElement (String qName) { 267 if (diffReading) { 268 if ((qName.equals (XmiConstants.XMI_ADD)) || 269 (qName.equals (XmiConstants.XMI_DELETE)) || 270 (qName.equals (XmiConstants.XMI_REPLACE))) { 271 diffReading = false; 272 LinkedList list = (LinkedList) diffs.get (currentDiff.xmiId); 273 if (list == null) 274 diffs.put (currentDiff.xmiId, list = new LinkedList ()); 275 if (currentDiff.kind == Diff.DELETE) 276 list.addFirst (currentDiff); 277 else 278 list.addLast (currentDiff); 279 } else 280 currentDiff.items.add (new Item (qName)); 281 return this; 282 } 283 context.resolveDifferences (href, diffs); 285 return parent; 286 } 287 288 public static class Diff { 290 public static final int ADD = 0; 292 public static final int DELETE = 1; 293 public static final int REPLACE = 2; 294 295 public int kind; 297 public int position; 299 public String xmiId; 301 public LinkedList items = new LinkedList (); 304 public int timeStamp; 305 306 public Diff (int kind, String xmiId, int position, int timeStamp) { 307 this.kind = kind; 308 this.xmiId = xmiId; 309 this.position = position; 310 this.timeStamp = timeStamp; 311 } 312 313 } 314 315 public static class Item { 317 public boolean isStart; 319 public String qName; 321 public Attributes attrs; 323 324 public Item (String qName) { 326 this.qName = qName; 327 isStart = false; 328 } 329 330 public Item (String qName, Attributes attrs) { 332 this.qName = qName; 333 this.attrs = new AttributesImpl (attrs); 335 isStart = true; 336 } 337 } 338 339 } 341 public static class Content extends XmiElement { 345 348 private Attribute attr = null; 350 private RefClass refClass = null; 352 private List values; 354 355 public Content (XmiElement parent, XmiContext context) { 356 super (parent, context); 357 } 358 359 public XmiElement startSubElement (String qName, Attributes attrs) { 360 Object ref = context.resolveElementName (qName); 361 if ((ref == null) && context.ignoreUnknownElements()) { 362 return new XmiElement.Dummy(this, context, qName); 363 } 364 if (ref instanceof RefClass) 366 return context.resolveInstanceOrReference (this, qName, attrs); 367 if (ref instanceof Attribute) { 369 RefClass readRefClass = (RefClass) context.resolveElementName ( 370 qName.substring (0, qName.lastIndexOf (XmiConstants.DOT_SEPARATOR)) 371 ); 372 if ((ref != attr) || (refClass != readRefClass)) { 373 if (attr != null) { 375 setAttributeValue (); 377 } 378 attr = (Attribute) ref; 379 refClass = readRefClass; 380 values = new LinkedList (); 381 } 382 return new XmiElement.ClassLevelAttribute (this, context, attr, attrs); 384 } 385 if (ref instanceof Association) 387 return new XmiElement.AssociationElement (this, context, (Association) ref); 388 throw new DebugException ("Unexpected element: " + qName); 390 } 391 392 public XmiElement endElement (String qName) { 393 if (attr != null) { 394 setAttributeValue (); 397 } 398 399 context.resolveExternalReferences (); 401 402 if (context.isMain && !context.allReferencesResolved ()) { 403 String badRef = context.getUnresolvedRefId (); 408 Logger.getDefault ().log ("Unknown reference or circularity in instance dependences detected, bad reference: " + badRef); 409 } 411 return parent; 412 } 413 414 public void receiveValue (Object value) { 415 if (attr == null) 417 throw new DebugException ("Unexpected call of Content.receiveValue ()"); 418 if (value instanceof List) 419 values.addAll ((List) value); 420 else 421 values.add (value); 422 } 423 424 private void setAttributeValue () { 425 LinkedList list = new LinkedList (); 426 Iterator iter = values.iterator (); 427 Object value; 428 while (iter.hasNext ()) { 429 value = iter.next (); 430 if (value instanceof UnresolvedReference) { 431 value = ((UnresolvedReference) value).getValue (); 432 if (value == null) { 433 throw new DebugException ("Class-scoped attribute value not resolved: " + attr.getName ()); 434 } 435 } 436 list.add (value); 437 } 438 if (XmiContext.isMultivalued (attr)) 439 value = list; 440 else { 441 if (!(list.size () == 1)) 442 throw new DebugException ("Cannot set a multi-value to a non-multivalued attribute:" + attr.getName ()); 443 value = list.get (0); 444 } 445 refClass.refSetValue (attr, value); 446 attr = null; 447 refClass = null; 448 values = null; 449 } 450 451 } 453 public static class Instance extends XmiElement implements ReferencesCounter { 457 private String name; 459 private String xmiId = null; 461 private String docId; 463 private int unresolvedRefsCounter = 0; 465 private boolean endReached = false; 467 private UnresolvedReference unresRef = null; 469 private StructuralFeature currentFeature; 471 private Classifier currentType; 473 474 private RefClass refClass; 476 private MofClass metaClass; 478 private HashMap attributesValues = new HashMap (); 480 private HashMap referencesValues = new HashMap (); 482 483 public Instance (XmiElement parent, XmiContext context, String qName, 484 RefClass refClass, Attributes attrs) { 485 486 super (parent, context); 487 this.name = qName; 488 this.docId = context.getCurrentDocId (); 489 this.refClass = refClass; 490 metaClass = (MofClass) refClass.refMetaObject (); 491 492 int index; String attrName, attrValue; 494 int attrsLength = attrs.getLength (); 495 for (index = 0; index < attrsLength; index++) { 497 attrName = attrs.getQName (index); 498 attrValue = attrs.getValue (index); 499 if (attrName.equals (context.XMI_ID)) { 500 xmiId = attrValue; 501 } else { 502 resolveAttributeValue (attrName, attrValue); 503 } 504 } } 506 507 public XmiElement startSubElement (String qName, Attributes attrs) { 508 Object ref = context.resolveElementName (qName); 509 if (ref == null && context.ignoreUnknownElements()) { 510 return new XmiElement.Dummy(this, context, qName); 511 } 512 513 if (!(ref instanceof StructuralFeature)) { 514 throw new DebugException ("Invalid sub-element: " + qName); 515 } 516 currentFeature = (StructuralFeature) ref; 517 if (currentFeature.getScope ().equals (ScopeKindEnum.CLASSIFIER_LEVEL) && !context.isXmi20) { 518 throw new DebugException ("An instance serialization contains value of static attribute: " + currentFeature.getName ()); 519 } 520 521 if (currentFeature instanceof Attribute) { 522 Classifier type = currentFeature.getType (); 523 return context.resolveValue (this, type, attrs); 524 } else if (currentFeature instanceof Reference) { 525 return new XmiElement.ObjectValues (this, context, null, false); 526 } 527 throw new DebugException ("Invalid sub-element: " + qName); 528 } 529 530 534 private RefObject createInstance () { 535 536 List attributes = context.instanceAttributes (refClass); 537 List references = context.instanceReferences (refClass); 538 539 List args = new LinkedList (); 541 Iterator iter = attributes.iterator (); 542 while (iter.hasNext ()) { 543 Attribute attr = (Attribute) iter.next (); 544 Object param = attributesValues.get (attr); 545 if (param instanceof UnresolvedReference) { 546 param = ((UnresolvedReference) param).getValue (); 547 } else if (param instanceof List) { 548 Iterator iter2 = ((List) param).iterator (); 549 List temp = new LinkedList (); 550 while (iter2.hasNext ()) { 551 Object value = iter2.next (); 552 if (value instanceof UnresolvedReference) { 553 value = ((UnresolvedReference) value).getValue (); 554 if (value instanceof CollectionWrapper) 555 value = ((CollectionWrapper) value).getCollection (); 556 } 557 temp.add (value); 558 } 559 param = temp; 560 } 561 if (param instanceof CollectionWrapper) 562 param = ((CollectionWrapper) param).getCollection (); 563 if (param == null) 564 param = XmiContext.defaultValue (attr); 565 args.add (param); 566 } RefObject instance; 568 try { 569 instance = refClass.refCreateInstance (args); 570 } catch (Exception e) { 571 StringBuffer params = new StringBuffer (50); 572 for (Iterator it = args.iterator(); it.hasNext();) { 573 Object arg = it.next(); 574 params.append(" "); 575 if (arg == null) { 576 params.append("<null>"); 577 } else { 578 params.append("(" + arg.getClass() + ") " + arg.toString()); 579 } 580 params.append("\n"); 581 } 582 587 String msg = "Instance of " + name + " cannot be created, parameters:\n" + params.toString() + "\n reason: " + e.toString(); 588 Logger.getDefault ().log (msg); 589 return null; 590 } 591 if (parent instanceof XmiElement.Content) { 592 context.addOutermostObject (instance); 593 } 594 595 if (xmiId != null) 597 context.putReference (docId, xmiId, instance); 598 599 iter = references.iterator (); 601 while (iter.hasNext ()) { 602 Reference ref = (Reference) iter.next (); 603 List values = (List) referencesValues.get (ref); 604 if (values != null) 605 new ReferenceHandler (ref, instance, values, context); 606 } 608 context.countInstance (); 609 610 if (context.isXmi20) { 611 iter = context.staticAttributes (refClass).iterator (); 613 while (iter.hasNext ()) { 614 Attribute attr = (Attribute) iter.next (); 615 Object value = attributesValues.get (attr); 616 if (value != null) { 617 refClass.refSetValue (attr, value); 618 } } } 622 return instance; 623 } 624 625 public XmiElement endElement (String qName) { 626 endReached = true; 631 if (unresolvedRefsCounter == 0) { 632 RefObject instance = createInstance (); 633 if (!(parent instanceof XmiElement.Content)) { 634 parent.receiveValue (instance); 635 } 636 } else { 637 if (!(parent instanceof XmiElement.Content)) { 638 unresRef = new UnresolvedReference (); 639 parent.receiveValue (unresRef); 640 } 641 } 642 return parent; 643 } 644 645 650 private void setAttributeValue (StructuralFeature attr, Object value) { 653 boolean isMultivalued = XmiContext.isMultivalued (attr); 654 Object tempValue = attributesValues.get (attr); 655 if (!isMultivalued) { 656 if (tempValue != null) 657 throw new DebugException ("Cannot set a multi-value to a non-multivalued attribute:" + attr.getName ()); 658 attributesValues.put (attr, value); 659 660 665 666 } else { 667 if (tempValue == null) 668 attributesValues.put (attr, tempValue = new LinkedList ()); 669 ((List) tempValue).add (value); 670 } } 672 673 677 private void setAttributeValues (StructuralFeature attr, List values) { 678 boolean isMultivalued = XmiContext.isMultivalued (attr); 679 if (!isMultivalued && (values.size () == 1)) { 680 setAttributeValue (attr, values.get (0)); 681 return; 682 } 683 684 687 688 if (!isMultivalued) { 689 throw new DebugException ("Cannot set a multi-value to a non-multivalued attribute:" + attr.getName ()); 690 } 691 Object tempValue = attributesValues.get (attr); 692 if (tempValue == null) 693 attributesValues.put (attr, tempValue = new LinkedList ()); 694 ((List) tempValue).addAll (values); 695 } 696 697 700 private void setReferenceValues (Reference ref, List values) { 701 boolean isMultivalued = XmiContext.isMultivalued (ref); 702 Object tempValue = referencesValues.get (ref); 703 if (!isMultivalued) { 704 if ((tempValue != null) || (values.size () > 1)) { 705 throw new DebugException 706 ("Cannot set a multi-value to a non-multivalued reference:" + ref.getName()); 707 } 708 referencesValues.put (ref, values); 709 return; 710 } 711 if (tempValue == null) 712 referencesValues.put (ref, tempValue = new LinkedList ()); 713 ((List) tempValue).addAll (values); 714 } 715 716 public void receiveValue (Object value) { 717 if (currentFeature instanceof Attribute) { 718 if (value instanceof List) 719 setAttributeValues (currentFeature, (List) value); 720 else 721 setAttributeValue (currentFeature, value); 722 } else { if (!(value instanceof List)) { 725 List temp = new LinkedList (); 726 temp.add (value); 727 value = temp; 728 } 729 setReferenceValues ((Reference) currentFeature, (List) value); 730 } 731 } 732 733 737 private void resolveAttributeValue (String attrName, String attrValue) { 738 StructuralFeature attr; 739 740 attr = context.instanceElementByName (refClass, attrName); 741 if ((attr == null) && context.isXmi20) { 742 attr = context.staticAttributeByName (refClass, attrName); 743 } 744 if (attr == null) 745 return; 746 747 Classifier type = attr.getType (); 748 while (type instanceof AliasType) 749 type = ((AliasType) type).getType (); 750 Object value = null; 751 752 if (type instanceof PrimitiveType) { 753 value = XmiContext.resolvePrimitiveValue ((PrimitiveType) type, attrValue); 754 setAttributeValue (attr, value); 755 } else if (type instanceof EnumerationType) { 756 value = context.resolveEnumerationValue ((EnumerationType) type, attrValue); 757 setAttributeValue (attr, value); 758 } else if (type instanceof MofClass) { 759 boolean isReference = attr instanceof Reference; 760 StringTokenizer tokenizer = new StringTokenizer (attrValue, " "); 761 List list = new LinkedList (); 762 while (tokenizer.hasMoreTokens ()) { 763 String xmiId = tokenizer.nextToken (); 766 Object obj = context.getReference (xmiId); 767 if (obj == null) { 768 if (isReference) 770 obj = new UnresolvedReference (); 771 else 772 obj = new UnresolvedReference (this); 773 context.registerUnresolvedRef (xmiId, (UnresolvedReference) obj); 774 } 775 list.add (obj); 776 } if (isReference) 778 setReferenceValues ((Reference) attr, list); 779 else 780 setAttributeValues (attr, list); 781 } else { 782 throw new DebugException ("type cannot be resolved: " + attr.getType ().getName ()); 783 } 784 } 785 786 788 public void increaseUnresolvedRefs () { 789 unresolvedRefsCounter++; 790 } 791 792 public void decreaseUnresolvedRefs () { 793 unresolvedRefsCounter--; 794 if (endReached && (unresolvedRefsCounter == 0)) { 795 RefObject instance = createInstance (); 796 if (unresRef != null) 797 unresRef.referenceResolved (instance); 798 } 799 } 800 801 } 803 public static class DataTypeElement extends XmiElement { 807 808 820 821 private boolean typeCodeReading = false; 823 private Node node = null; 825 private String xmiId; 827 private String docId; 829 830 public DataTypeElement (XmiElement parent, XmiContext context, 831 String name, Attributes attrs) { 832 super (parent, context); 833 xmiId = attrs.getValue (context.XMI_ID); 834 docId = context.getCurrentDocId (); 835 } 836 837 public XmiElement startSubElement (String qName, Attributes attrs) { 838 if (!typeCodeReading) { 839 if (qName.endsWith ("typeCode")) 840 typeCodeReading = true; 841 return this; 842 } 843 if ((node == null) && (!qName.equals (XmiConstants.XMI_CORBA_TYPE_CODE))) 844 throw new DebugException ("XMI.CorbaTypeCode element expected"); 845 node = new Node (qName, attrs, node); 846 return this; 847 } 848 849 public XmiElement endElement (String qName) { 850 if (typeCodeReading) { 851 if (node.parent != null) 852 node = node.parent; 853 else 854 typeCodeReading = false; 855 return this; 856 } 857 if (!qName.endsWith ("DataType")) 858 return this; 859 RefObject typeEquivalent = context.resolveCorbaType (node, false); 861 if (xmiId != null) 862 context.putReference (docId, xmiId, typeEquivalent); 863 if (!(parent instanceof XmiElement.Content)) 864 parent.receiveValue (typeEquivalent); 865 return parent; 866 } 867 868 public static class Node { 870 public Node parent; 872 public List subnodes = new LinkedList (); 874 public String name; 876 public String tcName; 878 879 public Node (String name, Attributes attrs, Node parent) { 880 this.parent = parent; 881 this.name = name; 882 tcName = attrs.getValue (XmiConstants.XMI_TCNAME); 883 if (parent != null) 884 parent.addSubNode (this); 885 } 886 887 public void addSubNode (Node subNode) { 888 subnodes.add (subNode); 889 } 890 891 public Node firstSubNode () { 892 return (Node) subnodes.get (0); 893 } 894 895 } 897 } 899 public static class ClassLevelAttribute extends XmiElement { 903 904 private Classifier type; 905 906 public ClassLevelAttribute (XmiElement parent, XmiContext context, Attribute attr, 907 Attributes attrs) { 908 super (parent, context); 909 type = attr.getType (); 910 } 911 912 public XmiElement startSubElement (String qName, Attributes attrs) { 913 return context.resolveValue (this, type, attrs); 914 } 915 916 public void receiveValue (Object value) { 917 parent.receiveValue (value); 919 } 920 921 } 923 public static class AssociationElement extends XmiElement implements ReferencesCounter { 927 928 private Association assoc; 930 private boolean oddNumberOfElementsRead = false; 932 private int counter = 0; 934 private boolean endReached = false; 936 private List elements = new LinkedList (); 938 939 public AssociationElement (XmiElement parent, XmiContext context, Association assoc) { 940 super (parent, context); 941 this.assoc = assoc; 942 } 943 944 public XmiElement startSubElement (String qName, Attributes attrs) { 945 return context.resolveInstanceOrReference (this, qName, attrs); 946 } 947 948 public void receiveValue (Object obj) { 949 if (obj instanceof UnresolvedReference) { 950 ((UnresolvedReference) obj).setOwner (this); 951 } 952 elements.add (obj); 953 oddNumberOfElementsRead = !oddNumberOfElementsRead; 954 } 955 956 public XmiElement endElement (String qName) { 957 if (oddNumberOfElementsRead) { 958 throw new DebugException ("Odd number of association ends serialized: " + assoc.getName ()); 959 } 960 endReached = true; 961 if (counter == 0) 962 createLinks (); 963 return parent; 964 } 965 966 private void createLinks () { 967 RefAssociation refAssoc = ((RefPackage) context.findProxy (assoc)).refAssociation (assoc); 968 Iterator iter = elements.iterator (); 969 while (iter.hasNext ()) { 970 Object firstObject = iter.next (); 971 Object secondObject = iter.next (); 972 if (firstObject instanceof UnresolvedReference) 973 firstObject = ((UnresolvedReference) firstObject).getValue (); 974 if (secondObject instanceof UnresolvedReference) 975 secondObject = ((UnresolvedReference) secondObject).getValue (); 976 if (!refAssoc.refLinkExists ((RefObject) firstObject, (RefObject) secondObject)) { 977 refAssoc.refAddLink ((RefObject) firstObject, (RefObject) secondObject); 978 } 979 } } 981 982 984 public void increaseUnresolvedRefs() { 985 counter++; 986 } 987 988 public void decreaseUnresolvedRefs() { 989 counter--; 990 if (endReached && (counter == 0)) 991 createLinks (); 992 } 993 994 } 996 public static class PrimitiveValue extends XmiElement { 1000 1001 private String xmiValue; 1003 private String valueAsText = ""; 1005 private PrimitiveType type; 1007 private boolean xmiAnyValueEndExpected = false; 1009 private boolean stopCharsReading = false; 1011 1012 public PrimitiveValue (XmiElement parent, XmiContext context, 1013 PrimitiveType type, Attributes attrs) { 1014 super (parent, context); 1015 this.type = type; 1016 xmiValue = attrs.getValue (XmiConstants.XMI_VALUE); 1017 } 1018 1019 1025 public PrimitiveValue (XmiContext context) { 1026 super (context); 1027 } 1028 1029 public void init (XmiElement parent, PrimitiveType type, Attributes attrs) { 1030 this.parent = parent; 1031 this.type = type; 1032 xmiValue = attrs.getValue (XmiConstants.XMI_VALUE); 1033 valueAsText = ""; 1034 xmiAnyValueEndExpected = false; 1035 stopCharsReading = false; 1036 } 1037 1038 public void characters (char buf[], int offset, int len) { 1039 if (!stopCharsReading) 1040 valueAsText = valueAsText + new String (buf, offset, len); 1041 } 1042 1043 public XmiElement startSubElement (String qName, Attributes attrs) { 1044 if (!qName.equals (XmiConstants.XMI_ANY_TYPE)) 1048 throw new DebugException ("Unexpected element: " + qName); 1049 xmiAnyValueEndExpected = true; 1050 valueAsText = ""; 1051 return this; 1052 } 1053 1054 public XmiElement endElement (String qName) { 1055 if (xmiAnyValueEndExpected) { 1056 stopCharsReading = true; 1057 xmiAnyValueEndExpected = false; 1058 return this; 1059 } 1060 if (xmiValue != null) 1064 valueAsText = xmiValue; 1065 parent.receiveValue 1067 (XmiContext.resolvePrimitiveValue ((PrimitiveType) type, valueAsText)); 1068 return parent; 1069 } 1070 1071 } 1073 public static class EnumerationValue extends XmiElement { 1077 1078 public EnumerationValue (XmiElement parent, XmiContext context, 1079 EnumerationType type, Attributes attributes) { 1080 super (parent, context); 1081 init (parent, type, attributes); 1082 } 1083 1084 1090 public EnumerationValue (XmiContext context) { 1091 super (context); 1092 } 1093 1094 public void init (XmiElement parent, EnumerationType type, 1095 Attributes attrs) { 1096 this.parent = parent; 1097 String enumValue = attrs.getValue (XmiConstants.XMI_VALUE); 1098 if (enumValue == null) 1099 throw new DebugException ("xmi.value attribute expected in Enum element"); 1100 parent.receiveValue 1101 (context.resolveEnumerationValue (type, enumValue)); 1102 } 1103 1104 } 1106 public static class StructureValue extends XmiElement 1110 implements ReferencesCounter { 1111 1112 private StructureType type; 1114 private List fields; 1116 1119 private Iterator fieldsIterator; 1120 private StructureField currentField; 1122 private HashMap fieldsValues = new HashMap (); 1124 private boolean oldFormat; 1126 1127 private int counter = 0; 1129 private boolean endReached = false; 1131 private UnresolvedReference unresRef = null; 1133 1134 public StructureValue (XmiElement parent, XmiContext context, 1135 StructureType type, Attributes attrs, boolean oldFormat) { 1136 super (parent, context); 1137 this.type = type; 1138 this.oldFormat = oldFormat; 1139 1140 int attrsLength = attrs.getLength (); 1141 fields = context.structureFields (type); 1142 1143 if (oldFormat) 1144 fieldsIterator = fields.iterator (); 1145 else { 1146 boolean isMultiplicityType = 1147 XmiContext.getQualifiedName (type).equals ("Model.MultiplicityType"); 1148 String fieldName, fieldValue; 1149 for (int index = 0; index < attrsLength; index++) { 1150 fieldName = attrs.getQName (index); 1151 if (isMultiplicityType) { 1153 if (fieldName.equals ("is_ordered")) 1154 fieldName = "isOrdered"; 1155 else if (fieldName.equals ("is_unique")) 1156 fieldName = "isUnique"; 1157 } 1158 fieldValue = attrs.getValue (index); 1160 resolveFieldValue (fieldName, fieldValue); 1161 } } } 1164 1165 public XmiElement startSubElement (String qName, Attributes attrs) { 1166 if (oldFormat) { 1167 if (!fieldsIterator.hasNext ()) { 1169 finishElement (); 1170 return parent.startSubElement (qName, attrs); 1171 } 1172 currentField = (StructureField) fieldsIterator.next (); 1173 } else { 1174 currentField = (StructureField) context.resolveElementName (qName); 1175 } 1176 1177 Classifier type = currentField.getType (); 1178 return context.resolveValue (this, type, attrs); 1179 } 1180 1181 public void receiveValue (Object value) { 1182 if (value instanceof List) { 1183 if (((List) value).size () != 1) 1184 throw new DebugException ("Multi-valued structure field: " + currentField.getName ()); 1185 value = ((List) value).get (0); 1186 } 1187 if (value instanceof UnresolvedReference) 1188 ((UnresolvedReference) value).setOwner (this); 1189 setFieldValue (currentField, value); 1190 } 1191 1192 private void setFieldValue (TypedElement field, Object value) { 1193 if (fieldsValues.get (field) != null) 1194 throw new DebugException ("Multi-valued structure field: " + field.getName ()); 1195 fieldsValues.put (field, value); 1196 } 1197 1198 private void resolveFieldValue (String fieldName, String fieldValue) { 1199 StructureField field; 1200 try { 1201 field = (StructureField) type.lookupElement (fieldName); 1202 } catch (NameNotFoundException e) { 1203 throw new DebugException ("Field name cannot be resolved: " + type.getName () + "." + fieldName); 1204 } 1205 1206 Classifier type = field.getType (); 1207 while (type instanceof AliasType) 1208 type = ((AliasType) type).getType (); 1209 Object value = null; 1210 1211 if (type instanceof PrimitiveType) { 1212 value = XmiContext.resolvePrimitiveValue ((PrimitiveType) type, fieldValue); 1213 } else if (type instanceof EnumerationType) { 1214 value = context.resolveEnumerationValue ((EnumerationType) type, fieldValue); 1215 } else if (type instanceof MofClass) { 1216 String xmiId = fieldValue.trim (); 1217 Object obj = context.getReference (xmiId); 1218 if (obj == null) { 1219 obj = new UnresolvedReference (this); 1221 context.registerUnresolvedRef (xmiId, (UnresolvedReference) obj); 1222 value = obj; 1223 } 1224 } else { 1225 throw new DebugException ("Field cannot be resolved, invalid type: " + type.getName ()); 1226 } 1227 setFieldValue (field, value); 1228 } 1229 1230 private RefStruct createInstance () { 1231 List args = new LinkedList (); 1233 Iterator iter = fields.iterator (); 1234 while (iter.hasNext ()) { 1235 StructureField field = (StructureField) iter.next (); 1236 Object param = fieldsValues.get (field); 1237 if (param instanceof UnresolvedReference) { 1238 param = ((UnresolvedReference) param).getValue (); 1239 } 1240 if (param instanceof CollectionWrapper) { 1241 param = ((CollectionWrapper) param).getCollection (); 1242 } 1243 if (param == null) 1244 param = XmiContext.defaultValue (field.getType ()); 1245 args.add (param); 1246 } 1248 RefStruct struct = null; 1249 RefBaseObject proxy = context.findProxy (type); 1250 if (proxy == null) 1251 throw new DebugException ("Proxy not found: " + type.getName ()); 1252 if (proxy instanceof RefClass) 1253 struct = ((RefClass) proxy).refCreateStruct (type, args); 1254 else 1255 struct = ((RefPackage) proxy).refCreateStruct (type, args); 1256 return struct; 1257 } 1258 1259 private void finishElement () { 1260 endReached = true; 1261 if (counter == 0) { 1262 RefStruct instance = createInstance (); 1263 if (!(parent instanceof XmiElement.Content)) { 1264 parent.receiveValue (instance); 1265 } 1266 } else { 1267 if (!(parent instanceof XmiElement.Content)) { 1268 unresRef = new UnresolvedReference (); 1269 parent.receiveValue (unresRef); 1270 } 1271 } 1272 } 1273 1274 public XmiElement endElement (String qName) { 1275 if (oldFormat) { 1276 if (fieldsIterator.hasNext ()) 1277 throw new DebugException ("Structure value serialization not complete: " + type.getName ()); 1278 finishElement (); 1279 return parent.endElement (qName); 1281 } else { 1282 finishElement (); 1283 return parent; 1284 } 1285 } 1286 1287 1289 public void increaseUnresolvedRefs () { 1290 counter++; 1291 } 1292 1293 public void decreaseUnresolvedRefs () { 1294 counter--; 1295 if (endReached && (counter == 0)) { 1296 RefStruct instance = createInstance (); 1297 if (unresRef != null) 1298 unresRef.referenceResolved (instance); 1299 } 1300 } 1301 1302 } 1304 public static class CollectionValues extends XmiElement { 1308 1309 private List values = new LinkedList (); 1311 private CollectionType type; 1313 1314 public CollectionValues (XmiElement parent, XmiContext context, CollectionType type) { 1315 super (parent, context); 1316 this.type = type; 1317 } 1318 1319 public XmiElement startSubElement (String qName, Attributes attrs) { 1320 return new CollectionValue (this, context, type); 1321 } 1322 1323 public void receiveValue (Object value) { 1324 values.add (value); 1325 } 1326 1327 public XmiElement endElement (String qName) { 1328 parent.receiveValue (values); 1329 return parent; 1330 } 1331 1332 } 1334 public static class CollectionValue extends XmiElement implements ReferencesCounter { 1338 1339 private Classifier type; 1340 private List values = new LinkedList (); 1341 private String collName; 1342 1343 private int counter = 0; 1344 private boolean endReached = false; 1345 private UnresolvedReference unresRef = null; 1346 1347 public CollectionValue (XmiElement parent, XmiContext context, CollectionType collType) { 1348 super (parent, context); 1349 type = collType.getType (); 1350 collName = collType.getName (); 1351 } 1352 1353 public XmiElement startSubElement (String qName, Attributes attrs) { 1354 if (type instanceof MofClass) { 1355 return context.resolveInstanceOrReference (this, qName, attrs); 1356 } 1357 if (type instanceof CollectionType) { 1358 return new XmiElement.CollectionValue (this, context, (CollectionType) type); 1359 } 1360 return context.resolveValue (this, type, attrs); 1361 } 1362 1363 public void receiveValue (Object value) { 1364 if (value instanceof List) { 1365 Iterator iter = ((List) value).iterator (); 1366 while (iter.hasNext ()) { 1367 Object obj = iter.next (); 1368 if (obj instanceof UnresolvedReference) 1369 ((UnresolvedReference) obj).setOwner (this); 1370 values.add (obj); 1371 } 1372 } else { 1373 if (value instanceof UnresolvedReference) 1374 ((UnresolvedReference) value).setOwner (this); 1375 values.add (value); 1376 } 1377 } 1378 1379 public XmiElement endElement (String qName) { 1380 finishElement (); 1381 return parent; 1382 } 1383 1384 private void finishElement () { 1385 endReached = true; 1386 if (counter == 0) { 1387 CollectionWrapper val = createValue (); 1388 if (!(parent instanceof XmiElement.Content)) { 1389 parent.receiveValue (val); 1390 } 1391 } else { 1392 if (!(parent instanceof XmiElement.Content)) { 1393 unresRef = new UnresolvedReference (); 1394 parent.receiveValue (unresRef); 1395 } 1396 } 1397 } 1398 1399 public CollectionWrapper createValue () { 1400 List list = new LinkedList (); 1401 Iterator iter = values.iterator (); 1402 while (iter.hasNext ()) { 1403 Object obj = iter.next (); 1404 if (obj instanceof UnresolvedReference) { 1405 obj = ((UnresolvedReference) obj).getValue (); 1406 } 1407 if (obj instanceof CollectionWrapper) { 1408 obj = ((CollectionWrapper) obj).getCollection (); 1409 } 1410 list.add (obj); 1411 } 1412 return new CollectionWrapper (list); 1413 } 1414 1415 1417 public void increaseUnresolvedRefs () { 1418 counter++; 1419 } 1420 1421 public void decreaseUnresolvedRefs () { 1422 counter--; 1423 if (endReached && (counter == 0)) { 1424 CollectionWrapper value = createValue (); 1425 if (unresRef != null) 1426 unresRef.referenceResolved (value); 1427 } 1428 } 1429 1430 } 1432 public static class ObjectValues extends XmiElement { 1436 1441 1442 private List values = new LinkedList (); 1444 private ReferencesCounter target; 1446 private boolean isNull; 1448 1449 1459 public ObjectValues (XmiElement parent, XmiContext context, ReferencesCounter target, boolean isNull) { 1460 super (parent, context); 1461 this.target = target; 1462 this.isNull = isNull; 1463 } 1464 1465 public XmiElement startSubElement (String qName, Attributes attrs) { 1466 return context.resolveInstanceOrReference (this, qName, attrs); 1467 } 1468 1469 public void receiveValue (Object value) { 1470 values.add (value); 1471 if ((value instanceof UnresolvedReference) && (target != null)) 1472 ((UnresolvedReference) value).setOwner (target); 1473 } 1474 1475 public XmiElement endElement (String qName) { 1476 parent.receiveValue (isNull ? null : values); 1477 return parent; 1478 } 1479 1480 } 1482 public static class StructureValues extends XmiElement { 1486 1489 1490 private List values = new LinkedList (); 1492 private StructureType type; 1494 private boolean oldFormat = false; 1496 1497 public StructureValues (XmiElement parent, XmiContext context, StructureType type) { 1498 super (parent, context); 1499 this.type = type; 1500 } 1501 1502 public XmiElement startSubElement (String qName, Attributes attrs) { 1503 if (qName.equals (XmiConstants.XMI_FIELD)) 1504 oldFormat = true; 1505 StructureValue struct = new StructureValue (this, context, type, attrs, oldFormat); 1506 if (oldFormat) { 1507 1513 return struct.startSubElement (qName, attrs); 1514 } 1515 return struct; 1516 } 1517 1518 public void receiveValue (Object value) { 1519 values.add (value); 1520 } 1521 1522 public XmiElement endElement (String qName) { 1523 parent.receiveValue (values); 1524 return parent; 1525 } 1526 1527 } 1529 public static class ReferenceValue extends XmiElement { 1533 1536 1537 public ReferenceValue (XmiElement parent, XmiContext context, String xmiId) { 1538 super (parent, context); 1539 init (parent, xmiId); 1540 } 1541 1542 1548 public ReferenceValue (XmiContext context) { 1549 super (context); 1550 } 1551 1552 public void init (XmiElement parent, String xmiId) { 1553 this.parent = parent; 1554 Object obj = context.getReference (xmiId); 1555 if (obj == null) { 1556 obj = new UnresolvedReference (); 1557 context.registerUnresolvedRef (xmiId, (UnresolvedReference) obj); 1558 } 1559 parent.receiveValue (obj); 1560 } 1561 1562 public void initExternal (XmiElement parent, String hRef) { 1563 this.parent = parent; 1564 Object obj; 1565 1566 XMIReferenceProvider.XMIReference ref = context.toXMIReference (hRef); 1567 1568 String docId = ref.getSystemId (); 1569 String xmiId = ref.getXmiId (); 1570 obj = context.getReference (docId, xmiId); 1571 if (obj == null) { 1572 obj = new UnresolvedReference (); 1573 context.registerUnresolvedExternalRef (docId, xmiId, (UnresolvedReference) obj); 1574 } 1575 parent.receiveValue (obj); 1576 } 1577 1578 } 1580 public static class Dummy extends XmiElement { 1584 1585 private int level = 0; 1586 1587 public Dummy (XmiElement parent, XmiContext context, String qName) { 1588 super (parent, null); 1589 context.unknownElementFound(qName); 1590 } 1591 1592 public XmiElement startSubElement (String qName, Attributes attrs) { 1593 level++; 1594 return this; 1595 } 1596 1597 public XmiElement endElement (String qName) { 1598 if (level == 0) { 1599 return parent; 1600 } else { 1601 level--; 1602 return this; 1603 } 1604 } 1605 1606 } 1607 1608 public static interface ReferencesCounter { 1612 1616 public void increaseUnresolvedRefs (); 1617 1618 1619 public void decreaseUnresolvedRefs (); 1620 1621 } 1622 1623 public static class UnresolvedReference { 1627 1635 1636 private Object value = null; 1638 private ReferencesCounter owner; 1640 1641 1645 public UnresolvedReference () { 1646 } 1647 1648 public UnresolvedReference (ReferencesCounter owner) { 1649 this.owner = owner; 1650 owner.increaseUnresolvedRefs (); 1651 } 1652 1653 public void referenceResolved (Object value) { 1654 this.value = value; 1655 if (owner != null) 1656 owner.decreaseUnresolvedRefs (); 1657 } 1658 1659 public Object getValue () { 1660 return value; 1661 } 1662 1663 public void setOwner (ReferencesCounter owner) { 1664 this.owner = owner; 1665 owner.increaseUnresolvedRefs (); 1666 } 1667 1668 } 1670 public static class ReferenceHandler implements ReferencesCounter { 1674 1679 1680 private RefObject obj; 1682 private Reference ref; 1684 private List values = new LinkedList (); 1686 private int unresolvedRefsCounter = 0; 1688 private XmiContext context; 1690 1691 public ReferenceHandler (Reference ref, RefObject obj, List args, XmiContext context) { 1692 this.obj = obj; 1693 this.ref = ref; 1694 this.context = context; 1695 Iterator iter = args.iterator (); 1696 while (iter.hasNext ()) { 1697 Object value = iter.next (); 1698 if (value instanceof UnresolvedReference) { 1699 Object val = ((UnresolvedReference) value).getValue (); 1700 if (val != null) 1701 value = val; 1702 else 1703 ((UnresolvedReference) value).setOwner (this); 1704 } values.add (value); 1706 } if (unresolvedRefsCounter == 0) { 1708 setReference (); 1709 } 1710 } 1711 1712 public void increaseUnresolvedRefs () { 1713 unresolvedRefsCounter++; 1714 } 1715 1716 public void decreaseUnresolvedRefs () { 1717 unresolvedRefsCounter--; 1718 if (unresolvedRefsCounter == 0) 1719 setReference (); 1720 } 1721 1722 private void setReference () { 1723 Iterator iter; 1724 AssociationEnd end = ref.getReferencedEnd (); 1725 boolean isOrdered = end.getMultiplicity ().isOrdered (); 1726 Association association = (Association) end.getContainer (); 1727 1728 1734 1735 boolean isFirst = false; 1736 for (iter = association.getContents ().iterator (); iter.hasNext ();) { 1737 ModelElement me = (ModelElement) iter.next (); 1738 if (me instanceof AssociationEnd) { 1739 isFirst = me.equals (end); 1740 break; 1741 } 1742 } 1743 1744 RefPackage refPackage = (RefPackage) context.findProxy (association); 1745 if (refPackage == null) 1746 throw new DebugException ("Proxy not found: " + association.getName ()); 1747 RefAssociation refAssoc = refPackage.refAssociation (association); 1748 if (refAssoc == null) 1749 throw new DebugException ("Proxy not found: " + association.getName ()); 1750 iter = values.iterator (); 1751 while (iter.hasNext ()) { 1752 Object value = iter.next (); 1753 RefObject endValue; 1754 if (value instanceof UnresolvedReference) 1755 endValue = (RefObject) ((UnresolvedReference) value).getValue (); 1756 else 1757 endValue = (RefObject) value; 1758 RefObject firstObj = isFirst ? endValue : obj; 1759 RefObject secondObj = isFirst ? obj : endValue; 1760 if ((firstObj != null) && (secondObj != null)) { 1761 if (!refAssoc.refLinkExists (firstObj, secondObj)) { 1762 refAssoc.refAddLink (firstObj, secondObj); 1763 1764 1768 1769 } else if (isOrdered) { 1770 refAssoc.refRemoveLink (firstObj, secondObj); 1771 refAssoc.refAddLink (firstObj, secondObj); 1772 1773 1777 1778 } else { 1779 1783 1784 } 1785 1786 } 1787 } 1789 1800 1801 } 1802 1803 } 1805 public static class CollectionWrapper { 1809 1810 private Collection coll; 1811 1812 public CollectionWrapper (Collection coll) { 1813 this.coll = coll; 1814 } 1815 1816 public Collection getCollection () { 1817 return coll; 1818 } 1819 1820 } 1822} 1823 | Popular Tags |