View Javadoc

1   // $Id: ComplexTypeDescription.java 165 2009-05-28 21:46:38Z agony $
2   /**
3    * 
4    */
5   package de.mindcrimeilab.xsanalyzer.xsext;
6   
7   import java.security.MessageDigest;
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import java.util.Collections;
11  import java.util.List;
12  
13  import org.apache.xerces.xs.XSAttributeDeclaration;
14  import org.apache.xerces.xs.XSAttributeUse;
15  import org.apache.xerces.xs.XSComplexTypeDefinition;
16  import org.apache.xerces.xs.XSConstants;
17  import org.apache.xerces.xs.XSElementDeclaration;
18  import org.apache.xerces.xs.XSModelGroup;
19  import org.apache.xerces.xs.XSObjectList;
20  import org.apache.xerces.xs.XSParticle;
21  import org.apache.xerces.xs.XSSimpleTypeDefinition;
22  import org.apache.xerces.xs.XSTerm;
23  import org.apache.xerces.xs.XSTypeDefinition;
24  
25  import de.mindcrimeilab.util.CollectionsHelper;
26  import de.mindcrimeilab.xsanalyzer.util.NameComparator;
27  import de.mindcrimeilab.xsanalyzer.util.XSListHelper;
28  import de.mindcrimeilab.xsanalyzer.util.XSModelHelper;
29  import de.mindcrimeilab.xsanalyzer.util.XsAttributeExtractor;
30  
31  /**
32   * @author Michael Engelhardt<me@mindcrime-ilab.de>
33   * @author $Author: agony $
34   * @version $Revision: 165 $
35   * 
36   */
37  public class ComplexTypeDescription extends AbstractTypeDescription {
38  
39      public static String getSignatureDigest(XSComplexTypeDefinition ctypedef, MessageDigest md) {
40          String signature = ComplexTypeDescription.getSignature(ctypedef);
41          String digest = AbstractTypeDescription.getSignatureDigest(signature, md);
42          AbstractTypeDescription.logger.debug("Signature of type [{" + ctypedef.getNamespace() + "}:" + ctypedef.getName() + "|" + signature.toString() + "] is [" + digest + "]");
43          return digest;
44      }
45  
46      public static String getSignature(XSComplexTypeDefinition ctypedef) {
47  
48          StringBuilder signature = new StringBuilder();
49          XSTypeDefinition baseType = AbstractTypeDescription.getBaseTypeRecursive(ctypedef);
50  
51          switch (ctypedef.getContentType()) {
52              case XSComplexTypeDefinition.CONTENTTYPE_SIMPLE:
53                  if (null == ctypedef.getParticle()) {
54                      signature.append(SimpleTypeDescription.getSignature(ctypedef.getSimpleType()));
55                  }
56                  else {
57                      AbstractTypeDescription.appendBaseType(signature, baseType);
58                      signature.append(ComplexTypeDescription.inspectComplexType(ctypedef));
59                  }
60                  break;
61              case XSComplexTypeDefinition.CONTENTTYPE_EMPTY:
62                  AbstractTypeDescription.appendBaseType(signature, baseType);
63                  AbstractTypeDescription.logger.debug("{" + ctypedef.getNamespace() + "}" + ctypedef.getName() + " empty content!");
64                  break;
65              case XSComplexTypeDefinition.CONTENTTYPE_ELEMENT:
66                  AbstractTypeDescription.appendBaseType(signature, baseType);
67                  signature.append(ComplexTypeDescription.inspectComplexType(ctypedef));
68                  break;
69              default:
70                  AbstractTypeDescription.appendBaseType(signature, baseType);
71                  signature.append(ctypedef.getName()).append(ctypedef.getNamespace());
72                  AbstractTypeDescription.logger.warn("{" + ctypedef.getNamespace() + "}" + ctypedef.getName() + " undefined content type.");
73                  break;
74  
75          }
76  
77          List<XSAttributeDeclaration> attributes = ComplexTypeDescription.getAttributes(ctypedef);
78          if (null != attributes) {
79              for (XSAttributeDeclaration attributeDeclaration : attributes) {
80                  signature.append(SimpleTypeDescription.getSignature(attributeDeclaration.getTypeDefinition()));
81              }
82          }
83  
84          return signature.toString();
85      }
86  
87      private static String inspectComplexType(XSComplexTypeDefinition ctypedef) {
88          StringBuilder sig = new StringBuilder();
89          XSParticle particle = ctypedef.getParticle();
90          if (null != particle) {
91              XSTerm term = particle.getTerm();
92              sig.append(ComplexTypeDescription.inspectTerm(term));
93          }
94          return sig.toString();
95      }
96  
97      /**
98       * @param ctypedef
99       * @param term
100      * @param signature
101      */
102     private static String inspectTerm(XSTerm term) {
103         StringBuilder sig = new StringBuilder();
104         switch (term.getType()) {
105             case XSConstants.MODEL_GROUP:
106                 AbstractTypeDescription.logger.debug("==> found model group");
107                 XSModelGroup group = (XSModelGroup) term;
108                 sig.append(":").append(XSModelHelper.compositorToString(group.getCompositor()));
109                 sig.append("[");
110                 XSObjectList list = group.getParticles();
111                 List<String> subSignatures = new ArrayList<String>();
112                 for (int i = 0; i < list.getLength(); ++i) {
113                     XSParticle part = (XSParticle) list.item(i);
114                     XSTerm item = part.getTerm();
115                     AbstractTypeDescription.logger.debug("==--> embedded [{" + item.getNamespace() + "}:" + item.getName() + "]");
116                     subSignatures.add(ComplexTypeDescription.inspectTerm(item));
117                 }
118 
119                 /*
120                  * choice elements may differ in their definition order describing the same content model for example:
121                  * {@code
122                  * 
123                  * <xs:choice>
124                  * 
125                  * <xs:element name="eihter" type="xs:string"/>
126                  * 
127                  * <xs:element name="or" type="xs:float"/>
128                  * 
129                  * </xs:choice>
130                  * 
131                  * }
132                  * 
133                  * may be equivalent to {@code
134                  * 
135                  * <xs:choice>
136                  * 
137                  * <xs:element name="or" type="xs:float"/>
138                  * 
139                  * <xs:element name="either" type="xs:string"/>
140                  * 
141                  * </xs:choice>
142                  * 
143                  * }
144                  */
145                 if (group.getCompositor() == XSModelGroup.COMPOSITOR_CHOICE) {
146                     Collections.sort(subSignatures);
147                 }
148                 for (String subSig : subSignatures) {
149                     sig.append(subSig).append("|");
150                 }
151                 sig.append("]");
152                 break;
153             case XSConstants.ELEMENT_DECLARATION:
154                 XSElementDeclaration elementDeclaration = (XSElementDeclaration) term;
155                 final String tempSig;
156                 if (XSTypeDefinition.COMPLEX_TYPE == elementDeclaration.getTypeDefinition().getTypeCategory()) {
157                     tempSig = ComplexTypeDescription.getSignature((XSComplexTypeDefinition) elementDeclaration.getTypeDefinition());
158                 }
159                 else {
160                     tempSig = SimpleTypeDescription.getSignature((XSSimpleTypeDefinition) elementDeclaration.getTypeDefinition());
161                 }
162                 sig.append(tempSig);
163                 break;
164             case XSConstants.WILDCARD:
165                 AbstractTypeDescription.logger.warn("==> found wildcard");
166                 break;
167             default:
168                 AbstractTypeDescription.logger.warn("-------------- UNKNOWN PARTICLE TYPE OF TYPE [" + term.getType() + "]");
169                 throw new RuntimeException("Unexpected branch selection - Not implemented");
170         }
171         return sig.toString();
172     }
173 
174     /**
175      * @param ctypedef
176      * @return
177      */
178     private static List<XSAttributeDeclaration> getAttributes(XSComplexTypeDefinition ctypedef) {
179         List<XSAttributeDeclaration> attributes = null;
180         XSObjectList attributesObjectList = ctypedef.getAttributeUses();
181         if (0 < attributesObjectList.getLength()) {
182             List temp = XSListHelper.asList(attributesObjectList);
183             attributes = new ArrayList<XSAttributeDeclaration>();
184             CollectionsHelper.copyCollection((Collection<XSAttributeUse>) temp, attributes, new XsAttributeExtractor());
185             Collections.sort(attributes, new NameComparator());
186         }
187         return attributes;
188     }
189 
190 }