3

Jaxb質問の元の理由 JaxB参照が解決される

単純なフレームワークで同じ問題を処理することができなかったということでした:

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

今日、パーシスターコールで機能するものを、Jaxbの質問と同じポイントに戻しました。参照ではなくコピーを取得します。繰り返しになりますが、適切なリファレンスを備えたソリューションを探しています。今回はSimpleXMLフレームワークです。

この例には、他の質問のようにPersonではなく基本クラス「ModelElement」があります。それ以外の場合、問題は同じです。

ここでも、アンマーシャリングを2回呼び出して、PASS 1のすべてのIDを取得し、PASS2で作成されたルックアップHashMapから収集された結果を使用します。

適切な参照を取得するための解決策は何でしょうか?私の仮定では、呼び出された関数がアンマーシャリングの結果を実際に変更できるようにするコールバックを追加すると(ラッピングアプローチについては、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);
            }
        }
  }
4

1 に答える 1

2

ナイル・ギャラガーは次のように提案しました。

CycleStrategy のようなものを使用すると、かなり簡単に実行できるはずです。MyCycleStrategy を作成するだけで、「無効な参照」の例外がある場合は、null を返し、参照を覚えておいてください。すべての ID と値を取得したら、2 回目のパスを実行します。2 番目のパスでは、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;
    }

}
于 2012-12-20T06:15:26.350 に答える