属性値に基づいて、JAXB Bean をサブクラスにアンマーシャリングしたいと考えています。
MOXyはそれを行うことができます:
@XmlDiscriminatorNode("@type")
public static class ActionDef extends ContainerOfStackableDefs { ... }
@XmlDiscriminatorValue("cli")
public static class CliActionDef extends ActionDef {
/** CLI command. EL. */
@XmlAttribute public String command;
}
ただし、 にはJAXBContext
指定されたすべてのクラスが必要です。「ルート」クラス以外の場所で定義するのはちょっと不快です。
私は次のようなことを望んでいました:
@XmlDiscriminatorNode("@type")
@XmlSubClasses({ CliActionDef.class, XsltActionDef.class, ... })
public static class ActionDef extends ContainerOfStackableDefs { ... }
私は s に入りたくありませんXmlAdapter
。これは簡単な作業であり、簡単な解決策が必要です。
仕様またはMOXy拡張のいずれかで、ルートクラスのサブクラスを単純にリストするために使用できるものはありますか?
それ以外の場合は、Jandex を使用してサブクラスを自動的に見つけようとしています。結局、MOXyもそれを行うことができました;-)
更新:記録のために、私は得ていました
Descriptor: XMLDescriptor(org.jboss.loom.migrators._ext.MigratorDefinition$ActionDef --> [])
at org.eclipse.persistence.exceptions.DescriptorException.missingClassIndicatorField(DescriptorException.java:957)
...
要するに: の名前と同じ名前のプロパティへの MOXy アンマーシャリングを行わないでください@XmlDiscriminatorNode("@name")
。もしそうなら、それを持って@XmlReadOnly
いて、クラスの抽象を持っていません。
更新:まだうまくいきません。私は基本クラスを取得し続けます。JDK の impl ではなく、MOXy によって処理されます。
私のコード:
<action type="xslt" var="addAction" ...>
</action>
<action type="manual">
...
</action>
豆:
//@XmlRootElement
@XmlDiscriminatorNode("@type")
@XmlSeeAlso({ CliActionDef.class, ModuleActionDef.class, CopyActionDef.class, XsltActionDef.class })
public static class ActionDef extends ContainerOfStackableDefs {
//@XmlAttribute
//@XmlReadOnly
public String typeVal; // Was type, caused an exception.
//public List<PropertyBean> properties;
//@XmlAnyAttribute
public Map<String, String> attribs = new HashMap();
}
@XmlRootElement
@XmlDiscriminatorValue("manual")
public static class ManualActionDef extends ActionDef {
}
public static class FileBasedActionDef extends ActionDef {
/** Path mask. Ant-like wildcards, EL. */
@XmlAttribute public String pathMask;
/** Where to store the result. May be a dir or a file. EL. */
@XmlAttribute public String dest;
}
@XmlRootElement
@XmlDiscriminatorValue("xslt")
public static class XsltActionDef extends FileBasedActionDef {
/** XSLT template path. */
@XmlAttribute public String xslt;
}
どうしたの?
アップデート:
@XmlDiscriminatorNode("@type") を最上位の classContainerOfStackableDefs
に配置すると、次のようになります。
Exception Description: Missing class for indicator field value [manual] of type [class java.lang.String].
Descriptor: XMLDescriptor(org.jboss.loom.migrators._ext.MigratorDefinition$ActionDef --> [])
at org.eclipse.persistence.exceptions.DescriptorException.missingClassForIndicatorFieldValue(DescriptorException.java:938)
at org.eclipse.persistence.internal.oxm.QNameInheritancePolicy.classFromRow(QNameInheritancePolicy.java:264)
要するに:欠落してjava.lang.String
います。:-o 解ける?
また、最も単純なテスト ケースを作成しました。
public class JaxbInheritanceTest {
@Test
public void testUnmarshall() throws JAXBException{
final Unmarshaller marshaller = XmlUtils.createJaxbContext(Root.class).createUnmarshaller();
Root root = (Root) marshaller.unmarshal( new StringReader(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root><sub disc=\"foo\"/><sub disc=\"bar\"/></root>") );
boolean rightClass = (DiscFoo.class.isAssignableFrom( root.subs.get(0).getClass() ));
Assert.assertTrue( "base elements go into subclasses", rightClass );
rightClass = (DiscBar.class.isAssignableFrom( root.subs.get(1).getClass() ));
Assert.assertTrue( "base elements go into subclasses", rightClass );
}
@XmlRootElement
public static class Root {
@XmlElement(name = "sub")
List<Base> subs;
}
@XmlDiscriminatorNode("@disc")
@XmlSeeAlso({DiscFoo.class, DiscBar.class})
public static abstract class Base {}
@XmlRootElement @XmlDiscriminatorValue("foo")
public static class DiscFoo {}
@XmlRootElement @XmlDiscriminatorValue("bar")
public static class DiscBar {}
}
しかし、これも私に 2x を与えますBase
。これは MOXy によって処理されます - デバッガーでチェックされます。
ここで何が問題なのですか?