1 package org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; 23 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; 24 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; 25 import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; 26 import org.codehaus.mojo.jaxb2.shared.Validate; 27 import org.w3c.dom.Node; 28 29 import java.util.SortedMap; 30 31 /** 32 * <p>Node processor that injects XSD documentation annotations consisting of JavaDoc harvested Java source code 33 * into ComplexTypes, Elements and Attributes. The documentation is injected as follows:</p> 34 * <ol> 35 * <li><strong>ComplexType</strong>: Class-level JavaDoc from the corresponding type is injected as an 36 * annotation directly inside the complexType.</li> 37 * <li><strong>Element</strong>: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does 38 * not contain a JavaDoc annotation) from the corresponding member is injected as an 39 * annotation directly inside the element.</li> 40 * <li><strong>Attribute</strong>: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does 41 * not contain a JavaDoc annotation) from the corresponding member is injected as an 42 * annotation directly inside the element.</li> 43 * </ol> 44 * <p>Thus, the following 'vanilla'-generated XSD:</p> 45 * <pre> 46 * <code> 47 * <xs:complexType name="somewhatNamedPerson"> 48 * <xs:sequence> 49 * <xs:element name="firstName" type="xs:string" nillable="true" minOccurs="0"/> 50 * <xs:element name="lastName" type="xs:string"/> 51 * </xs:sequence> 52 * <xs:attribute name="age" type="xs:int" use="required"/> 53 * </xs:complexType> 54 * </code> 55 * </pre> 56 * <p>... would be converted to the following annotated XSD, given a DefaultJavaDocRenderer:</p> 57 * <pre> 58 * <code> 59 * <xs:complexType name="somewhatNamedPerson"> 60 * <xs:annotation> 61 * <xs:documentation><![CDATA[Definition of a person with lastName and age, and optionally a firstName as well... 62 * 63 * (author): <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB 64 * (custom): A custom JavaDoc annotation.]]></xs:documentation> 65 * </xs:annotation> 66 * <xs:sequence> 67 * <xs:element minOccurs="0" name="firstName" nillable="true" type="xs:string"> 68 * <xs:annotation> 69 * <xs:documentation><![CDATA[The first name of the SomewhatNamedPerson.]]></xs:documentation> 70 * </xs:annotation> 71 * </xs:element> 72 * <xs:element name="lastName" type="xs:string"> 73 * <xs:annotation> 74 * <xs:documentation><![CDATA[The last name of the SomewhatNamedPerson.]]></xs:documentation> 75 * </xs:annotation> 76 * </xs:element> 77 * </xs:sequence> 78 * <xs:attribute name="age" type="xs:int" use="required"> 79 * <xs:annotation> 80 * <xs:documentation><![CDATA[The age of the SomewhatNamedPerson. Must be positive.]]></xs:documentation> 81 * </xs:annotation> 82 * </xs:attribute> 83 * </xs:complexType> 84 * </code> 85 * </pre> 86 * <p>... given that the Java class <code>SomewhatNamedPerson</code> has JavaDoc on its class and fields 87 * corresponding to the injected XSD annotation/documentation elements.</p> 88 * 89 * @author <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB 90 * @see org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocRenderer 91 * @since 2.0 92 */ 93 public class XsdAnnotationProcessor implements NodeProcessor { 94 95 // Internal state 96 private SortedMap<ClassLocation, JavaDocData> classJavaDocs; 97 private SortedMap<FieldLocation, JavaDocData> fieldJavaDocs; 98 private SortedMap<MethodLocation, JavaDocData> methodJavaDocs; 99 private JavaDocRenderer renderer; 100 101 /** 102 * Creates an XsdAnnotationProcessor that uses the supplied/generated SearchableDocumentation to read all 103 * JavaDoc structures and the supplied JavaDocRenderer to render JavaDocs into XSD documentation annotations. 104 * 105 * @param docs A non-null SearchableDocumentation, produced from the source code of the JAXB compilation unit. 106 * @param renderer A non-null JavaDocRenderer, used to render the JavaDocData within the SearchableDocumentation. 107 */ 108 public XsdAnnotationProcessor(final SearchableDocumentation docs, final JavaDocRenderer renderer) { 109 110 // Check sanity 111 Validate.notNull(docs, "docs"); 112 Validate.notNull(renderer, "renderer"); 113 114 // Assign internal state 115 this.classJavaDocs = docs.getAll(ClassLocation.class); 116 this.fieldJavaDocs = docs.getAll(FieldLocation.class); 117 this.methodJavaDocs = docs.getAll(MethodLocation.class); 118 this.renderer = renderer; 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 @Override 125 public boolean accept(final Node aNode) { 126 127 // Only deal with Element nodes with "name" attributes. 128 if (!DomHelper.isNamedElement(aNode)) { 129 return false; 130 } 131 132 /* 133 <xs:complexType name="somewhatNamedPerson"> 134 <!-- ClassLocation JavaDocData insertion point --> 135 136 <xs:sequence> 137 138 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) --> 139 <xs:element name="firstName" type="xs:string" nillable="true" minOccurs="0"/> 140 141 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) --> 142 <xs:element name="lastName" type="xs:string"/> 143 </xs:sequence> 144 145 <!-- FieldLocation or MethodLocation JavaDocData insertion point (within child) --> 146 <xs:attribute name="age" type="xs:int" use="required"/> 147 </xs:complexType> 148 */ 149 150 // Only process nodes corresponding to Types we have any JavaDoc for. 151 // TODO: How should we handle PackageLocations and package documentation? 152 153 boolean toReturn = false; 154 if (DomHelper.getMethodLocation(aNode, methodJavaDocs.keySet()) != null) { 155 toReturn = true; 156 } else if (DomHelper.getFieldLocation(aNode, fieldJavaDocs.keySet()) != null) { 157 toReturn = true; 158 } else if (DomHelper.getClassLocation(aNode, classJavaDocs.keySet()) != null) { 159 toReturn = true; 160 } 161 162 // All done. 163 return toReturn; 164 } 165 166 /** 167 * {@inheritDoc} 168 */ 169 @Override 170 public void process(final Node aNode) { 171 DomHelper.insertXmlDocumentationAnnotationsFor(aNode, classJavaDocs, fieldJavaDocs, methodJavaDocs, renderer); 172 } 173 }