Как создать сгенерированные классы содержат Javadoc из документации XML Schema

В настоящее время я работаю с XML-схемой, которая имеет <xsd:annotation>/<xsd:documentation> для большинства типов и элементов. Когда я генерирую Java Beans из этой XML-схемы, Javadoc из этих Beans содержит только общую генерированную информацию о разрешенном содержимом типа/элемента.

Я хотел бы видеть содержимое тега <xsd:documentation> в соответствующих местах (например, содержимое этого тега для contentxtType должно отображаться в Javadoc класса, сгенерированного для представления этого complexType).

Есть ли способ достичь этого?

Изменить: эта XML-схема будет использоваться в WSDL с JAX-WS, поэтому этот тег также может быть подходящим.

Изменить 2. Я читал о <jxb:javadoc>. Насколько я понимаю, я могу указать это либо в отдельном файле привязки JAXB, либо непосредственно в XML-схеме. Это почти решило бы мою проблему. Но я бы предпочел использовать существующий тег <xsd:documentation>, поскольку Javadoc не является основной целью документации (это информация о структуре данных в первую очередь, а не о Java Beans, сгенерированном из нее), и разрешить инструменты без JAXB для доступа к информации. Предоставление документации в <jxb:javadoc> и xsd:documentation> "кажется" неправильным, потому что я не дублирую данные (и работаю) без уважительной причины.

Изменить 3. Благодаря ответу Паскаля я понял, что у меня уже есть половина решения: <xsd:documentation> of complexType записывается в начало его Javadoc! Проблема по-прежнему заключается в том, что используется только complexType и simpleType (что также может привести к классу), а элементы все еще Javadoc-less.

Ответ 1

Мне никогда не приходилось устанавливать регулярные xsd:documentation в исходный код java, кроме , если и только если это сложный тип. Документация для элементов, простых типов, и т.д. игнорируются.

Итак, я использую jxb:javadoc. Для этого включите определение xmlns:jxb="http://java.sun.com/xml/ns/jaxb" в свой <xsd:schema> элемент.

Добавьте ребенка в <xsd:complexType> или <xsd: element> или <xsd:attribute>:

<xsd:annotation><xsd:appinfo><jxb:XXX><jxb:javadoc>
  This is my comment for a class/property
</jxb:javadoc></jxb:XXX></xsd:appinfo></xsd:annotation>

Где XXX - это либо "класс", либо "свойство".

Для пакета вы пишете дочерний элемент xsd:schema

<xsd:annotation><xsd:appinfo><jxb:schemaBindings><jxb:package name="com.acme"><jxb:javadoc>
  This is my comment for a package
</jxb:javadoc></jxb:package></jxb:schemaBindings></xsd:appinfo></xsd:annotation>

Запись HTML-документа требует брекетинга с помощью <![CDATA[ --- ]]>

(EDIT: при написании моего ответа вопрос был отредактирован OP, поэтому я обновляю его соответствующим образом)

В моем случае javadoc был единственной целью, поэтому было приемлемо использовать jxb:javadoc. Но ваше обновление имеет прекрасный смысл, и, на самом деле, я полностью согласен с вами. К сожалению, я никогда не нашел идеального решения для ситуации, которую вы описали (поэтому я буду внимательно следить за этим вопросом). Возможно, вы могли бы использовать что-то вроде xframe для создания документации из xsd:documentation, но это не отвечает на вопрос.

Ответ 2

Это невозможно с помощью эталонной реализации JAXB. Даже если вы попытаетесь написать плагин XJC, вы обнаружите, что API-интерфейс плагина не имеет никакого отношения к определению схемы, поэтому нет способа извлечь эту информацию.

Нашей единственной надеждой является то, что будущая версия JAXB исправляет ситуацию. Здесь откройте запрос функции здесь.

Ответ 3

Я считаю, что следующие методы очень хорошо работают для добавления заголовков JavaDoc в классы Java-классов (сгенерированные из XML-схем). Я устанавливаю JavaDoc в теги, определенные в пространстве имен jax-b, вложенные в аннотации схемы xml и теги appinfo. Обратите внимание, что пространство имен jaxb определяет типы тегов документации; Я использую два из них: класс и теги свойств. определенный в следующем пространстве имен: xmlns: jxb = "http://java.sun.com/xml/ns/jaxb"

1) Чтобы документировать класс, я использую тег jaxb "class" в следующей последовательности:

  <xs:complexType name="Structure">
     <xs:annotation>
        <xs:appinfo>
           <jxb:class>
              <jxb:javadoc>
                 Documentation text goes here. Since parsing the schema  
                 into Java involves evaluating the xml, I escape all 
                 the tags I use as follows &lt;p&gt; for <p>.
              </jxb:javadoc>
           </jxb:class>
        </xs:appinfo>
     </xs:annotation>

     .
     .
     .
  </xs:complexType>

