Внедрение кода JAXB в класс Enum

#java #enums #jaxb #xsd #tostring

#java #перечисления #jaxb #xsd #tostring

Вопрос:

Фоновая проблема заключается в том, что когда мы размышляем о Enum классе, сгенерированном JAXB, toString() вызывается класс, который без @override of toString() вернет .name() вместо .value() . Итак, я хотел бы внедрить свой собственный toString() .

Я не могу внедрить код в класс, созданный Enum JAXB. Хотя я могу вводить код на верхнем уровне complexType , но не в встроенный Enum класс.

Вот раздел рассматриваемого XSD, показанный ниже (я пробовал абсолютный и относительный):

  <jxb:bindings node="/xs:schema/xs:complexType[@name='QueryPgm']/xs:sequence/xs:element[@name='STATUS']/xs:simpleType">
  

Я использую эти аргументы:

 "-verbose -Xinject-code -extension"
  

Ошибок не появляется, и вывод:

 разбор схемы...
 компиляция схемы...
 [ИНФОРМАЦИЯ] генерация кода
неизвестное местоположение
com/ibm/query /pgm/ObjectFactory
com/ibm/query/pgm/QueryPgm
com /ibm/query/pgm/package-info

Вот раздел рассматриваемой схемы:

 <xs:complexType name="QueryPgm">
<xs:sequence>
    <xs:element name="NAME" type="tns:nameOptions" minOccurs="1" maxOccurs="unbounded" />

    <xs:element name="SHOW" minOccurs="0" maxOccurs="unbounded">
        <xs:simpleType>
            <xs:annotation>
                <xs:appinfo>
                    <jxb:typesafeEnumClass name="showOptions"/>
                </xs:appinfo>
            </xs:annotation>
            <xs:restriction base="xs:string">
                <xs:enumeration value="ALL" />
            </xs:restriction>
        </xs:simpleType>
    </xs:element>

    <xs:element name="STATUS" minOccurs="0" maxOccurs="unbounded">
        <xs:simpleType>
            <xs:annotation>
                <xs:appinfo>
                    <jxb:typesafeEnumClass name="statusOptions"/>

                    <jxb:bindings node="/xs:schema/xs:complexType[@name='QueryPgm']/xs:sequence/xs:element[@name='STATUS']/xs:simpleType">
                        <ci:code>
                            @Override
                            public String toString() { return this.value();}
                        </ci:code>
                    </jxb:bindings>
                </xs:appinfo>
            </xs:annotation>

            <xs:restriction base="xs:string">
                <xs:enumeration value="DB-NOTAVL" />
                <xs:enumeration value="IOPREV" />
                <xs:enumeration value="LOCK" />
                <xs:enumeration value="NOTINIT" />
                <xs:enumeration value="STOSCHD" />
                <xs:enumeration value="TRACE" />
            </xs:restriction>
        </xs:simpleType>
    </xs:element>
</xs:sequence>
</xs:complexType>
  

Я был бы признателен за помощь или идеи, которые могут возникнуть. Спасибо.

Комментарии:

1. Существует ли какой-либо сложный тип верхнего уровня с именем QueryPgm ? Если есть, пожалуйста, включите его или вашу полную схему, если это возможно.

2. ОК. Я вижу это сейчас после редактирования.

3. Рад, что вы могли это видеть; если бы не было QueryPgm, я бы получил сообщение о том, что узел документа не существует или аналогичная ошибка. К сожалению, я получаю чистый запуск, но метод code is toString() не вводится.

4. Вы решили эту проблему?

5. Дэвид, мы не решили эту проблему, у меня есть несколько других идей, которые я добавил к нашему бэклогу, чтобы попробовать, когда позволит время, а пока мы просто вручную вводим функции toString(), это только 2 или 3 места, которые нам нужны для этого, не идеально, но пока это работает.

Ответ №1:

сегодня 25 апреля 2019 года, не уверен, что автор все еще ищет решение такого рода проблем через 5 лет, в любом случае, для тех, кто заботится, отлично работает, чтобы внедрить фрагмент кода в сгенерированный класс enum с помощью jaxb (плагин jvnet). причина в том, что мы пытаемся поддерживать десериализацию xml и json с помощью устаревших классов, созданных jaxb, только с аннотациями xml. таким образом, нам действительно не нужны аннотации json с помощью каких-либо плагинов maven json (вы не можете применять как jaxb, так и плагин json для создания классов с аннотациями json и xml. было бы катастрофой). таким образом, эти устаревшие java-классы, созданные jaxb, могут использоваться для десериализации строк json (приходит ответ). а перечисление name() и value() — это боль. поскольку jaxb перешел на другой сайт с более чем 400 проблемами https://github.com/javaee/jaxb-v2 , большинство из которых даже не находятся в стадии активной разработки или будут исправлены в ближайшее время. итак, я попытался ниже исправить проблему с name() и value(), поэтому при вызове toString() экземпляра Enum вместо имен В ВЕРХНЕМ РЕГИСТРЕ может быть возвращено «реальное значение». ниже приведены некоторые фрагменты кода и информация о плагине:

файл связующего:

 <jaxb:bindings schemaLocation = "locale.xsd" node = "/xs:schema">
    <jaxb:bindings node = "xs:simpleType[@name='localetype']">
        <ci:code>
            <![CDATA[
            @Override
            public String toString() {
            return this.value();
            }
            ]]>
        </ci:code>
    </jaxb:bindings>
</jaxb:bindings>
  

locale.xsd

 <xs:simpleType name="localetype">
    <xs:restriction base="xs:string">
        <xs:enumeration value="en_US"/>
        <xs:enumeration value="de_DE"/>
    </xs:restriction>
</xs:simpleType>
  

main.xsd

 <xs:element name="customLocale" type="localetype"/>
  

плагин maven

 <plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.14.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <schemaDirectory>src/main/resources/schema</schemaDirectory>
        <bindingDirectory>src/main/resources/schema</bindingDirectory>
        <schemaIncludes>
            <include>*.xsd</include>
        </schemaIncludes>
        <forceRegenerate>true</forceRegenerate>
        <removeOldOutput>true</removeOldOutput>
        <verbose>true</verbose>
        <extension>true</extension>
        <args>
            <arg>-Xinject-code</arg>
            <arg>-extension</arg>
            <arg>-XhashCode</arg>
        </args>
        <plugins>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics</artifactId>
                <version>0.6.4</version>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics-annotate</artifactId>
                <version>0.6.4</version>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-default-value</artifactId>
                <version>1.1</version>
            </plugin>
        </plugins>
    </configuration>
</plugin>
  

сгенерированный класс jaxb

 @XmlType(name = "localetype", namespace = "http://www.xxxx.com/ns/datatype")
@XmlEnum
public enum Localetype {

    @XmlEnumValue("en_US")
    EN_US("en_US"),

    @XmlEnumValue("de_DE")
    DE_DE("de_DE"),


    private final String value;

    Localetype(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static Localetype fromValue(String v) {
        for (Localetype c: Localetype.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }


                    @Override
                    public String toString() {
                        return this.value();
                    }    
}
  

тестирование Джексона

 compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
  

конфигурация клиентского кода jackson.

 ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
  

не забывайте об этом:
СЧИТЫВАТЬ_ENUMS_USING_TO_STRING как true (версия jackson 2.x)