2012-12-18 101 views
3

當初之所以我JAXB問題 JaxB reference resolving簡單 - XML參考解決

的是,我無法得到同樣的問題,用簡單的框架工作:

http://old.nabble.com/Two-Phase-support-for-CycleStrategy--td34802791.html

今天我得到了與持久性有機污染物的工作回調到我的Jaxb問題中的相同點: 我得到副本 - 未提及。再次,我正在尋找適當的參考解決方案。這次是簡單的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); 
      } 
     } 
    } 

回答

2

尼爾·加拉格爾建議:

應該是相當容易的東西,如CycleStrategy做。只需創建MyCycleStrategy,並在出現「Invalid reference」異常的情況下,返回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; 
    } 

}