<html>
<!--
Copyright (C) 2006 Joe Walnes.
Copyright (C) 2006, 2007, 2009 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
style license a copy of which has been included with this distribution in
the LICENSE.txt file.
Created on 03. April 2006 by Guilherme Silveira
-->
<head>
<title>Object references</title>
</head>
<body>
<!-- ...................................................... -->
<h2 id="references">How does XStream deals with duplicate and circular references?</h2>
<p>It depends on XStream's mode, the default is uses XPath to allow serialized objects to be treated as graphs instead of simple trees (typical XML usage).</p>
<p>Sometimes it's not desirable to work this way, let's take a look in a simple example in order to switch between XStream's modes and see what its capable of.</p>
<p>We start with a simple compact-disc class, with id and a bonus cd fields:</p>
<div class="Source Java"><pre>package com.thoughtworks.xstream;
public class Cd {
private String id;
private Cd bonusCd;
Cd(String id, Cd bonusCd) {
this.id = id;
this.bonusCd = bonusCd;
}
Cd(String id) {
this.id = id;
}
public String getId() {
return id;
}
public Cd getBonusCd() {
return bonusCd;
}
}</pre></div>
<p>And let's create an order with the same cd twice and the order itself, so we can simulate
two references to the same object and a back-reference.</p>
<div class="Source Java"><pre>Cd bj = new Cd("basement_jaxx_singles");
List order = new ArrayList();
// adds the same cd twice (two references to the same object)
order.add(bj);
order.add(bj);
// adds itself (cycle)
order.add(order);
XStream xstream = new XStream();
xstream.alias("cd", Cd.class);
System.out.println(xstream.toXML(order));
</pre></div>
<p>If we execute the above code, XStream's uses its <b>default mode</b> called XPATH_RELATIVE_REFERENCES
based on the W3C XPath specification. Cross and back references are treated in a way that it's (almost) human
readable:</p>
<div class="Source Java"><pre>
<list>
<cd>
<id>maria rita</id>
</cd>
<cd>
<id>basement_jaxx_singles</id>
</cd>
<cd reference="../cd[2]"/>
<list reference=".."/>
</list>
</pre></div>
<p>The second reference to the Basement Jaxx cd was serialized as "../cd[2]" while the order inside
itself used the ".." path. The XPath Relative mode allows any type of graphs to be used as both cross and
back-references are supported.</p>
<p>In order to make use of the XPath Relative mode one can implicitly call:</p>
<div class="Source Java"><pre>
xstream.setMode(XStream.XPATH_RELATIVE_REFERENCES);
</pre></div>
<!-- ...................................................... -->
<h2 id="rel-abs">Relative x Absolute</h2>
<p>There is an absolute mode which is easy to use and understand. It works
using the same XPath specification and also supports all types of graphs.</p>
<div class="Source Java"><pre>
xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);
</pre></div>
<p>The changes in the resulting xml is a little more 'clutter':</p>
<div class="Source Java"><pre>
<list>
<cd>
<id>maria rita</id>
</cd>
<cd>
<id>basement_jaxx_singles</id>
</cd>
<cd reference="/list/cd[2]"/>
<list reference="/list"/>
</list>
</pre></div>
<!-- ...................................................... -->
<h2 id="single-node">Single Node Selectors</h2>
<p>In some cases where the XML is used later on or is generated by someone else, the
XPath selectors can be forced to select always a single node instead of a node list where
the first element is taken. Therefore two more modes exist:</p>
<div class="Source Java"><pre>
xstream.setMode(XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES);
xstream.setMode(XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES);
</pre></div>
<p>The changes in the resulting xml is even more 'clutter':</p>
<div class="Source Java"><pre>
<list>
<cd>
<id>maria rita</id>
</cd>
<cd>
<id>basement_jaxx_singles</id>
</cd>
<cd reference="/list[1]/cd[2]"/>
<list reference="/list[1]"/>
</list>
</pre></div>
<p>For XStream is the notation with the single node selectors absolutely equivalent to the
one without. These two notations are completely transparent at deserialization time.</p>
<!-- ...................................................... -->
<h2 id="ids">Id mode</h2>
<p>Both modes displayed until now are not so easy to write by hand. XStream has another
mode which makes it is easier to read/write by a human being:</p>
<div class="Source Java"><pre>
xstream.setMode(XStream.ID_REFERENCES);
</pre></div>
<p>The result is a XML which generates an "id" attribute for each new object marshaled,
and whenever it finds back or cross-references, it uses a "reference" attribute to so
it doesn't copy the entire object.</p>
<p>In our example, the list has id 1, the Maria Rita cd 2, and the Basement Jaxx 3. Therefore
the cross-reference to our cd should contain a reference attribute to object number 2 and
the back-reference to our order a reference to object 1. The result is:</p>
<div class="Source Java"><pre>
<list id="1">
<cd id="2">
<id>maria rita</id>
</cd>
<cd id="3">
<id>basement_jaxx_singles</id>
</cd>
<cd reference="3"/>
<list reference="1"/>
</list>
</pre></div>
<!-- ...................................................... -->
<h2>No references</h2>
<p>For some uses of XStream we do not desire any kind of back or cross references like a graph, but a simple
tree. The most famous example is when using XStream to generate XML for B2B services.</p>
<p>In such scenarios it's impossible to represent a graph cycle (remember: no tree contains such structure), therefore
we have to remove the last <b>add</b> call from our example:</p>
<div class="Source Java"><pre>Cd bj = new Cd("basement_jaxx_singles");
List order = new ArrayList();
// adds the same cd twice (two references to the same object)
order.add(bj);
order.add(bj);
XStream xstream = new XStream();
xstream.alias("cd", Cd.class);
System.out.println(xstream.toXML(order));
</pre></div>
<p>Now if we add the NO_REFERENCES option, every reference shall be completed serialized.</p>
<div class="Source Java"><pre>
xstream.setMode(XStream.NO_REFERENCES);
</pre></div>
<p>The result are three references:</p>
<div class="Source Java"><pre>
<list>
<cd>
<id>maria rita</id>
</cd>
<cd>
<id>basement_jaxx_singles</id>
</cd>
<cd>
<id>basement_jaxx_singles</id>
</cd>
</list>
</pre></div>
<p>After reading from the above XML, you will get three <b>different</b> Cd instances.</p>
<p>Remember: it's impossible to support back-references (cycles) with NO_REFERENCES mode activated therefore
a CircularReferenceException is thrown if you ever try to do so.</p>
</body>
</html>