Повторное использование классов JAXB для похожих XML-схем - PullRequest
0 голосов
/ 27 июня 2019

У меня есть следующие XML, для каждого из XML у меня есть соответствующие классы Java, смоделированные с помощью JAXB.

XML 1:

<counts at="2019-06-27 09:54:31">
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <count id="1" value="1" at="2019-06-27 09:54:31" duration="5"/>
        <count id="2" value="2" at="2019-06-27 09:54:31" duration="5"/>
        <count id="3" value="3" at="2019-06-27 09:54:31" duration="5"/>
    </media>
</counts>

XML 2:

<tags at="2019-06-27 09:54:31">
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <tag id="1" value="1" at="2019-06-27 09:54:31" visible="true" />
        <tag id="2" value="2" at="2019-06-27 09:54:31" visible="true" />
        <tag id="3" value="3" at="2019-06-27 09:54:31" visible="true" />
    </media>
</tags>

XML 3:

<trajectories at="2019-06-27 09:54:31">
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <trajectory id="1" value="1" at="2019-06-27 09:54:31" />
        <trajectory id="2" value="2" at="2019-06-27 09:54:31" />
        <trajectory id="3" value="3" at="2019-06-27 09:54:31" />
    </media>
</trajectories>

Поскольку большинство элементов во всех XML-файлах более или менее одинаковы, за исключением <count>, <tag> and <trajectory>. Есть ли способ абстрагировать классы для <counts>, <tags>, <trajectories> and <media>?

В идеале я бы хотел что-то вроде:

class CountsTagsTrajectories<T extends CommonObjectsOfMedia> {
    private Media<T> media;
}


class Media<T> {
    private List<T> listOfObjects;
}

class Count extends CommonObjectsOfMedia {
    ...
    ...
    ...
}

class Tag extends CommonObjectsOfMedia {
    ...
    ...
    ...
}

class Trajectory extends CommonObjectsOfMedia {
    ...
    ...
    ...
}

Возможен ли такой подход? Или я должен был бы иметь классы как:

Counts > CountMedia > Count
Tags > TagMedia > Tag
Trajectories > TrajectoryMedia > Trajectory

Проблема, с которой я сейчас пытаюсь абстрагировать классы, заключается в том, что мне нужно определить имя в @XmlElement, будь то счетчик / счетчик, теги / тег или траектории / траектория.

ПРИМЕЧАНИЕ: я видел эту запись , но она добавляет список всех возможных «CommonObjectsOfMedia» в класс Media, а это не то, что я ищу.

1 Ответ

2 голосов
/ 27 июня 2019

Вы на правильном пути. Есть две точки, где вы можете улучшить.

  1. Структура медиа имеет теги, траекторию и количество, которые почти одинаковы и используют разные имена. Мы можем справиться с этим:

Сначала у вас есть CommonObjectsOfMedia

@XmlAccessorType(XmlAccessType.FIELD)
public class CommonObjectsOfMedia {

    @XmlAttribute
    private String id;
    @XmlAttribute
    private String value;
    @XmlAttribute
    private String at;

}

Тогда тег внутри носителя имеет дополнительный атрибут от общего. Это будет выглядеть так:

@XmlAccessorType(XmlAccessType.FIELD)
public class MediaTag extends CommonObjectsOfMedia {

    @XmlAttribute
    private boolean visible;
}

Аналогично для подсчета:

@XmlAccessorType(XmlAccessType.FIELD)
public class MediaCount extends  CommonObjectsOfMedia {

    @XmlAttribute
    private String duration;
}

и траектория имеет только общее.

Теперь давайте создадим класс Media, который сможет обрабатывать любые их случаи. Магия от @XmlElements.

@XmlAccessorType(XmlAccessType.FIELD)
public class Media {

    @XmlAttribute
    private String id;
    @XmlAttribute
    private String start;
    @XmlAttribute
    private String finish;
    @XmlAttribute
    private String timeZone;

    @XmlElements ({
        @XmlElement(name="tag", type = MediaTag.class),
        @XmlElement(name="trajectory", type = CommonObjectsOfMedia.class),
        @XmlElement(name="count", type = MediaCount.class),
    })
    private List<CommonObjectsOfMedia> commonObjectsOfMedia;
}

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

<someroot at="2019-06-27 09:54:31">
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <tag id="1" value="1" at="2019-06-27 09:54:31" visible="true" />
        <tag id="2" value="2" at="2019-06-27 09:54:31" visible="true" />
        <tag id="3" value="3" at="2019-06-27 09:54:31" visible="true" />
    </media>
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <trajectory id="1" value="1" at="2019-06-27 09:54:31" />
        <trajectory id="2" value="2" at="2019-06-27 09:54:31" />
        <trajectory id="3" value="3" at="2019-06-27 09:54:31" />
    </media>
    <media id="1" start="1" finish="1000" timeZone="NZST">
        <count id="1" value="1" at="2019-06-27 09:54:31" duration="5"/>
        <count id="2" value="2" at="2019-06-27 09:54:31" duration="5"/>
        <count id="3" value="3" at="2019-06-27 09:54:31" duration="5"/>
    </media>
</someroot>

и корневой класс вот так:

@XmlRootElement
public class Someroot {

    @XmlElement
    private List<Media> media;
}

Это будет отменено правильно. И мы переходим к пункту 2.

Корни имеют другое имя, но одинаковую структуру внутри. Может быть, вы тоже хотите это исправить. Это можно сделать, как показано в этом ответе: Может ли JAXB обрабатывать несколько «корневых» элементов?

...