2) Чтобы документировать элемент, я использую тег "property" следующим образом:

       <xs:element name="description" type="rep:NamedString">
          <xs:annotation>
             <xs:appinfo>
                <jxb:property>
                   <jxb:javadoc>
                      &lt;p&gt;Documentation goes here.&lt;/p&gt;
                   </jxb:javadoc>
                </jxb:property>
             </xs:appinfo>
          </xs:annotation>
       </xs:element>

3) Я использую тот же набор тегов для атрибутов документа:

      <xs:attribute name="name" type="xs:NCName" use="required">
          <xs:annotation>
             <xs:appinfo>
                <jxb:property>
                   <jxb:javadoc>
                      &lt;p&gt;Documentation goes here.&lt;/p&gt;
                   </jxb:javadoc>
                </jxb:property>
             </xs:appinfo>
          </xs:annotation>
       </xs:attribute>

4) Чтобы документировать выбор, я использую тэг jaxb свойства, и я документирую выбор.

    <xs:choice maxOccurs="unbounded">
          <xs:annotation>
             <xs:appinfo>
                <jxb:property>
                   <jxb:javadoc>
                      &lt;p&gt;Documentation goes here.&lt;/p&gt;
                   </jxb:javadoc>
                </jxb:property>
             </xs:appinfo>
          </xs:annotation>

          <xs:element name="value" type="rep:NamedValue" />
          <xs:element name="list" type="rep:NamedList" />
          <xs:element name="structure" type="rep:NamedStructure" />
       </xs:choice>

Попытка документировать отдельные варианты здесь не удалась, поскольку этот тег создает нетипизированный список.

Ответ 4

Специально для этого случая я написал XJC-плагин xjc-documents-annotation-plugin.

Что он делает: <annotation><documentation> → аннотации классов Java

Сказал, что у нас есть этот объект, описанный в XSD:

<xs:complexType name="CadastralBlock">
    <xs:annotation>
        <xs:documentation>Cadastral quarter</xs:documentation>
    </xs:annotation>
    <xs:sequence>
        <xs:element name="number" type="xs:string">
            <xs:annotation>
                <xs:documentation>Cadastral number</xs:documentation>
            </xs:annotation>
        </xs:element>
</xs:complexType>

Мы запускаем xjc как:

xjc -npa -no-header -d src/main/generated-java/ -p xsd.generated scheme.xsd

И получил класс как (геттеры, сеттеры и любые аннотации опущены для простоты):

public class CadastralBlock {
    protected String number;
}

Но в моем случае я хочу знать, как класс и поля были названы в исходном файле! Так что же делать этот плагин!

Итак, вы получите:

@XsdInfo(name = "Cadastral quarter", xsdElementPart = "<complexType name=\"CadastralBlock\">\n  <complexContent>\n    <restriction base=\"{http://www.w3.org/2001/XMLSchema}anyType\">\n      <sequence>\n        <element name=\"number\" type=\"{http://www.w3.org/2001/XMLSchema}string\"/></sequence>\n      </restriction>\n  </complexContent></complexType>")
public class CadastralBlock {
    @XsdInfo(name = "Cadastral number")
    protected String number;
}

Как пользоваться

Ручной вызов в командной строке

Если вы хотите запустить его вручную, обеспечьте jar-класс с плагином в run classpath и просто добавьте опцию -XPluginDescriptionAnnotation. Fe:

xjc -npa -no-header -d src/main/generated-java/ -p xsd.generated -XPluginDescriptionAnnotation scheme.xsd

Звонок с Java/Groovy

Driver.run(
    [
        '-XPluginDescriptionAnnotation'
        ,'-d', generatedClassesDir.absolutePath
        ,'-p', 'info.hubbitus.generated.test'
        ,'CadastralBlock.xsd'
    ] as String[]
    ,new XJCListener() {...}
)

См. Тестовый XJCPluginDescriptionAnnotationTest для примера.

Используйте от Gradle

С помощью gradle-xjc-plugin:

plugins {
    id 'java'
    id 'org.unbroken-dome.xjc' version '1.4.1' // https://github.com/unbroken-dome/gradle-xjc-plugin
}

...

dependencies {
    xjcClasspath 'info.hubbitus:xjc-documentation-annotation-plugin:1.0'
}

// Results by default in 'build/xjc/generated-sources'
xjcGenerate {
    source = fileTree('src/main/resources') { include '*.xsd' }
    packageLevelAnnotations = false
    targetPackage = 'info.hubbitus.xjc.plugin.example'
    extraArgs = [ '-XPluginDescriptionAnnotation' ]
}

Завершите пример gradle в gradle example -project-gradle проекта.