1 19 package org.netbeans.lib.jmi.xmi; 20 21 import java.io.*; 22 import java.util.*; 23 24 import org.xml.sax.*; 25 import org.xml.sax.helpers.AttributesImpl ; 26 import org.xml.sax.helpers.DefaultHandler ; 27 import javax.xml.parsers.SAXParserFactory ; 28 import javax.xml.parsers.ParserConfigurationException ; 29 import javax.xml.parsers.SAXParser ; 30 31 import javax.jmi.reflect.*; 32 import javax.jmi.model.*; 33 34 import org.netbeans.lib.jmi.util.DebugException; 35 import org.netbeans.lib.jmi.util.Logger; 36 import org.netbeans.lib.jmi.util.TagProvider; 37 38 public class SchemaProducer { 39 40 private static String FIXED_SCHEMA_FILE = "resources/fixed_schema.xml"; 42 43 private OutputStreamWriter streamWriter; 45 private DefaultWriter writer; 47 private TagProvider tagProvider; 49 private RefPackage extent; 51 private ElementsCache elementsCache; 53 private Set trackedPackages; 55 private Map classHierarchy; 57 private Map allSubtypes_cache; 59 private Map namespaces; 61 private HashMap nsPrefixToURI; 63 private Set enumerations; 65 66 private boolean elementStarted; 68 private String elementName; 69 private AttributesImpl attributes = new AttributesImpl (); 70 71 75 private void startElement (String name) { 76 if (elementStarted) { 77 writeStartElement (); 78 } 79 elementName = name; 80 elementStarted = true; 81 } 82 83 private void endElement (String name) { 84 if (elementStarted) { 85 writeStartElement (); 86 } 87 try { 88 writer.endElement (null, null, name); 89 } catch (SAXException e) { 90 throw new DebugException (e.getMessage ()); 91 } 92 } 93 94 private void addAttribute (String name, String value) { 95 attributes.addAttribute(null, null, name, null, value); } 97 98 private void characters (String text) { 99 if (elementStarted) { 100 writeStartElement (); 101 } 102 try { 103 writer.characters (text.toCharArray(), 0, text.length ()); 104 } catch (SAXException e) { 105 throw new DebugException (e.getMessage ()); 106 } 107 } 108 109 private void writeStartElement () { 110 try { 111 writer.startElement (null, null, elementName, attributes); 112 } catch (SAXException e) { 113 throw new DebugException (e.getMessage ()); 114 } 115 elementStarted = false; 116 attributes.clear (); 117 } 118 119 121 123 124 public void init () { 125 writer = new DefaultWriter (streamWriter, null); 126 elementStarted = false; 127 elementName = null; 128 attributes.clear (); 129 130 enumerations = new HashSet (); 131 tagProvider = new TagProvider (); 132 elementsCache = new ElementsCache (extent); 133 trackedPackages = new HashSet (); 134 classHierarchy = new HashMap (); 135 allSubtypes_cache = new HashMap (); 136 namespaces = new HashMap (); 137 nsPrefixToURI = new HashMap (); 138 139 findNamespaces (extent); 140 trackedPackages.clear (); 141 } 142 143 145 149 public void generate (OutputStream stream, RefPackage extent) throws IOException { 150 streamWriter = new OutputStreamWriter (stream); 151 this.extent = extent; 152 init (); 153 154 try { 155 writer.startDocument (); 156 157 startElement ("xsd:schema"); 158 addAttribute ("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); 159 addAttribute ("xmlns:xmi", "http://www.omg.org/XMI"); 160 161 startElement ("xsd:import"); 164 addAttribute ("namespace", "http://www.omg.org/XMI"); 165 endElement ("xsd:import"); 166 167 169 writePackageSchema (extent); 170 for (Iterator iter = enumerations.iterator (); iter.hasNext ();) { 171 writeEnumerationSchema ((EnumerationType) iter.next ()); 172 } 173 174 endElement ("xsd:schema"); 175 176 try { 177 writer.endDocument (); 178 } catch (SAXException e) { 179 throw new IOException (e.getMessage ()); 180 } 181 182 stream.flush (); 183 stream.close (); 184 } catch (SAXException e) { 185 e.printStackTrace (); 186 throw new IOException (e.getMessage ()); 187 } 188 } 189 190 public void writePackageSchema (RefPackage pkg) { 191 if (trackedPackages.contains (pkg)) { 192 return; 193 } else { 194 trackedPackages.add (pkg); 195 } 196 Iterator iter = pkg.refAllPackages ().iterator (); 197 while (iter.hasNext ()) { 198 writePackageSchema ((RefPackage) iter.next ()); 199 } 200 iter = pkg.refAllClasses ().iterator (); 201 while (iter.hasNext ()) { 202 writeClassSchema ((RefClass) iter.next ()); 203 } 204 writePackageElementDef (pkg); 205 } 206 207 public void writeClassSchema (RefClass proxy) { 208 Iterator iter; 209 String text; 210 StringBuffer buffer = new StringBuffer (); 211 MofClass meta = (MofClass) proxy.refMetaObject (); 212 String className = objectName (meta); 213 List instAttrs, references; 214 215 String contentType = getContentType (meta); 216 boolean useExtensions = isUseSchemaExtensions (meta); 217 boolean isChoice = isMaxMultiplicityEnforced (meta) || isMinMultiplicityEnforced (meta); 218 219 findEnumerations (meta); 220 221 startElement ("xsd:complexType"); 223 addAttribute ("name", meta.getName ()); 224 if ((contentType != null) && contentType.equals ("mixed")) { 225 addAttribute ("mixed", "true"); 226 } 227 228 if (useExtensions) { 229 startElement ("xsd:complexContent"); 230 startElement ("xsd:extension"); 231 Collection supers = meta.getSupertypes (); 232 if (supers.size () != 1) { 233 } 235 String base = objectName ((MofClass) supers.iterator ().next ()); 236 addAttribute ("base", base); 237 } 238 239 if (isChoice) { 240 startElement ("xsd:choice"); 241 addAttribute ("minOccurs", "0"); 242 addAttribute ("maxOccurs", "unbounded"); 243 } else { 244 startElement ("xsd:sequence"); 245 } 246 247 if (contentType == null) { 248 instAttrs = useExtensions ? elementsCache.localInstanceAttributes (meta) : 250 elementsCache.instanceAttributes (meta); 251 for (iter = instAttrs.iterator (); iter.hasNext ();) { 252 Attribute attr = (Attribute) iter.next (); 253 startElement ("xsd:element"); 254 addAttribute ("name", attr.getName ()); 255 if (isNillable (attr)) { 256 addAttribute ("nillable", "true"); 257 } 258 if (isMinMultiplicityEnforced (attr)) { 259 addAttribute ("minOccurs", multToString (attr.getMultiplicity ().getLower ())); 260 } 261 if (isMaxMultiplicityEnforced (attr)) { 262 addAttribute ("maxOccurs", multToString (attr.getMultiplicity ().getUpper ())); 263 } 264 Classifier type = getType (attr); 265 if (type instanceof MofClass) { 266 String schemaType = getSchemaType (attr); 267 if (schemaType != null) { 268 addAttribute ("type", schemaType); 269 } else { 270 writeAnyElement (); 271 } 272 } else if (type instanceof EnumerationType) { 273 addAttribute ("type", type.getName ()); 274 } else { 275 addAttribute ("type", "xsd:string"); 276 } 277 endElement ("xsd:element"); 278 } references = useExtensions ? elementsCache.localReferences (meta) : 281 elementsCache.references (meta); 282 for (iter = references.iterator (); iter.hasNext ();) { 283 Reference reference = (Reference) iter.next (); 284 startElement ("xsd:element"); 285 addAttribute ("name", reference.getName ()); 286 if (isMinMultiplicityEnforced (reference)) { 287 addAttribute ("minOccurs", multToString (reference.getMultiplicity ().getLower ())); 288 } 289 if (isMaxMultiplicityEnforced (reference)) { 290 addAttribute ("maxOccurs", multToString (reference.getMultiplicity ().getUpper ())); 291 } 292 String contType = getContentType (reference); 293 if (((contType != null) && (contType.equals ("complex"))) || isUseSchemaExtensions (reference)) { 294 addAttribute ("type", getType (reference).getName ()); 295 } else { 296 writeAnyElement (); 297 } 298 endElement ("xsd:element"); 299 } startElement ("xsd:element"); 302 addAttribute ("ref", "xmi:extension"); 303 endElement ("xsd:element"); 304 305 } else if (contentType.equals ("any")) { 306 startElement ("xsd:any"); 307 addAttribute ("minOccurs", "0"); 308 addAttribute ("maxOccurs", "unbounded"); 309 addAttribute ("processContents", getProcessContents (meta)); 310 endElement ("xsd:any"); 311 } 313 endElement (isChoice ? "xsd:choice" : "xsd:sequence"); 314 315 writeFixedAttribs (meta); 318 references = useExtensions ? elementsCache.localReferences (meta) : 320 elementsCache.references (meta); 321 for (iter = references.iterator (); iter.hasNext ();) { 322 Reference reference = (Reference) iter.next (); 323 if (AggregationKindEnum.COMPOSITE.equals (reference.getReferencedEnd ().getAggregation ())) 324 continue; 325 startElement ("xsd:attribute"); 326 addAttribute ("name", reference.getName ()); 327 MultiplicityType mult = reference.getMultiplicity (); 328 if ((mult.getLower () == 1) && (mult.getUpper () == 1) && isMinMultiplicityEnforced (reference)) { 329 addAttribute ("type", "xsd:IDREFS"); 330 addAttribute ("use", "optional"); 331 } else { 332 addAttribute ("type", "xsd:IDREF"); 333 addAttribute ("use", "required"); 334 } 335 endElement ("xsd:attribute"); 336 } instAttrs = useExtensions ? elementsCache.localInstanceAttributes (meta) : 339 elementsCache.instanceAttributes (meta); 340 for (iter = instAttrs.iterator (); iter.hasNext ();) { 341 Attribute attr = (Attribute) iter.next (); 342 String val; 343 Classifier type = getType (attr); 344 if (type instanceof MofClass) { 345 continue; 346 } 347 MultiplicityType mult = attr.getMultiplicity (); 348 boolean required = (mult.getLower () == 1) && (mult.getUpper () == 1) && isMinMultiplicityEnforced (attr); 349 startElement ("xsd:attribute"); 350 addAttribute ("name", attr.getName ()); 351 if (type instanceof EnumerationType) { 352 addAttribute ("type", objectName (type)); 353 val = getDefaultValue (attr); 354 if (val != null) { 355 addAttribute ("use", "default"); 356 addAttribute ("value", val); 357 } else { 358 addAttribute ("use", required ? "required" : "optional"); 359 } 360 } else { 361 addAttribute ("type", "xsd:string"); 362 addAttribute ("use", required ? "required" : "optional"); 363 val = getDefaultValue (attr); 364 if (val != null) 365 addAttribute ("default", val); 366 val = getFixedValue (attr); 367 if (val != null) 368 addAttribute ("fixed", val); 369 val = getForm (attr); 370 if (val != null) 371 addAttribute ("form", val); 372 } 373 endElement ("xsd:attribute"); 374 } 376 if (useExtensions) { 377 endElement ("xsd:extension"); 378 endElement ("xsd:complexContent"); 379 } 380 endElement ("xsd:complexType"); 381 startElement ("xsd:attributeGroup"); 382 addAttribute ("ref", "xmi:ObjectAttribs"); 383 endElement ("xsd:attributeGroup"); 384 385 startElement ("xsd:element"); 387 addAttribute ("name", meta.getName ()); 388 addAttribute ("type", objectName (meta)); 389 endElement ("xsd:element"); 390 } 391 392 public void writeAnyElement () { 393 startElement ("xsd:complexType"); 394 startElement ("xsd:choice"); 395 addAttribute ("minOccurs", "0"); 396 addAttribute ("maxOccurs", "unbounded"); 397 startElement ("xsd:any"); 398 addAttribute ("processContents", "skip"); 399 endElement ("xsd:any"); 400 endElement ("xsd:choice"); 401 endElement ("xsd:complexType"); 402 } 403 404 public void writeFixedAttribs (ModelElement elem) { 405 startElement ("xsd:attribute"); 406 String idName = getIdName (elem); 407 if (idName == null) { 408 addAttribute ("ref", "xmi:id"); 409 } else { 410 addAttribute ("name", idName); 411 addAttribute ("type", "xsd:ID"); 412 } 413 addAttribute ("use", "optional"); 414 endElement ("xsd:attribute"); 415 } 416 417 public void writeAssociationSchema (Association assoc) { 418 startElement ("xsd:element"); 419 addAttribute ("name", assoc.getName ()); 420 startElement ("xsd:complexType"); 421 startElement ("xsd:choice"); 422 addAttribute ("minOccurs", "0"); 423 addAttribute ("maxOccurs", "unbounded"); 424 for (Iterator iter = assoc.getContents ().iterator (); iter.hasNext ();) { 425 Object elem = iter.next (); 426 if (elem instanceof AssociationEnd) { 427 writeAssociationEndDef ((AssociationEnd) elem); 428 } } startElement ("xsd:extension"); 432 addAttribute ("ref", "xmi:extension"); 433 endElement ("xsd:extension"); 434 endElement ("xsd:choice"); 436 writeFixedAttribs (assoc); 437 endElement ("xsd:complexType"); 438 endElement ("xsd:element"); 439 } 440 441 public void writeAssociationEndDef (AssociationEnd end) { 442 startElement ("xsd:element"); 443 addAttribute ("name", end.getName ()); 444 startElement ("xsd:complexType"); 445 writeFixedAttribs (end); 446 endElement ("xsd:complexType"); 447 endElement ("xsd:element"); 448 } 449 450 public void writeEnumerationSchema(EnumerationType en) { 451 startElement ("xsd:simpleType"); 452 addAttribute ("name", en.getName ()); 453 startElement ("xsd:restriction"); 454 addAttribute ("base", "xsd:string"); 455 for (Iterator iter = en.getLabels ().iterator (); iter.hasNext ();) { 457 String label = (String ) iter.next (); 458 startElement ("xsd:enumeration"); 459 addAttribute ("value", label); 460 endElement ("xsd:enumeration"); 461 } 462 endElement ("xsd:restriction"); 463 endElement ("xsd:simpleType"); 464 } 465 466 public void writeFixedContent () throws SAXException { 467 java.net.URL fixedSchema = getClass().getResource(FIXED_SCHEMA_FILE); 468 if (fixedSchema == null) { 469 throw new DebugException("Resource not found: " + FIXED_SCHEMA_FILE); 470 } 471 try { 472 SAXParserFactory factory = SAXParserFactory.newInstance (); 473 factory.setValidating (false); 474 SAXParser saxParser = factory.newSAXParser (); 475 saxParser.parse (fixedSchema.openStream (), new FixedContentHandler ()); 476 } catch (IOException e) { 477 Logger.getDefault().log("Unable to open " + FIXED_SCHEMA_FILE + ": " + e.getMessage()); 478 throw new DebugException (e.getMessage ()); 479 } catch (ParserConfigurationException e) { 480 throw new SAXException (e.getMessage ()); 481 } 482 } 483 484 public void writeNamespaces () { 485 499 } 500 501 public void writePackageElementDef (RefPackage pkg) { 502 Iterator iter; 503 MofPackage meta = (MofPackage) pkg.refMetaObject (); 504 String packageName = packageName (meta); 505 506 findEnumerations (meta); 507 508 startElement ("xsd:element"); 509 addAttribute ("name", meta.getName ()); 510 startElement ("xsd:complexType"); 511 startElement ("xsd:choice"); 512 addAttribute ("minOccurs", "0"); 513 addAttribute ("maxOccurs", "unbounded"); 514 for (iter = pkg.refAllClasses ().iterator (); iter.hasNext ();) { 517 Object metaObject = ((RefClass) iter.next ()).refMetaObject (); 518 MofClass mofClass = (MofClass) (metaObject instanceof AliasType ? 519 getType ((AliasType) metaObject) : metaObject); 520 521 startElement ("xsd:element"); 522 addAttribute ("name", objectName (mofClass)); 523 addAttribute ("type", mofClass.getName ()); 524 endElement ("xsd:element"); 525 } for (iter = getFreeAssociations (pkg).iterator (); iter.hasNext ();) { 528 writeAssociationSchema ((Association) iter.next ()); 529 } for (iter = pkg.refAllPackages ().iterator (); iter.hasNext ();) { 531 startElement ("xsd:element"); 532 addAttribute ("ref", packageName ((MofPackage) ((RefPackage) iter.next ()).refMetaObject ())); 533 endElement ("xsd:element"); 534 } startElement ("xsd:extension"); 536 addAttribute ("ref", "xmi:extension"); 537 endElement ("xsd:extension"); 538 endElement ("xsd:choice"); 540 endElement ("xsd:complexType"); 541 endElement ("xsd:element"); 542 } 543 544 546 protected void findNamespaces(RefPackage pkg) { 547 String name, uri; 548 Iterator iter; 549 550 if (trackedPackages.contains (pkg)) 551 return; 552 553 MofPackage metaPackage = (MofPackage) pkg.refMetaObject (); 554 555 name = getNsPrefixTag (metaPackage); 556 if (name == null) { 557 name = tagProvider.getTagValue (metaPackage, XmiConstants.TAGID_XMI_NAMESPACE); 558 } 559 560 if (name != null) { 561 iter = metaPackage.getQualifiedName ().iterator (); 562 String fqName = (String ) iter.next (); 563 while (iter.hasNext ()) 564 fqName = fqName.concat (XmiConstants.DOT_SEPARATOR).concat ((String ) iter.next ()); 565 namespaces.put (fqName, name); 566 uri = getNsURITag (metaPackage); 567 if (uri == null) 568 throw new DebugException ("A tag defining namespace uri not found, package " + metaPackage.getName ()); 569 nsPrefixToURI.put (name, uri); 570 } 571 572 trackedPackages.add (pkg); 573 iter = pkg.refAllPackages ().iterator (); 574 while (iter.hasNext ()) { 575 findNamespaces ((RefPackage) iter.next ()); 576 } 577 } 578 579 public String elementName (ModelElement element) { 580 ModelElement container = element.getContainer (); 581 return objectName (container) + '.' + getXmiName (element); 582 } 583 584 public String objectName (ModelElement element) { 585 String namespace = (String ) namespaces.get (element.getContainer ()); 586 if (namespace != null) { 587 return namespace + ":" + getXmiName (element); 588 } else { 589 return qualifiedName (element); 590 } 591 } 592 593 public String packageName (MofPackage pkg) { 594 String namespace = (String ) namespaces.get (pkg); 595 if (namespace != null) { 596 return namespace + ":" + getXmiName (pkg); 597 } else { 598 return qualifiedName (pkg); 599 } 600 } 601 602 public String qualifiedName (ModelElement element) { 603 Iterator iter = element.getQualifiedName ().iterator (); 604 String name = (String ) iter.next (); 605 while (iter.hasNext ()) { 606 name = name.concat (XmiConstants.DOT_SEPARATOR).concat ((String ) iter.next ()); 607 } 608 return name; 609 } 610 611 public Classifier getType (TypedElement elem) { 612 Classifier type = elem.getType (); 613 while (type instanceof AliasType) 614 type = ((AliasType) type).getType (); 615 return type; 616 } 617 618 public Set getFreeAssociations (RefPackage pkg) { 619 ModelPackage model = (ModelPackage) pkg.refMetaObject ().refImmediatePackage (); 620 RefersTo refersTo = model.getRefersTo (); 621 Set set = new HashSet (); 622 for (Iterator iter = pkg.refAllAssociations ().iterator (); iter.hasNext ();) { 623 Association assoc = (Association) ((RefAssociation) iter.next ()).refMetaObject (); 624 boolean found = false; 625 for (Iterator it = assoc.getContents ().iterator (); it.hasNext ();) { 626 Object elem = it.next (); 627 if (elem instanceof AssociationEnd) { 628 Collection col = refersTo.getReferent ((AssociationEnd) elem); 629 if ((col != null) && (col.size () > 0)) { 630 found = true; 631 break; 632 } 633 } 634 } if (!found) { 636 set.add (assoc); 637 } 638 } return set; 640 } 641 642 public String multToString (int multiplicity) { 643 return (multiplicity == -1) ? "unbounded" : "" + multiplicity; 644 } 645 646 public void findEnumerations (Namespace elem) { 647 for (Iterator iter = elem.getContents ().iterator (); iter.hasNext ();) { 648 Object obj = iter.next (); 649 if (obj instanceof EnumerationType) { 650 enumerations.add (obj); 651 } 652 } } 654 655 657 public String getContentScopedTagValue (ModelElement elem, String tagId) { 658 String value = null; 659 while ((value == null) && (elem != null)) { 660 value = tagProvider.getTagValue (elem, tagId); 661 elem = elem.getContainer (); 662 } 663 if (value != null) 664 value = value.trim (); 665 return value; 666 } 667 668 public boolean isMaxMultiplicityEnforced (ModelElement elem) { 669 String s = getContentScopedTagValue (elem, XmiConstants.TAG_ENFORCE_MAX_MULTIPLICITY); 670 return (s != null) && s.equals ("true"); 671 } 672 673 public boolean isMinMultiplicityEnforced (ModelElement elem) { 674 String s = getContentScopedTagValue (elem, XmiConstants.TAG_ENFORCE_MIN_MULTIPLICITY); 675 return (s != null) && s.equals ("true"); 676 } 677 678 public boolean isUseSchemaExtensions (ModelElement elem) { 679 String s = getContentScopedTagValue (elem, XmiConstants.TAG_USE_SCHEMA_EXTENSIONS); 680 return (s != null) && s.equals ("true"); 681 } 682 683 public boolean isNillable (ModelElement elem) { 684 String s = getContentScopedTagValue (elem, XmiConstants.TAG_INCLUDE_NILS); 685 return (s == null) || s.equals ("true"); 686 } 687 688 public String getProcessContents (ModelElement elem) { 689 String s = getContentScopedTagValue (elem, XmiConstants.TAG_PROCESS_CONTENTS); 690 if (s == null) { 691 return "strict"; } 693 return s; 694 } 695 696 public String getIdName (ModelElement elem) { 697 return getContentScopedTagValue (elem, XmiConstants.TAG_ID_NAME); 698 } 699 700 public String getForm (ModelElement elem) { 701 return getContentScopedTagValue (elem, XmiConstants.TAG_FORM); 702 } 703 704 public String getFixedValue (ModelElement elem) { 705 return getContentScopedTagValue (elem, XmiConstants.TAG_FIXED_VALUE); 706 } 707 708 public String getNsPrefixTag (ModelElement elem) { 709 return getContentScopedTagValue (elem, XmiConstants.TAG_NS_PREFIX); 710 } 711 712 public String getNsURITag (ModelElement elem) { 713 return getContentScopedTagValue (elem, XmiConstants.TAG_NS_URI); 714 } 715 716 717 public String getDefaultValue (ModelElement elem) { 718 return tagProvider.getTagValue (elem, XmiConstants.TAG_DEFAULT_VALUE); 719 } 720 721 public String getXmiName (ModelElement elem) { 722 String name = tagProvider.getTagValue (elem, XmiConstants.TAG_XMI_NAME); 723 if (name == null) 724 return elem.getName (); 725 else 726 return name; 727 } 728 729 public String getContentType (ModelElement elem) { 730 return tagProvider.getTagValue (elem, XmiConstants.TAG_CONTENT_TYPE); 731 } 732 733 public String getSchemaType (ModelElement elem) { 734 return tagProvider.getTagValue (elem, XmiConstants.TAG_SCHEMA_TYPE); 735 } 736 737 739 private class FixedContentHandler extends DefaultHandler { 740 741 private int depth = 0; 742 743 public void startElement (String namespaceURI, String sName, String qName, Attributes attrs) 744 throws SAXException { 745 if (depth > 0) 746 writer.startElement (namespaceURI, sName, qName, attrs); 747 depth++; 748 } 750 751 public void endElement (String namespaceURI, String sName, String qName) throws SAXException { 752 depth--; 753 if (depth > 0) 754 writer.endElement (namespaceURI, sName, qName); 755 } 757 758 public void characters (char buf[], int offset, int len) throws SAXException { 759 for (int x = offset; x < offset + len; x++) { 760 if (!Character.isWhitespace(buf[x])) { 761 writer.characters (buf, offset, len); 762 break; 763 } } } 766 767 } 768 769 } 770 771 | Popular Tags |