これが私がこれを行う方法です。
@XmlRootElement // or @XmlTransient if you want to
public class Plural<S> {
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType, final Collection<S> elms) {
P lt = (P) pluralType.newInstance();
lt.singulars = new ArrayList<>(elms);
return lt;
}
protected Collection<S> getSingulars() {
if (singulars == null) {
singulars = new ArrayList<S>();
}
return singulars;
}
private Collection<S> singulars;
}
次に、任意の単数型の必要な複数型を作成できます。すべての単数型に対して複数形のクラスを作成する必要があるのは気に入らないかもしれませんが、特にクライアント開発者に見栄えを良くしたい場合には、非常に役立つ可能性があります。
@XmlRootElement
public class Customers extends Plural<Customer> {
@XmlElement(name = "customer")
public Collection<Customer> getCustomers() {
return getSingulars();
}
}
@XmlRootElement
public class Items extends Plural<Item> {
@XmlElement(name = "item")
public Collection<Item> getItems() {
return getSingulars();
}
}
@XmlRootElement
public class Invoices extends Plural<Invoice> {
@XmlElement(name = "invoice")
public Collection<Invoice> getInvoices() {
return getSingulars();
}
}
@XmlRootElement
public class BrettRyans extends Plural<BrettRyan> {
@XmlElement(name = "brettRyan")
public Collection<BrettRyan> getBrettRyans() {
return getSingulars();
}
}
ブレット・ライアンのコメントによる更新
ここには、完全な機能を備えたソース コードが付属しています。
完全な mavenized プロジェクトは、http: //code.google.com/p/jinahya/source/browse/trunk/com.googlecode.jinahya/stackoverflow/ で確認できます。
プロパティではなくフィールドを使用するように制御する場合、JAXB はセッターを必要としません。
@XmlTransient
public class Plural<S> {
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType) {
return newInstance(pluralType, Collections.<S>emptyList());
}
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType, final Collection<? extends S> singulars) {
try {
final P plural = pluralType.newInstance();
plural.getSingulars().addAll(singulars);
return plural;
} catch (InstantiationException ie) {
throw new RuntimeException(ie);
} catch (IllegalAccessException iae) {
throw new RuntimeException(iae);
}
}
protected Collection<S> getSingulars() {
if (singulars == null) {
singulars = new ArrayList<S>();
}
return singulars;
}
private Collection<S> singulars;
}
@XmlAccessorType(XmlAccessType.NONE)
public class Item {
public static Item newInstance(final long id, final String name) {
final Item instance = new Item();
instance.id = id;
instance.name = name;
return instance;
}
@Override
public String toString() {
return id + "/" + name;
}
@XmlAttribute
private long id;
@XmlValue
private String name;
}
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class Items extends Plural<Item> {
@XmlElement(name = "item")
public Collection<Item> getItems() {
return getSingulars();
}
}
テスト中...
public class ItemsTest {
@Test
public void testXml() throws JAXBException, IOException {
final Items marshallable = Plural.newInstance(Items.class);
for (int i = 0; i < 5; i++) {
marshallable.getItems().add(Item.newInstance(i, "name" + i));
}
for (Item item : marshallable.getItems()) {
System.out.println("marshallable.item: " + item);
}
final JAXBContext context = JAXBContext.newInstance(Items.class);
final Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
marshaller.marshal(marshallable, baos);
baos.flush();
final Unmarshaller unmarshaller = context.createUnmarshaller();
final Items unmarshalled = (Items) unmarshaller.unmarshal(
new ByteArrayInputStream(baos.toByteArray()));
for (Item item : unmarshalled.getItems()) {
System.out.println("unmarshalled.item: " + item);
}
}
}
版画
marshallable.item: 1/name1
marshallable.item: 2/name2
marshallable.item: 3/name3
marshallable.item: 4/name4
unmarshalled.item: 0/name0
unmarshalled.item: 1/name1
unmarshalled.item: 2/name2
unmarshalled.item: 3/name3
unmarshalled.item: 4/name4
Brett Ryan の 2 回目のコメントによる更新
@Test
public void testXsd() throws JAXBException, IOException {
final JAXBContext context = JAXBContext.newInstance(Items.class);
context.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(final String namespaceUri,
final String suggestedFileName)
throws IOException {
return new StreamResult(System.out) {
@Override
public String getSystemId() {
return "noid";
}
};
}
});
}
Plural
で注釈を付けた場合@XmlRootElement
。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="items" type="items"/>
<xs:element name="plural" type="plural"/>
<xs:complexType name="items">
<xs:complexContent>
<xs:extension base="plural">
<xs:sequence>
<xs:element name="item" type="item" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="plural">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="item">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:long" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
Plural
で注釈を付けた場合@XmlTransient
。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="items" type="items"/>
<xs:complexType name="items">
<xs:sequence>
<xs:element name="item" type="item" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="item">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:long" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>