1 31 32 package org.opencms.xml; 33 34 import org.opencms.file.CmsObject; 35 import org.opencms.main.OpenCms; 36 import org.opencms.util.CmsStringUtil; 37 import org.opencms.xml.content.CmsDefaultXmlContentHandler; 38 import org.opencms.xml.content.I_CmsXmlContentHandler; 39 import org.opencms.xml.types.CmsXmlLocaleValue; 40 import org.opencms.xml.types.CmsXmlNestedContentDefinition; 41 import org.opencms.xml.types.I_CmsXmlContentValue; 42 import org.opencms.xml.types.I_CmsXmlSchemaType; 43 44 import java.io.IOException ; 45 import java.util.ArrayList ; 46 import java.util.Arrays ; 47 import java.util.Collections ; 48 import java.util.HashMap ; 49 import java.util.HashSet ; 50 import java.util.Iterator ; 51 import java.util.List ; 52 import java.util.Locale ; 53 import java.util.Map ; 54 import java.util.Set ; 55 56 import org.dom4j.Attribute; 57 import org.dom4j.Document; 58 import org.dom4j.DocumentHelper; 59 import org.dom4j.Element; 60 import org.dom4j.Namespace; 61 import org.dom4j.QName; 62 import org.xml.sax.EntityResolver ; 63 import org.xml.sax.InputSource ; 64 import org.xml.sax.SAXException ; 65 66 75 public class CmsXmlContentDefinition implements Cloneable { 76 77 80 private final class CmsXmlComplexTypeSequence { 81 82 83 protected boolean m_hasLanguageAttribute; 84 85 86 protected String m_name; 87 88 89 protected List m_sequence; 90 91 98 protected CmsXmlComplexTypeSequence(String name, List sequence, boolean hasLanguageAttribute) { 99 100 m_name = name; 101 m_sequence = sequence; 102 m_hasLanguageAttribute = hasLanguageAttribute; 103 } 104 } 105 106 107 public static final String XSD_ATTRIBUTE_DEFAULT = "default"; 108 109 110 public static final String XSD_ATTRIBUTE_ELEMENT_FORM_DEFAULT = "elementFormDefault"; 111 112 113 public static final String XSD_ATTRIBUTE_MAX_OCCURS = "maxOccurs"; 114 115 116 public static final String XSD_ATTRIBUTE_MIN_OCCURS = "minOccurs"; 117 118 119 public static final String XSD_ATTRIBUTE_NAME = "name"; 120 121 122 public static final String XSD_ATTRIBUTE_SCHEMA_LOCATION = "schemaLocation"; 123 124 125 public static final String XSD_ATTRIBUTE_TYPE = "type"; 126 127 128 public static final String XSD_ATTRIBUTE_USE = "use"; 129 130 131 public static final String XSD_ATTRIBUTE_VALUE_LANGUAGE = "language"; 132 133 134 public static final String XSD_ATTRIBUTE_VALUE_OPTIONAL = "optional"; 135 136 137 public static final String XSD_ATTRIBUTE_VALUE_QUALIFIED = "qualified"; 138 139 140 public static final String XSD_ATTRIBUTE_VALUE_REQUIRED = "required"; 141 142 143 public static final String XSD_ATTRIBUTE_VALUE_UNBOUNDED = "unbounded"; 144 145 146 public static final String XSD_ATTRIBUTE_VALUE_ZERO = "0"; 147 148 149 public static final String XSD_INCLUDE_OPENCMS = CmsXmlEntityResolver.OPENCMS_SCHEME + "opencms-xmlcontent.xsd"; 150 151 152 public static final Namespace XSD_NAMESPACE = Namespace.get("xsd", "http://www.w3.org/2001/XMLSchema"); 153 154 155 public static final QName XSD_NODE_ANNOTATION = QName.get("annotation", XSD_NAMESPACE); 156 157 158 public static final QName XSD_NODE_APPINFO = QName.get("appinfo", XSD_NAMESPACE); 159 160 161 public static final QName XSD_NODE_ATTRIBUTE = QName.get("attribute", XSD_NAMESPACE); 162 163 164 public static final QName XSD_NODE_COMPLEXTYPE = QName.get("complexType", XSD_NAMESPACE); 165 166 167 public static final QName XSD_NODE_ELEMENT = QName.get("element", XSD_NAMESPACE); 168 169 170 public static final QName XSD_NODE_INCLUDE = QName.get("include", XSD_NAMESPACE); 171 172 173 public static final QName XSD_NODE_SCHEMA = QName.get("schema", XSD_NAMESPACE); 174 175 176 public static final QName XSD_NODE_SEQUENCE = QName.get("sequence", XSD_NAMESPACE); 177 178 179 private I_CmsXmlContentHandler m_contentHandler; 180 181 182 private Set m_includes; 183 184 185 private String m_innerName; 186 187 188 private String m_outerName; 189 190 191 private String m_schemaLocation; 192 193 194 private String m_typeName; 195 196 197 private Map m_types; 198 199 200 private List m_typeSequence; 201 202 208 public CmsXmlContentDefinition(String innerName, String schemaLocation) { 209 210 this(innerName + "s", innerName, schemaLocation); 211 } 212 213 220 public CmsXmlContentDefinition(String outerName, String innerName, String schemaLocation) { 221 222 m_outerName = outerName; 223 m_innerName = innerName; 224 setInnerName(innerName); 225 m_typeSequence = new ArrayList (); 226 m_types = new HashMap (); 227 m_includes = new HashSet (); 228 m_schemaLocation = schemaLocation; 229 m_contentHandler = new CmsDefaultXmlContentHandler(); 230 } 231 232 235 protected CmsXmlContentDefinition() { 236 237 } 239 240 252 public static CmsXmlContentDefinition unmarshal(byte[] xmlData, String schemaLocation, EntityResolver resolver) 253 throws CmsXmlException { 254 255 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 256 if (result == null) { 257 result = unmarshalInternal(CmsXmlUtils.unmarshalHelper(xmlData, resolver), schemaLocation, resolver); 259 } 260 return result; 261 } 262 263 273 public static CmsXmlContentDefinition unmarshal(CmsObject cms, String resourcename) throws CmsXmlException { 274 275 CmsXmlEntityResolver resolver = new CmsXmlEntityResolver(cms); 276 String schemaLocation = CmsXmlEntityResolver.OPENCMS_SCHEME.concat(resourcename.substring(1)); 277 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 278 if (result == null) { 279 InputSource source = resolver.resolveEntity(null, schemaLocation); 281 result = unmarshalInternal(CmsXmlUtils.unmarshalHelper(source, resolver), schemaLocation, resolver); 282 } 283 return result; 284 } 285 286 299 public static CmsXmlContentDefinition unmarshal(Document document, String schemaLocation) throws CmsXmlException { 300 301 EntityResolver resolver = document.getEntityResolver(); 302 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 303 if (result == null) { 304 result = unmarshalInternal(document, schemaLocation, resolver); 306 } 307 return result; 308 } 309 310 321 public static CmsXmlContentDefinition unmarshal(InputSource source, String schemaLocation, EntityResolver resolver) 322 throws CmsXmlException { 323 324 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 325 if (result == null) { 326 result = unmarshalInternal(CmsXmlUtils.unmarshalHelper(source, resolver), schemaLocation, resolver); 328 } 329 return result; 330 } 331 332 347 public static CmsXmlContentDefinition unmarshal(String schemaLocation, EntityResolver resolver) 348 throws CmsXmlException, SAXException , IOException { 349 350 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 351 if (result == null) { 352 InputSource source = resolver.resolveEntity(null, schemaLocation); 354 result = unmarshalInternal(CmsXmlUtils.unmarshalHelper(source, resolver), schemaLocation, resolver); 355 } 356 return result; 357 } 358 359 371 public static CmsXmlContentDefinition unmarshal(String xmlData, String schemaLocation, EntityResolver resolver) 372 throws CmsXmlException { 373 374 CmsXmlContentDefinition result = getCachedContentDefinition(schemaLocation, resolver); 375 if (result == null) { 376 result = unmarshalInternal(CmsXmlUtils.unmarshalHelper(xmlData, resolver), schemaLocation, resolver); 378 } 379 return result; 380 } 381 382 389 protected static String createTypeName(String name) { 390 391 StringBuffer result = new StringBuffer (32); 392 result.append("OpenCms"); 393 result.append(name.substring(0, 1).toUpperCase()); 394 if (name.length() > 1) { 395 result.append(name.substring(1)); 396 } 397 return result.toString(); 398 } 399 400 417 protected static String validateAttribute(Element element, String attributeName, String requiredValue) 418 throws CmsXmlException { 419 420 Attribute attribute = element.attribute(attributeName); 421 if (attribute == null) { 422 throw new CmsXmlException(Messages.get().container( 423 Messages.ERR_EL_MISSING_ATTRIBUTE_2, 424 element.getUniquePath(), 425 attributeName)); 426 } 427 String value = attribute.getValue(); 428 429 if (requiredValue == null) { 430 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value) || !value.equals(value.trim())) { 431 throw new CmsXmlException(Messages.get().container( 432 Messages.ERR_EL_BAD_ATTRIBUTE_WS_3, 433 element.getUniquePath(), 434 attributeName, 435 value)); 436 } 437 } else { 438 if (!requiredValue.equals(value)) { 439 throw new CmsXmlException(Messages.get().container( 440 Messages.ERR_EL_BAD_ATTRIBUTE_VALUE_4, 441 new Object [] {element.getUniquePath(), attributeName, requiredValue, value})); 442 } 443 } 444 return value; 445 } 446 447 456 protected static void validateAttributesExists( 457 Element element, 458 String [] requiredAttributes, 459 String [] optionalAttributes) throws CmsXmlException { 460 461 if (element.attributeCount() < requiredAttributes.length) { 462 throw new CmsXmlException(Messages.get().container( 463 Messages.ERR_EL_ATTRIBUTE_TOOFEW_3, 464 element.getUniquePath(), 465 new Integer (requiredAttributes.length), 466 new Integer (element.attributeCount()))); 467 } 468 469 if (element.attributeCount() > (requiredAttributes.length + optionalAttributes.length)) { 470 throw new CmsXmlException(Messages.get().container( 471 Messages.ERR_EL_ATTRIBUTE_TOOMANY_3, 472 element.getUniquePath(), 473 new Integer (requiredAttributes.length + optionalAttributes.length), 474 new Integer (element.attributeCount()))); 475 } 476 477 List attributes = element.attributes(); 478 479 for (int i = 0; i < requiredAttributes.length; i++) { 480 String attributeName = requiredAttributes[i]; 481 if (element.attribute(attributeName) == null) { 482 throw new CmsXmlException(Messages.get().container( 483 Messages.ERR_EL_MISSING_ATTRIBUTE_2, 484 element.getUniquePath(), 485 attributeName)); 486 } 487 } 488 489 List rA = Arrays.asList(requiredAttributes); 490 List oA = Arrays.asList(optionalAttributes); 491 492 for (int i = 0; i < attributes.size(); i++) { 493 String attributeName = element.attribute(i).getName(); 494 if (!rA.contains(attributeName) && !oA.contains(attributeName)) { 495 throw new CmsXmlException(Messages.get().container( 496 Messages.ERR_EL_INVALID_ATTRIBUTE_2, 497 element.getUniquePath(), 498 attributeName)); 499 } 500 } 501 } 502 503 514 protected static CmsXmlComplexTypeSequence validateComplexTypeSequence( 515 Element element, 516 Set includes, 517 CmsXmlContentDefinition definition) throws CmsXmlException { 518 519 validateAttributesExists(element, new String [] {XSD_ATTRIBUTE_NAME}, new String [0]); 520 521 String name = validateAttribute(element, XSD_ATTRIBUTE_NAME, null); 522 523 List mainElements = element.elements(); 525 if ((mainElements.size() != 1) && (mainElements.size() != 2)) { 526 throw new CmsXmlException(Messages.get().container( 527 Messages.ERR_TS_SUBELEMENT_COUNT_2, 528 element.getUniquePath(), 529 new Integer (mainElements.size()))); 530 } 531 532 boolean hasLanguageAttribute = false; 533 if (mainElements.size() == 2) { 534 536 Element typeAttribute = (Element)mainElements.get(1); 537 if (!XSD_NODE_ATTRIBUTE.equals(typeAttribute.getQName())) { 538 throw new CmsXmlException(Messages.get().container( 539 Messages.ERR_CD_ELEMENT_NAME_3, 540 typeAttribute.getUniquePath(), 541 XSD_NODE_ATTRIBUTE.getQualifiedName(), 542 typeAttribute.getQName().getQualifiedName())); 543 } 544 validateAttribute(typeAttribute, XSD_ATTRIBUTE_NAME, XSD_ATTRIBUTE_VALUE_LANGUAGE); 545 validateAttribute(typeAttribute, XSD_ATTRIBUTE_TYPE, CmsXmlLocaleValue.TYPE_NAME); 546 try { 547 validateAttribute(typeAttribute, XSD_ATTRIBUTE_USE, XSD_ATTRIBUTE_VALUE_REQUIRED); 548 } catch (CmsXmlException e) { 549 validateAttribute(typeAttribute, XSD_ATTRIBUTE_USE, XSD_ATTRIBUTE_VALUE_OPTIONAL); 550 } 551 hasLanguageAttribute = true; 553 } 554 555 Element typeSequence = (Element)mainElements.get(0); 557 if (!XSD_NODE_SEQUENCE.equals(typeSequence.getQName())) { 558 throw new CmsXmlException(Messages.get().container( 559 Messages.ERR_CD_ELEMENT_NAME_3, 560 typeSequence.getUniquePath(), 561 XSD_NODE_SEQUENCE.getQualifiedName(), 562 typeSequence.getQName().getQualifiedName())); 563 } 564 565 List typeSequenceElements = typeSequence.elements(); 567 if (typeSequenceElements.size() < 1) { 568 throw new CmsXmlException(Messages.get().container( 569 Messages.ERR_TS_SUBELEMENT_TOOFEW_3, 570 typeSequence.getUniquePath(), 571 new Integer (1), 572 new Integer (typeSequenceElements.size()))); 573 } 574 575 List sequence = new ArrayList (); 577 578 if (hasLanguageAttribute) { 579 581 CmsXmlContentTypeManager typeManager = OpenCms.getXmlContentTypeManager(); 582 Iterator i = typeSequenceElements.iterator(); 583 while (i.hasNext()) { 584 sequence.add(typeManager.getContentType((Element)i.next(), includes)); 585 } 586 } else { 587 589 Element e = (Element)typeSequenceElements.get(0); 590 String typeName = validateAttribute(e, XSD_ATTRIBUTE_NAME, null); 591 String minOccurs = validateAttribute(e, XSD_ATTRIBUTE_MIN_OCCURS, XSD_ATTRIBUTE_VALUE_ZERO); 592 String maxOccurs = validateAttribute(e, XSD_ATTRIBUTE_MAX_OCCURS, XSD_ATTRIBUTE_VALUE_UNBOUNDED); 593 validateAttribute(e, XSD_ATTRIBUTE_TYPE, createTypeName(typeName)); 594 595 CmsXmlNestedContentDefinition cd = new CmsXmlNestedContentDefinition(null, typeName, minOccurs, maxOccurs); 596 sequence.add(cd); 597 } 598 599 return definition.new CmsXmlComplexTypeSequence(name, sequence, hasLanguageAttribute); 601 } 602 603 611 private static CmsXmlContentDefinition getCachedContentDefinition(String schemaLocation, EntityResolver resolver) { 612 613 if (resolver instanceof CmsXmlEntityResolver) { 614 CmsXmlEntityResolver cmsResolver = (CmsXmlEntityResolver)resolver; 616 return cmsResolver.getCachedContentDefinition(schemaLocation); 617 } 618 return null; 619 } 620 621 636 private static CmsXmlContentDefinition unmarshalInternal( 637 Document document, 638 String schemaLocation, 639 EntityResolver resolver) throws CmsXmlException { 640 641 Element root = document.getRootElement(); 643 if (!XSD_NODE_SCHEMA.equals(root.getQName())) { 644 throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_NO_SCHEMA_NODE_0)); 646 } 647 648 List includes = root.elements(XSD_NODE_INCLUDE); 649 if (includes.size() < 1) { 650 throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_ONE_INCLUDE_REQUIRED_0)); 652 } 653 654 Element include = (Element)includes.get(0); 655 String target = validateAttribute(include, XSD_ATTRIBUTE_SCHEMA_LOCATION, null); 656 if (!XSD_INCLUDE_OPENCMS.equals(target)) { 657 throw new CmsXmlException(Messages.get().container( 659 Messages.ERR_CD_FIRST_INCLUDE_2, 660 XSD_INCLUDE_OPENCMS, 661 target)); 662 } 663 664 Set nestedDefinitions = new HashSet (); 665 if (includes.size() > 1) { 666 for (int i = 1; i < includes.size(); i++) { 668 669 Element inc = (Element)includes.get(i); 670 String schemaLoc = validateAttribute(inc, XSD_ATTRIBUTE_SCHEMA_LOCATION, null); 671 InputSource source = null; 672 try { 673 source = resolver.resolveEntity(null, schemaLoc); 674 } catch (Exception e) { 675 throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_BAD_INCLUDE_1, schemaLoc)); 676 } 677 CmsXmlContentDefinition xmlContentDefinition = unmarshal(source, schemaLoc, resolver); 678 nestedDefinitions.add(xmlContentDefinition); 679 } 680 } 681 682 List elements = root.elements(XSD_NODE_ELEMENT); 683 if (elements.size() != 1) { 684 throw new CmsXmlException(Messages.get().container( 686 Messages.ERR_CD_ROOT_ELEMENT_COUNT_1, 687 XSD_INCLUDE_OPENCMS, 688 new Integer (elements.size()))); 689 } 690 691 Element main = (Element)elements.get(0); 693 String name = validateAttribute(main, XSD_ATTRIBUTE_NAME, null); 694 695 List complexTypes = root.elements(XSD_NODE_COMPLEXTYPE); 697 if (complexTypes.size() != 2) { 698 throw new CmsXmlException(Messages.get().container( 700 Messages.ERR_CD_COMPLEX_TYPE_COUNT_1, 701 new Integer (complexTypes.size()))); 702 } 703 704 CmsXmlContentDefinition result = new CmsXmlContentDefinition(name, null, schemaLocation); 706 707 result.m_includes = nestedDefinitions; 709 710 List complexTypeData = new ArrayList (); 711 Iterator ct = complexTypes.iterator(); 712 while (ct.hasNext()) { 713 Element e = (Element)ct.next(); 714 CmsXmlComplexTypeSequence sequence = validateComplexTypeSequence(e, nestedDefinitions, result); 715 complexTypeData.add(sequence); 716 } 717 718 CmsXmlComplexTypeSequence outerSequence = (CmsXmlComplexTypeSequence)complexTypeData.get(0); 720 CmsXmlNestedContentDefinition outer = (CmsXmlNestedContentDefinition)outerSequence.m_sequence.get(0); 721 722 String outerTypeName = createTypeName(name); 724 String innerTypeName = createTypeName(outer.getName()); 725 validateAttribute((Element)complexTypes.get(0), XSD_ATTRIBUTE_NAME, outerTypeName); 726 validateAttribute((Element)complexTypes.get(1), XSD_ATTRIBUTE_NAME, innerTypeName); 727 validateAttribute(main, XSD_ATTRIBUTE_TYPE, outerTypeName); 728 729 result.setInnerName(outer.getName()); 731 732 CmsXmlComplexTypeSequence innerSequence = (CmsXmlComplexTypeSequence)complexTypeData.get(1); 734 735 Iterator it = innerSequence.m_sequence.iterator(); 737 while (it.hasNext()) { 738 result.addType((I_CmsXmlSchemaType)it.next()); 739 } 740 741 List annotations = root.elements(XSD_NODE_ANNOTATION); 743 I_CmsXmlContentHandler contentHandler = null; 744 Element appInfoElement = null; 745 746 if (annotations.size() > 0) { 747 List appinfos = ((Element)annotations.get(0)).elements(XSD_NODE_APPINFO); 748 749 if (appinfos.size() > 0) { 750 appInfoElement = (Element)appinfos.get(0); 752 753 Element handlerElement = appInfoElement.element("handler"); 755 if (handlerElement != null) { 756 String className = handlerElement.attributeValue("class"); 757 if (className != null) { 758 contentHandler = OpenCms.getXmlContentTypeManager().getContentHandler(className, schemaLocation); 759 } 760 } 761 } 762 } 763 764 if (contentHandler == null) { 765 contentHandler = OpenCms.getXmlContentTypeManager().getContentHandler( 767 CmsDefaultXmlContentHandler.class.getName(), 768 name); 769 } 770 771 contentHandler.initialize(appInfoElement, result); 773 result.m_contentHandler = contentHandler; 774 775 result.freeze(); 776 777 if (resolver instanceof CmsXmlEntityResolver) { 778 ((CmsXmlEntityResolver)resolver).cacheContentDefinition(schemaLocation, result); 780 } 781 782 return result; 783 } 784 785 797 public Element addDefaultXml(CmsObject cms, I_CmsXmlDocument document, Element root, Locale locale) { 798 799 Iterator i = m_typeSequence.iterator(); 800 int currentPos = 0; 801 List allElements = root.elements(); 802 803 while (i.hasNext()) { 804 I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)i.next(); 805 806 String elementName = type.getName(); 808 List elements = root.elements(elementName); 809 810 currentPos += elements.size(); 811 for (int j = elements.size(); j < type.getMinOccurs(); j++) { 812 Element typeElement = type.generateXml(cms, document, root, locale); 814 I_CmsXmlContentValue value = type.createValue(document, typeElement, locale); 816 String defaultValue = document.getContentDefinition().getContentHandler().getDefault(cms, value, locale); 817 if (defaultValue != null) { 818 value.setStringValue(cms, defaultValue); 820 } 821 822 typeElement.detach(); 824 allElements.add(currentPos, typeElement); 825 currentPos++; 826 } 827 } 828 829 return root; 830 } 831 832 837 public void addInclude(CmsXmlContentDefinition nestedSchema) { 838 839 m_includes.add(nestedSchema); 840 } 841 842 849 public void addType(I_CmsXmlSchemaType type) throws CmsXmlException { 850 851 CmsXmlContentTypeManager typeManager = OpenCms.getXmlContentTypeManager(); 853 if (type.isSimpleType() && (typeManager.getContentType(type.getTypeName()) == null)) { 854 throw new CmsXmlException(Messages.get().container(Messages.ERR_UNREGISTERED_TYPE_1, type.getTypeName())); 855 } 856 857 m_typeSequence.add(type); 859 m_types.put(type.getName(), type); 860 861 type.setContentDefinition(this); 863 } 864 865 870 public Object clone() { 871 872 CmsXmlContentDefinition result = new CmsXmlContentDefinition(); 873 result.m_innerName = m_innerName; 874 result.m_schemaLocation = m_schemaLocation; 875 result.m_typeSequence = m_typeSequence; 876 result.m_types = m_types; 877 result.m_contentHandler = m_contentHandler; 878 result.m_typeName = m_typeName; 879 result.m_includes = m_includes; 880 return result; 881 } 882 883 897 public Element createDefaultXml(CmsObject cms, I_CmsXmlDocument document, Element root, Locale locale) { 898 899 Iterator i = m_typeSequence.iterator(); 900 while (i.hasNext()) { 901 I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)i.next(); 902 for (int j = 0; j < type.getMinOccurs(); j++) { 903 Element typeElement = type.generateXml(cms, document, root, locale); 904 I_CmsXmlContentValue value = type.createValue(document, typeElement, locale); 906 String defaultValue = document.getContentDefinition().getContentHandler().getDefault(cms, value, locale); 907 if (defaultValue != null) { 908 value.setStringValue(cms, defaultValue); 910 } 911 } 912 } 913 914 return root; 915 } 916 917 926 public Document createDocument(CmsObject cms, I_CmsXmlDocument document, Locale locale) { 927 928 Document doc = DocumentHelper.createDocument(); 929 930 Element root = doc.addElement(getOuterName()); 931 932 root.add(I_CmsXmlSchemaType.XSI_NAMESPACE); 933 root.addAttribute(I_CmsXmlSchemaType.XSI_NAMESPACE_ATTRIBUTE_NO_SCHEMA_LOCATION, getSchemaLocation()); 934 935 createLocale(cms, document, root, locale); 936 return doc; 937 } 938 939 949 public Element createLocale(CmsObject cms, I_CmsXmlDocument document, Element root, Locale locale) { 950 951 Element element = root.addElement(getInnerName()); 953 element.addAttribute(XSD_ATTRIBUTE_VALUE_LANGUAGE, locale.toString()); 954 955 return createDefaultXml(cms, document, element, locale); 957 } 958 959 962 public boolean equals(Object obj) { 963 964 if (obj == this) { 965 return true; 966 } 967 if (!(obj instanceof CmsXmlContentDefinition)) { 968 return false; 969 } 970 CmsXmlContentDefinition other = (CmsXmlContentDefinition)obj; 971 if (!getInnerName().equals(other.getInnerName())) { 972 return false; 973 } 974 if (!getOuterName().equals(other.getOuterName())) { 975 return false; 976 } 977 return m_typeSequence.equals(other.m_typeSequence); 978 } 979 980 986 public void freeze() { 987 988 m_types = Collections.unmodifiableMap(m_types); 989 m_typeSequence = Collections.unmodifiableList(m_typeSequence); 990 } 991 992 1000 public I_CmsXmlContentHandler getContentHandler() { 1001 1002 return m_contentHandler; 1003 } 1004 1005 1010 public Set getIncludes() { 1011 1012 return m_includes; 1013 } 1014 1015 1020 public String getInnerName() { 1021 1022 return m_innerName; 1023 } 1024 1025 1030 public String getOuterName() { 1031 1032 return m_outerName; 1033 } 1034 1035 1040 public Document getSchema() { 1041 1042 Document schema = DocumentHelper.createDocument(); 1043 1044 Element root = schema.addElement(XSD_NODE_SCHEMA); 1045 root.addAttribute(XSD_ATTRIBUTE_ELEMENT_FORM_DEFAULT, XSD_ATTRIBUTE_VALUE_QUALIFIED); 1046 1047 Element include = root.addElement(XSD_NODE_INCLUDE); 1048 include.addAttribute(XSD_ATTRIBUTE_SCHEMA_LOCATION, XSD_INCLUDE_OPENCMS); 1049 1050 if (m_includes.size() > 0) { 1051 Iterator i = m_includes.iterator(); 1052 while (i.hasNext()) { 1053 CmsXmlContentDefinition definition = (CmsXmlContentDefinition)i.next(); 1054 root.addElement(XSD_NODE_INCLUDE).addAttribute( 1055 XSD_ATTRIBUTE_SCHEMA_LOCATION, 1056 definition.m_schemaLocation); 1057 } 1058 } 1059 1060 String outerTypeName = createTypeName(getOuterName()); 1061 String innerTypeName = createTypeName(getInnerName()); 1062 1063 Element content = root.addElement(XSD_NODE_ELEMENT); 1064 content.addAttribute(XSD_ATTRIBUTE_NAME, getOuterName()); 1065 content.addAttribute(XSD_ATTRIBUTE_TYPE, outerTypeName); 1066 1067 Element list = root.addElement(XSD_NODE_COMPLEXTYPE); 1068 list.addAttribute(XSD_ATTRIBUTE_NAME, outerTypeName); 1069 1070 Element listSequence = list.addElement(XSD_NODE_SEQUENCE); 1071 Element listElement = listSequence.addElement(XSD_NODE_ELEMENT); 1072 listElement.addAttribute(XSD_ATTRIBUTE_NAME, getInnerName()); 1073 listElement.addAttribute(XSD_ATTRIBUTE_TYPE, innerTypeName); 1074 listElement.addAttribute(XSD_ATTRIBUTE_MIN_OCCURS, XSD_ATTRIBUTE_VALUE_ZERO); 1075 listElement.addAttribute(XSD_ATTRIBUTE_MAX_OCCURS, XSD_ATTRIBUTE_VALUE_UNBOUNDED); 1076 1077 Element main = root.addElement(XSD_NODE_COMPLEXTYPE); 1078 main.addAttribute(XSD_ATTRIBUTE_NAME, innerTypeName); 1079 1080 Element mainSequence = main.addElement(XSD_NODE_SEQUENCE); 1081 1082 Iterator i = m_typeSequence.iterator(); 1083 while (i.hasNext()) { 1084 I_CmsXmlSchemaType schemaType = (I_CmsXmlSchemaType)i.next(); 1085 schemaType.appendXmlSchema(mainSequence); 1086 } 1087 1088 Element language = main.addElement(XSD_NODE_ATTRIBUTE); 1089 language.addAttribute(XSD_ATTRIBUTE_NAME, XSD_ATTRIBUTE_VALUE_LANGUAGE); 1090 language.addAttribute(XSD_ATTRIBUTE_TYPE, CmsXmlLocaleValue.TYPE_NAME); 1091 language.addAttribute(XSD_ATTRIBUTE_USE, XSD_ATTRIBUTE_VALUE_REQUIRED); 1092 1093 return schema; 1094 } 1095 1096 1101 public String getSchemaLocation() { 1102 1103 return m_schemaLocation; 1104 } 1105 1106 1114 public I_CmsXmlSchemaType getSchemaType(String elementPath) { 1115 1116 String path = CmsXmlUtils.getFirstXpathElement(elementPath); 1117 1118 I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)m_types.get(path); 1119 if (type == null) { 1120 return null; 1122 } 1123 1124 if (type.isSimpleType() || !CmsXmlUtils.isDeepXpath(elementPath)) { 1126 return type; 1128 } 1129 1130 CmsXmlNestedContentDefinition nestedDefinition = (CmsXmlNestedContentDefinition)type; 1132 path = CmsXmlUtils.removeFirstXpathElement(elementPath); 1133 return nestedDefinition.getNestedContentDefinition().getSchemaType(path); 1134 } 1135 1136 1141 public String getTypeName() { 1142 1143 return m_typeName; 1144 } 1145 1146 1151 public List getTypeSequence() { 1152 1153 return m_typeSequence; 1154 } 1155 1156 1159 public int hashCode() { 1160 1161 return getInnerName().hashCode(); 1162 } 1163 1164 1169 protected void setInnerName(String innerName) { 1170 1171 m_innerName = innerName; 1172 if (m_innerName != null) { 1173 m_typeName = createTypeName(innerName); 1174 } 1175 } 1176 1177 1182 protected void setOuterName(String outerName) { 1183 1184 m_outerName = outerName; 1185 } 1186} | Popular Tags |