The original reason for my Jaxb Question
JaxB reference resolving
was that I couldn’t get the same issue working with the simple-framework:
http://old.nabble.com/Two-Phase-support-for-CycleStrategy–td34802791.html
Today I got the things working with a persister call back to the same point as in my Jaxb Questions:
I get copies – not references. Again I am looking for a solution with proper references. This time for the Simple XML framework.
The example here has the base class “ModelElement” not Person as in the other question. Otherwise the problem is the same.
Again I am calling the unmarshalling twice to get all ids in PASS 1 and use the gathered results from the lookup HashMap created in PASS2.
What would be a solution to get proper references? My assumption is that adding a call back that actually lets the called function modify the unmarshalling result (see How to use an output parameter in Java? for a wrapping approach)
would do the trick (comparable to the JaxB solution I have posted in the meantime).
Persister serializer = new Persister();
ModelElementSimpleXmlImpl.lookup.clear();
serializer.read(result, xml);
System.err.println("PASS 2");
serializer.read(result, xml);
This code is from the ModelElementSimpleXmlImpl base class:
…
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);
}
}
}
Niall Gallagher suggested:
Should be fairly easy to do with something like the CycleStrategy. Just create MyCycleStrategy and where there is an exception with “Invalid reference” just return null and remember the reference. When you have picked up all the ids and the values then do a second pass. In the second pass assign the value to the first occurrence of either the ref or the id. Then all following references should be given the same value. This should work.
And he is right. The following extended Cycle Strategy works as proposed: