跟进JAXB and Composite Pattern,我设法映射:
<precondition>
<or>
<and>
<just><query>foo</query></just>
<just><query>bar</query></just>
</and>
<just><query>baz</query></just>
</or>
</precondition>
但我想映射:
<precondition>
<or>
<and>
<query>foo</query>
<query>bar</query>
</and>
<query>baz</query>
</or>
</precondition>
我的JAXB类层次结构如下:
@XmlRootElement
@XmlSeeAlso({SimplePreconditionQuery.class, CompoundAndPreconditionQuery.class, CompoundOrPreconditionQuery.class})
public abstract class PreconditionQuery {
// JAXB does not deal with interfaces by default >:(
}
有几种查询:
@XmlSeeAlso(PreconditionQuery.class)
@XmlRootElement(name = "just")
public class SimplePreconditionQuery extends PreconditionQuery {
private String query;
@XmlElement(name = "query")
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
}
化合物(AND / OR)非常相似:
@XmlSeeAlso(PreconditionQuery.class)
@XmlRootElement(name = "and")
public class CompoundAndPreconditionQuery extends PreconditionQuery {
private Collection<PreconditionQuery> preconditionQueries = newArrayList();
@XmlElementRef(name = "query")
public Collection<PreconditionQuery> getPreconditionQueries() {
return preconditionQueries;
}
public void setPreconditionQueries(Collection<PreconditionQuery> preconditionQueries) {
this.preconditionQueries = preconditionQueries;
}
}
封闭的豆子:
public class Precondition {
private PreconditionQuery query;
@XmlElementRef(required = true)
public PreconditionQuery getQuery() {
return query;
}
public void setQuery(PreconditionQuery query) {
this.query = query;
}
}
JAXB不允许我在@XmlValue
上映射SimplePreconditionQuery
。为什么和有什么替代方案?
答案 0 :(得分:4)
如果您只是这样做:
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "query")
public class SimplePreconditionQuery extends PreconditionQuery {
private String query;
@XmlValue
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
}
您将收到以下异常,因为SimplePreconditionQuery
是java.lang.Object
以外的其他内容。
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
@XmlValue is not allowed on a class that derives another class.
this problem is related to the following location:
at public java.lang.String forum26714143.SimplePreconditionQuery.getQuery()
at forum26714143.SimplePreconditionQuery
at @javax.xml.bind.annotation.XmlSeeAlso(value=[class forum26714143.SimplePreconditionQuery, class forum26714143.CompoundAndPreconditionQuery, class forum26714143.CompoundOrPreconditionQuery])
at public forum26714143.PreconditionQuery forum26714143.Precondition.getQuery()
at forum26714143.Precondition
PreconditionQuery
。我们可以在类级别使用@XmlTransient
注释从JAXB中删除该类。超类中的所有属性都将被视为超类的属性。
import javax.xml.bind.annotation.*;
@XmlSeeAlso({SimplePreconditionQuery.class, CompoundAndPreconditionQuery.class, CompoundOrPreconditionQuery.class})
@XmlTransient
public abstract class PreconditionQuery {
// JAXB does not deal with interfaces by default >:(
}
现在我们得到以下异常:
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "class forum26714143.PreconditionQuery" or any of its subclasses are not known to this context.
this problem is related to the following location:
at public forum26714143.PreconditionQuery forum26714143.Precondition.getQuery()
at forum26714143.Precondition
现在我们已经从JAXB所关注的类集中删除了PreconditionQuery
,现在我们可以从它包含的@XmlSeeAlso
注释中获益。因此,我们需要使@XmlElementRef
注释更明确:
<强>前提条件强>
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Precondition {
private PreconditionQuery query;
@XmlElementRefs({
@XmlElementRef(name="and", type = CompoundAndPreconditionQuery.class),
@XmlElementRef(name="or", type= CompoundOrPreconditionQuery.class),
@XmlElementRef(name="query", type=SimplePreconditionQuery.class)
})
public PreconditionQuery getQuery() {
return query;
}
public void setQuery(PreconditionQuery query) {
this.query = query;
}
}
<强> CompoundAndPreconditionQuery 强>
您还需要为CompoundAndPreconditionQuery
和CompoundAndPreconditionQuery
执行此操作。
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "and")
public class CompoundAndPreconditionQuery extends PreconditionQuery {
private Collection<PreconditionQuery> preconditionQueries = new ArrayList();
@XmlElementRefs({
@XmlElementRef(name="and", type = CompoundAndPreconditionQuery.class),
@XmlElementRef(name="or", type= CompoundOrPreconditionQuery.class),
@XmlElementRef(name="query", type=SimplePreconditionQuery.class)
})
public Collection<PreconditionQuery> getPreconditionQueries() {
return preconditionQueries;
}
public void setPreconditionQueries(Collection<PreconditionQuery> preconditionQueries) {
this.preconditionQueries = preconditionQueries;
}
}
// JAXB默认不处理接口&gt; :(
现在JAXB已不再了解Precondition
查询类,如果您愿意,可以将其设为接口。
public interface PreconditionQuery {
}