このカスタム IDResolver を作成しました。
final class MyIDResolver extends IDResolver {
Map<String, Course> courses = new HashMap<>();
/**
* @see com.sun.xml.bind.IDResolver#bind(java.lang.String, java.lang.Object)
*/
@Override
public void bind(String id, Object obj) throws SAXException {
if (obj instanceof Course)
courses.put(id, (Course)obj);
else
throw new SAXException("This " + obj.toString() + " cannot found");
}
/**
* @see com.sun.xml.bind.IDResolver#resolve(java.lang.String, java.lang.Class)
*/
@Override
public Callable<?> resolve(final String id, final Class targetType) throws SAXException {
return new Callable<Object>() {
@Override
public Object call() throws Exception {
if (targetType == Course.class)
return courses.get(id);
else
throw new ClassNotFoundException(targetType.toString() + " cannot found");
}
};
}
}
そして、次のような2つのクラスがあります。
@XmlRootElement(name = "course")
public class Course {
@XmlID
@XmlAttribute
private String id;
@XmlAttribute
private int units;
@XmlAttribute
private Level level;
@XmlAttribute
private String name;
@XmlIDREF
@XmlElement(name = "pre")
private ArrayList<Course> prerequisite;
@XmlIDREF
@XmlElement(name = "co")
private ArrayList<Course> corequisite;
}
@XmlRootElement(name = "dept")
@XmlAccessorType(XmlAccessType.FIELD)
public final class Department {
@XmlAttribute
private String name;
@XmlElementWrapper(name = "courses")
@XmlElement(name = "course")
private ArrayList<Course> courses;
}
そして、次のような XML のサンプル:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<dept name="ece">
<courses>
<course id="1" units="4" level="UNDERGRADUATE" name="Fundamentals of Programming"/>
<course id="2" units="3" level="UNDERGRADUATE" name="Advanced Programming">
<pre>1</pre>
</course>
</courses>
</dept>
そして、このような単純なメイン:
unmarshaller.unmarshal(new FileReader(arg0))
context = JAXBContext.newInstance(Department.class);
unmarshaller = context.createUnmarshaller();
unmarshaller.setProperty(IDResolver.class.getName(), new MyIDResolver());
カスタム IDResolver の resolve() メソッドは、Object.class を targetType として取得します。ただし、Course.class である必要があります。これにより、間違った ID 解決が発生します。私の問題はどこですか?