Java XSD - использование настраиваемого типа коллекции

Моя проблема

Я использую плагин jaxb2 maven для преобразования моих объектов, определенных XSD, в классы Java. Моя цель - установить элемент типа списка в моем XSD (например, xs:choice unbound) в LinkedList вместо использования типа ArrayList по умолчанию. Я использую jaxb-xew-plugin версии 1.10. Вот мой соответствующий код:

XSD:

      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           jaxb:version="2.0"
           xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
           xmlns:xew="http://github.com/jaxb-xew-plugin"
           jaxb:extensionBindingPrefixes="xew"
           elementFormDefault="qualified">


    <xs:element name="TEST">
        <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
                <xs:element ref="action"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>



    <xs:element name="action">
        <xs:complexType>
            <xs:annotation>
                <xs:appinfo>
                    <xew:xew collection="java.util.LinkedList"
                             collectionInterface="java.util.List"
                             instantiate="lazy"
                             plural="true"/>
                </xs:appinfo>
            </xs:annotation>
            <xs:sequence>
                <xs:element name="order" type="xs:nonNegativeInteger"/>
                <xs:choice maxOccurs="unbounded">
                    <xs:element name="x" type="xs:token"/>
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

ПОМ:

          <build>
        <resources>
            <resource>
                <directory>src/main/xsd</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>2.5.0</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                        <configuration>
                            <sources>src/main/xsd</sources>
                            <packageName>com.tug.data.model.gen</packageName>
                            <verbose>true</verbose>
                            <clearOutputDir>false</clearOutputDir>
                            <extension>true</extension>
                            <arguments>
                                <argument>-Xsetters</argument>
                                <argument>-Xxew</argument>
                                <argument>-Xfluent-api</argument>
                                <argument>-Xjaxbindex</argument>
                                <argument>-Xequals</argument>
                                <argument>-XhashCode</argument>
                                <argument>-XtoString</argument>
                                <argument>-Xcopyable</argument>
                                <argument>-Xmergeable</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>com.github.jaxb-xew-plugin</groupId>
                        <artifactId>jaxb-xew-plugin</artifactId>
                        <version>1.10</version>
                    </dependency>
                    <dependency>
                        <groupId>net.java.dev.jaxb2-commons</groupId>
                        <artifactId>jaxb-fluent-api</artifactId>
                        <version>2.1.8</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>0.12.0</version>
                    </dependency>
                </dependencies>
            </plugin>

Сгенерированный в результате код Java

      @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "action"
})
@XmlRootElement(name = "TEST")
public class TEST implements Cloneable, CopyTo2, Equals2, HashCode2, MergeFrom2, ToString2
{

    @XmlElement(required = true)
    protected List<Action> action;

    public List<Action> getAction() {
        if (action == null) {
            action = new ArrayList<Action>(); // <--- **This should have been LinkedList**
        }
        return this.action;
    }

Как видите, ArrayList Тип все еще выходит вместо LinkedList. На самом деле кажется, что xew аргументы и команды полностью игнорируются ... Я не получаю ошибок

Я пробовал много вариантов этого, копируя и вставляя xs:annotationаннотацию почти во всех комбинациях локаций, которые я мог придумать. Единственная ошибка, которую я получаю, здесь:

          <xs:element name="TEST">
        <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
                <xs:element ref="action">
                    <xs:annotation>
                        <xs:appinfo>
                            <xew:xew collection="java.util.LinkedList"
                                     collectionInterface="java.util.List"
                                     instantiate="lazy"
                                     plural="true"/>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

Эта комбинация приводит к: com.sun.istack.SAXParseException2: compiler was unable to honor this xew customization. It is attached to a wrong place, or its inconsistent with other bindings.

Видите ли вы какой-либо пропущенный шаг, который может привести к тому, что моя пользовательская коллекция не будет переопределена?

Я приложил вывод отладки maven, это много, чтобы просмотреть, и я не улавливаю там никаких подсказок. mvn-debug.log

Или же...

Есть ли другой способ использовать настраиваемый тип списка при создании моих объектов Java из XSD?

(PS. Я разместил это в разделе github для jaxb-xew-plugin, однако я понял, что последняя фиксация была более двух лет назад, поэтому это может быть бездействующий проект. Публикация здесь для помощи в сообществе SOF)

2 ответа

Вам необходимо настроить привязки JAXB. Итак, в каталоге вашего проекта скажем src/main/xjb, создайте такой файл (остерегайтесь collectionType):

