Reputation: 563
I have the following XMLs, for each of the XML I have the corresponding Java classes modeled with 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>
Since most of the elements in all the XMLs are more or less the same except for <count>, <tag> and <trajectory>
.
Is there a way to abstract the classes for <counts>, <tags>, <trajectories> and <media>
?
Ideally, I would like something like:
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 {
...
...
...
}
Is this approach possible? Or I would have to have classes like:
Counts > CountMedia > Count
Tags > TagMedia > Tag
Trajectories > TrajectoryMedia > Trajectory
The problem that I am facing right now trying to abstract the classes is that I need to define a name in @XmlElement, whether it is counts/count, tags/tag or trajectories/trajectory.
NOTE: I've seen this post but what it does is to add a list of all the possible "CommonObjectsOfMedia" to the Media class and that's not what I am looking for.
Upvotes: 0
Views: 163
Reputation: 2975
You are on the right path. There are two points where you can improve.
First as you have the CommonObjectsOfMedia
@XmlAccessorType(XmlAccessType.FIELD)
public class CommonObjectsOfMedia {
@XmlAttribute
private String id;
@XmlAttribute
private String value;
@XmlAttribute
private String at;
}
Then tag inside media has an extra attribute from the common. That would look like:
@XmlAccessorType(XmlAccessType.FIELD)
public class MediaTag extends CommonObjectsOfMedia {
@XmlAttribute
private boolean visible;
}
Similar for count:
@XmlAccessorType(XmlAccessType.FIELD)
public class MediaCount extends CommonObjectsOfMedia {
@XmlAttribute
private String duration;
}
and trajectory only has the common.
Now lets create the Media class that will be able to handle any case of them. The magic is from @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;
}
I will create a demo class that will show the unmarshalling of all the cases at the same time. The xml would look like this:
<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>
and the root class like this:
@XmlRootElement
public class Someroot {
@XmlElement
private List<Media> media;
}
This will unmarshall properly. And we go to item 2.
The roots have different name but same structure inside. Maybe you want to fix this too. This can be done as shown in this reply: Can JAXB handle multiple "root" elements?
Upvotes: 2