(De)Serializing to more files and keeping references between objects

View: New views
2 Messages — Rating Filter:   Alert me  

(De)Serializing to more files and keeping references between objects

by Tomas Klubal :: Rate this Message:

| View Threaded | Show Only this Message

Hi,
I am facing following problem:
- I have 3 classes: Document, Pack and DocumentInPack
- each Pack instance contains  ordered list of documents and same document can
be referenced by different packs

class Document {
  String name;
}

class Pack {
  String name;
  List<DocumentInPack> documents;
}

class DocumentInPack {
  Document document;
  Pack pack;
  int index;
}

- xstream mode is set to XStream.ID_REFERENCES

- I'd like to serialize (save) all Documents to one xml (file) and all Packs to
another file and still keep references between them

- if I serialize everything by one run of xstreem.toXml(new Object[]{documents,
packs}) references are correct:
***********
<object-array id="1">
  <list id="2">
    <document id="3">
      <name>First Document</name>
    </document>
    <document id="4">
      <name>Second Document</name>
    </document>
  </list>
  <list id="6">
    <pack id="7">
      <name>Pack 0001</name>
      <documents id="8">
        <documentInPack id="9">
          <document reference="4"/>
          <pack reference="7"/>
          <index>1</index>
        </documentInPack>
        <documentInPack id="10">
          <document reference="3"/>
          <pack reference="7"/>
          <index>2</index>
        </documentInPack>
      </documents>
    </pack>
    <pack id="11">
     ...

  </list>
</object-array>
********************

- but when I use XmlMap to save list of documents to one file (documents.xml)
and packs to another file (packs.xml) documents are fully specified inside the
DocumentInPack.
********************
...
<pack id="2">
    <name>Pack 0001</name>
    <documents id="3">
      <documentInPack id="4">
        <document id="5">
          <name>First Document</name>
        </document>
        <pack reference="2"/>
        <optional>false</optional>
      </documentInPack>
      <documentInPack id="6">
        <document id="7">
          <name>Second Document</name>
        </document>
        <pack reference="2"/>
        <optional>true</optional>
      </documentInPack>
    </documents>
  </pack>
...
**********************

Is there any way how to keep references between objects even if they are not
serialized in the same call of toXML() method?

Thanks,
Regards,
Tomas Klubal


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: (De)Serializing to more files and keeping references between objects

by Jörg Schaible-2 :: Rate this Message:

| View Threaded | Show Only this Message

Hi Tomas,

Tomas Klubal wrote:

> Hi,
> I am facing following problem:
> - I have 3 classes: Document, Pack and DocumentInPack
> - each Pack instance contains  ordered list of documents and same document
> can be referenced by different packs
>
> class Document {
>   String name;
> }
>
> class Pack {
>   String name;
>   List<DocumentInPack> documents;
> }
>
> class DocumentInPack {
>   Document document;
>   Pack pack;
>   int index;
> }
>
> - xstream mode is set to XStream.ID_REFERENCES
>
> - I'd like to serialize (save) all Documents to one xml (file) and all
> Packs to another file and still keep references between them
>
> - if I serialize everything by one run of xstreem.toXml(new
> Object[]{documents, packs}) references are correct:
> ***********
> <object-array id="1">
>   <list id="2">
>     <document id="3">
>       <name>First Document</name>
>     </document>
>     <document id="4">
>       <name>Second Document</name>
>     </document>
>   </list>
>   <list id="6">
>     <pack id="7">
>       <name>Pack 0001</name>
>       <documents id="8">
>         <documentInPack id="9">
>           <document reference="4"/>
>           <pack reference="7"/>
>           <index>1</index>
>         </documentInPack>
>         <documentInPack id="10">
>           <document reference="3"/>
>           <pack reference="7"/>
>           <index>2</index>
>         </documentInPack>
>       </documents>
>     </pack>
>     <pack id="11">
>      ...
>
>   </list>
> </object-array>
> ********************
>
> - but when I use XmlMap to save list of documents to one file
> (documents.xml) and packs to another file (packs.xml) documents are fully
> specified inside the DocumentInPack.
> ********************
> ...
> <pack id="2">
>     <name>Pack 0001</name>
>     <documents id="3">
>       <documentInPack id="4">
>         <document id="5">
>           <name>First Document</name>
>         </document>
>         <pack reference="2"/>
>         <optional>false</optional>
>       </documentInPack>
>       <documentInPack id="6">
>         <document id="7">
>           <name>Second Document</name>
>         </document>
>         <pack reference="2"/>
>         <optional>true</optional>
>       </documentInPack>
>     </documents>
>   </pack>
> ...
> **********************
>
> Is there any way how to keep references between objects even if they are
> not serialized in the same call of toXML() method?

There's currently no native support for this. However, you can construct
such a beast, but it will take a little effort.

You have to understand first, what XStream is internally doing. XStream uses
a MarshallingStrategy to manage references in the object graph. A call to
XStream.setMode(...) is a simple shortcut to a call of
Xstream.setMarshallingStrategy(...). Any conversion from Object to XML will
call in the end XStream.marshal(...), resp. XStream.unmarshal(...) for vice
versa. These methods will utilize the MarshallingStrategy to create a new
(Un)MarshallingContext, that keeps the references of the marshalled
objects. Therefore you can normally not have references between different
calls to these methods.

Now, have a look at the last fixture of the MultipleObjectsInOneStreamTest
in the acceptance tests (in the trunk). Here I've implemented a
MarshallingStrategy as workaround that utilizes the
ReferenceByIdMarshallingStrategy, but avoids the creation of these contexts
on each call. You can use this implementation.

Unfortunately this is not enough for the XmlMap, since my implementation
above keeps the context (which in turn keeps the underlaying
HierarchicalStreamWriter/Reader) and any newly provided HSW/HSR will be
ignored. You have to enhance therefore this implementation youself by
creating a delegate for the HSW/HSR where you are able to exchange the
delegate's target. Derive from ReaderWrapper or WriterWrapper so you have
access to the protected wrapper field that keeps the wrapped object. Put
such a wrapper into the created context and exchange it's wrapped object on
every call to start(...).

Caveats:

1/ Such an XStream instance is no longer thread-safe i.e. you may not
(implicitly) call marshal and/or unmarshal from different threads at the
same time.

2/ Since the context is kept, this XStream instance will keep a reference to
all (un)marshalled objects. So this can get memory consuming. However,
since XStream 1.2.2 these references are WeakReferences - so if you don't
have a reference on one of those elements anymore, XStream won't also.

Hope this helps.

- Jörg


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email