我的Jaxb问题的原因 JaxB reference resolving
是我在使用简单框架时遇到了同样的问题:
http://old.nabble.com/Two-Phase-support-for-CycleStrategy--td34802791.html
今天,我通过持久性调用回复了与Jaxb问题相同的观点: 我得到副本 - 不是引用。我再次寻找一个有适当参考的解决方案。这次是Simple XML框架。
这里的示例在另一个问题中具有基类“ModelElement”而不是Person。否则问题是一样的。
我再次调用两次解组来获取PASS 1中的所有ID并使用在PASS2中创建的查找HashMap的收集结果。
获得适当参考的解决方案是什么?我的假设是添加一个实际上允许被调用函数修改解组结果的回调(有关包装方法,请参阅How to use an output parameter in Java?) 会做的伎俩(与我在此期间发布的JaxB解决方案相比)。
Persister serializer = new Persister();
ModelElementSimpleXmlImpl.lookup.clear();
serializer.read(result, xml);
System.err.println("PASS 2");
serializer.read(result, xml);
此代码来自ModelElementSimpleXmlImpl基类: ...
protected String ref;
/**
* getter for xsd:string/String id
* @return id
*/
@org.simpleframework.xml.Attribute(name="ref",required=false)
public String getRef() {
return ref;
}
/**
* setter for xsd:string/String id
* @param pid - new value for id
*/
@org.simpleframework.xml.Attribute(name="ref",required=false)
public void setRef(String pRef) {
ref=pRef;
}
private boolean debug=true;
/**
* show debug information
* @param title
* @param key
* @param me
* @param found
*/
public void showDebug(String title,String key,ModelElementSimpleXmlImpl me, ModelElementSimpleXmlImpl found) {
String deref="?";
if (found!=null)
deref="->"+found.getId()+"("+found.getClass().getSimpleName()+")";
if (debug)
System.err.println(title+": "+key+"("+me.getClass().getSimpleName()+")"+deref+" - "+this);
}
/**
* keep track of the elements already seen
*/
public static Map<String,ModelElementSimpleXmlImpl> lookup=new HashMap<String,ModelElementSimpleXmlImpl>();
@Validate
public void validate() {
ModelElementSimpleXmlImpl me=this;
String key=me.getId();
if (key!=null) {
showDebug("id",key,me,null);
lookup.put(key, me);
}
key=me.getRef();
if (key!=null) {
if (lookup.containsKey(key)) {
ModelElementSimpleXmlImpl meRef=lookup.get(key);
showDebug("ref",key,me,meRef);
me.setRef(null);
me.copyFrom(meRef);
} else {
if (debug)
showDebug("ref",me.getRef(),me,null);
}
}
}
答案 0 :(得分:2)
Niall Gallagher建议:
使用CycleStrategy之类的东西应该相当容易。只需创建MyCycleStrategy,如果出现“无效引用”的异常,则返回null并记住引用。当您拾取所有ID和值后,再进行第二次传递。在第二遍中,将值分配给ref或id的第一个匹配项。然后,所有后面的引用应该被赋予相同的值。这应该有效。
他是对的。以下扩展周期策略的工作原理如下:
/**
* Two Path Cycle Strategy
*
* @author wf
*
*/
public static class TwoPathCycleStrategy extends CycleStrategy {
String id;
String ref;
public static boolean debug = false;
/**
* create a twoPath Cycle Strategy
*
* @param id
* @param ref
*/
public TwoPathCycleStrategy(String id, String ref) {
super(id, ref);
this.id = id;
this.ref = ref;
}
/**
* show debug information
*
* @param title
* @param key
* @param value
*/
public void showDebug(String title, String key, Value value) {
if (debug) {
String id = "?";
Object v = value;
while ((v instanceof Value) && ((Value) v).isReference()) {
v = ((Value) v).getValue();
}
if (v == null) {
id = "null";
} else {
// FIXME - adapt to your code or comment out
//if (v instanceof ModelElement) {
// ModelElement me = (ModelElement) v;
// id = me.getId();
//}
}
System.err.println(title + ":" + key + "->"
+ v.getClass().getSimpleName() + ":"
+ value.getType().getSimpleName() + ":" + value.isReference() + ":"
+ id);
}
}
public Map<String, Value> lookup = new HashMap<String, Value>();
@SuppressWarnings("rawtypes")
@Override
public Value read(Type type, NodeMap node, Map map) throws Exception {
Value value = null;
Node refNode = node.get(ref);
Node keyNode = node.get(id);
try {
value = super.read(type, node, map);
if (keyNode != null) {
String key = keyNode.getValue();
if (value != null) {
showDebug("id", key, value);
lookup.put(key, value);
} else {
showDebug("id?", key, value);
}
}
} catch (CycleException ce) {
if (ce.getMessage().contains("Invalid reference")) {
if (refNode != null) {
String key = refNode.getValue();
if (lookup.containsKey(key)) {
value = lookup.get(key);
showDebug("ref", key, value);
} else {
showDebug("ref?",key,null);
}
}
} else {
throw ce;
}
}
return value;
}
}