View Javadoc
1   package org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc;
2   
3   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor;
4   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation;
5   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation;
6   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation;
7   import org.codehaus.mojo.jaxb2.shared.Validate;
8   import org.w3c.dom.Element;
9   import org.w3c.dom.Node;
10  
11  import java.util.SortedMap;
12  
13  
14  /**
15   * <p>Node processor that injects XSD documentation annotations consisting of JavaDoc harvested Java source code
16   * into SimpleTypes, Elements and Attributes typically produced by SchemaGen when generate XSDs for Java Enumerations.
17   * The documentation is injected as follows:</p>
18   * <ol>
19   * <li><strong>SimpleType</strong>: Class-level JavaDoc from the corresponding type is injected as an
20   * annotation directly inside the SimpleType.</li>
21   * <li><strong>Element</strong>: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does
22   * not contain a JavaDoc annotation) from the corresponding member is injected as an
23   * annotation directly inside the element.</li>
24   * <li><strong>Attribute</strong>: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does
25   * not contain a JavaDoc annotation) from the corresponding member is injected as an
26   * annotation directly inside the element.</li>
27   * </ol>
28   * <p>Thus, the following 'vanilla'-generated XSD:</p>
29   * <pre>
30   *     <code>
31   *           &lt;xs:simpleType name="foodPreference"&gt;
32   *               &lt;xs:restriction base="xs:string"&gt;
33   *                   &lt;xs:enumeration value="NONE"/&gt;
34   *                   &lt;xs:enumeration value="VEGAN"/&gt;
35   *                   &lt;xs:enumeration value="LACTO_VEGETARIAN"/&gt;
36   *               &lt;/xs:restriction&gt;
37   *           &lt;/xs:simpleType&gt;
38   *     </code>
39   * </pre>
40   * <p>... will be converted in a manner similar to the one below:</p>
41   * <pre>
42   *     <code>
43   *         &lt;xs:simpleType name="foodPreference"&gt;
44   *             &lt;xs:annotation&gt;
45   *                 &lt;xs:documentation&gt;&lt;![CDATA[Simple enumeration example defining some Food preferences.]]&gt;&lt;/xs:documentation&gt;
46   *             &lt;/xs:annotation&gt;
47   *             &lt;xs:restriction base="xs:string"&gt;
48   *                 &lt;xs:enumeration value="LACTO_VEGETARIAN"&gt;
49   *                     &lt;xs:annotation&gt;
50   *                         &lt;xs:documentation&gt;&lt;![CDATA[Vegetarian who will not eat meats, but drinks milk.]]&gt;&lt;/xs:documentation&gt;
51   *                     &lt;/xs:annotation&gt;
52   *                 &lt;/xs:enumeration&gt;
53   *                 &lt;xs:enumeration value="NONE"&gt;
54   *                     &lt;xs:annotation&gt;
55   *                         &lt;xs:documentation&gt;&lt;![CDATA[No special food preferences; eats everything.]]&gt;&lt;/xs:documentation&gt;
56   *                     &lt;/xs:annotation&gt;
57   *                 &lt;/xs:enumeration&gt;
58   *                 &lt;xs:enumeration value="VEGAN"&gt;
59   *                     &lt;xs:annotation&gt;
60   *                         &lt;xs:documentation&gt;&lt;![CDATA[Vegan who will neither eat meats nor drink milk.]]&gt;&lt;/xs:documentation&gt;
61   *                     &lt;/xs:annotation&gt;
62   *                 &lt;/xs:enumeration&gt;
63   *             &lt;/xs:restriction&gt;
64   *         &lt;/xs:simpleType&gt;
65   *     </code>
66   * </pre>
67   * <p>... given that the Java class <code>FoodPreference</code> has JavaDoc on its class and fields
68   * corresponding to the injected XSD annotation/documentation elements.</p>
69   *
70   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>, jGuru Europe AB
71   */
72  public class XsdEnumerationAnnotationProcessor implements NodeProcessor {
73  
74      // Internal state
75      private SortedMap<ClassLocation, JavaDocData> classJavaDocs;
76      private SortedMap<FieldLocation, JavaDocData> fieldJavaDocs;
77      private SortedMap<MethodLocation, JavaDocData> methodJavaDocs;
78      private JavaDocRenderer renderer;
79  
80      /**
81       * Creates an XsdEnumerationAnnotationProcessor that uses the supplied/generated SearchableDocumentation to read all
82       * JavaDoc structures and the supplied JavaDocRenderer to render JavaDocs into XSD documentation annotations.
83       *
84       * @param docs     A non-null SearchableDocumentation, produced from the source code of the JAXB compilation unit.
85       * @param renderer A non-null JavaDocRenderer, used to render the JavaDocData within the SearchableDocumentation.
86       */
87      public XsdEnumerationAnnotationProcessor(final SearchableDocumentation docs, final JavaDocRenderer renderer) {
88  
89          // Check sanity
90          Validate.notNull(docs, "docs");
91          Validate.notNull(renderer, "renderer");
92  
93          // Assign internal state
94          this.classJavaDocs = docs.getAll(ClassLocation.class);
95          this.fieldJavaDocs = docs.getAll(FieldLocation.class);
96          this.methodJavaDocs = docs.getAll(MethodLocation.class);
97          this.renderer = renderer;
98      }
99  
100     /**
101      * <p>Only accept simpleTypes which are restrictions to either <code>xs:string</code> or <code>xs:integer</code>.
102      * The former is generated by JAXB when the Java Enum uses String values, and the latter is used
103      * for ordinal values.</p>
104      *
105      * {@inheritDoc}
106      */
107     @Override
108     public boolean accept(final Node aNode) {
109 
110         // Only deal with Element nodes.
111         if (aNode.getNodeType() != Node.ELEMENT_NODE) {
112             return false;
113         }
114 
115         // We should accept:
116         //
117         // 1) A simpleType Element
118         // 2) An enumeration Element
119         final Element theElement = (Element) aNode;
120 
121         final String localName = theElement.getLocalName();
122         if (localName != null) {
123 
124             final String trimmed = localName.trim();
125             return trimmed.equalsIgnoreCase("enumeration") || trimmed.equalsIgnoreCase("simpleType");
126         }
127 
128         /*
129         <xs:simpleType name="foodPreference">
130             <!-- ClassLocation JavaDocData insertion point -->
131 
132             <xs:restriction base="xs:string">
133 
134                 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) -->
135                 <xs:enumeration value="NONE"/>
136 
137                 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) -->
138                 <xs:enumeration value="LACTO_VEGETARIAN"/>
139 
140                 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) -->
141                 <xs:enumeration value="VEGAN"/>
142 
143             </xs:restriction>
144         </xs:simpleType>
145          */
146 
147         /*
148   <xs:simpleType name="foodPreference">
149     <xs:restriction base="xs:string">
150       <xs:enumeration value="NONE"/>
151       <xs:enumeration value="LACTO_VEGETARIAN"/>
152       <xs:enumeration value="VEGAN"/>
153     </xs:restriction>
154   </xs:simpleType>
155 
156   <xs:simpleType name="americanCoin">
157     <xs:restriction base="xs:int">
158       <xs:enumeration value="25"/>
159       <xs:enumeration value="1"/>
160       <xs:enumeration value="5"/>
161       <xs:enumeration value="10"/>
162     </xs:restriction>
163   </xs:simpleType>
164         */
165 
166         // All done.
167         return false;
168     }
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
174     public void process(final Node aNode) {
175         DomHelper.insertXmlDocumentationAnnotationsFor(aNode, classJavaDocs, fieldJavaDocs, methodJavaDocs, renderer);
176     }
177 }