      <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb">
 <jxb:globalBindings collectionType="java.util.Linkedlist"/>
</jxb:bindings>

Затем используйте его в конфигурации плагина jaxb2 maven в своем POM:

      ...
<configuration>
 <sources>src/main/xsd</sources>
 <xjbSources>
  <xjbSource>src/main/xjb</xjbSource>
 </xjbSources>
...
</configuration>
...

В рамках предоставленного вами XSD настройка имеет смысл. Вы должны понимать роль плагина Xew: если тип A имеет какое-то поле, которое является сложным, как тип TEST в нашем примере, тогда у нас есть "матроска" A→TEST→List, и в этом случае плагин пытается удалить тип TEST из модель. Теперь вы предоставили в своем примере только ТЕСТ, это только половина дела, плагин в этом случае ничего не делает. Вам также необходимо предоставить другой тип A, который использует TEST, например:

      <xs:element name="A">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="TEST">
                <xs:annotation>
                    <xs:appinfo>
                        <xew:xew collection="java.util.LinkedList"
                                 collectionInterface="java.util.List"
                                 instantiate="lazy"
                                 plural="true"/>
                    </xs:appinfo>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="TEST">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="action" type="xs:token" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

И именно здесь включается плагин. Вы увидите на выходе:

      [INFO] Modifications:
[INFO]     Replacing field [TEST com.tug.data.model.gen.A#test]
[INFO]     1 modification(s) to original code.
[INFO]
[INFO] Deletions:
[INFO]     Removing class com.tug.data.model.gen.TEST from package com.tug.data.model.gen
[INFO]     Removing factory method [com.tug.data.model.gen.TEST#createTEST()] from com.tug.data.model.gen.ObjectFactory
[INFO]     2 deletion(s) from original code.

и результирующий класс будет (я удалил несвязанный персонал):

      @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "tests"
})
@XmlRootElement(name = "A")
public class A implements Cloneable, CopyTo2, Equals2, HashCode2, MergeFrom2, ToString2
{

    @XmlElementWrapper(name = "TEST", required = true)
    @XmlElement(name = "action")
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    protected List<String> tests;

    public List<String> getTESTS() {
        if (tests == null) {
            tests = new LinkedList<String>();
        }
        return tests;
    }

    public void setTESTS(List<String> tests) {
        this.tests = tests;
    }

    public A withTESTS(String... values) {
        if (values!= null) {
            for (String value: values) {
                getTESTS().add(value);
            }
        }
        return this;
    }

    public A withTESTS(Collection<String> values) {
        if (values!= null) {
            getTESTS().addAll(values);
        }
        return this;
    }

    public A withTESTS(List<String> tests) {
        setTESTS(tests);
        return this;
    }

    ...
}

и вот где LinkedList всплывает.

Таким образом, плагин не изменяет тип ТЕСТА. По сути, политика будет «удалить или оставить в покое». Если вы хотите настроить тип TEST самостоятельно, вам необходимо использовать собственный набор настроек JAXB collectionType:

      <?xml version="1.0" encoding="UTF-8" ?>
<xs:schema jaxb:version="2.0"
           xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">

    <xs:element name="TEST">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="action" type="xs:token" minOccurs="0" maxOccurs="unbounded">
                    <xs:annotation>
                        <xs:appinfo>
                            <jaxb:property collectionType="java.util.LinkedList" />
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
Другие вопросы по тегам