views:

30

answers:

2

Say I have this XML

<doc:document>
  <objects>
    <circle radius="10" doc:colour="red" />
    <circle radius="20" doc:colour="blue" />
  </objects>
</doc:document>

And this is how it is parsed (pseudo code):

// class DocumentParser
public Document parse(Element edoc) {
     doc = new Document();
     doc.objects = ObjectsParser.parse(edoc.getChild("objects"));

     for ( ...?... ) {
         doc.objectColours.put(object, colour);
     }

     return doc;
}

ObjectsParser is responsible for parsing the objects bit, but is not and should not be aware of the existence of documents. However, in Document colours are associated with objects by use of a Map.

What kind of pattern would you recommend to give the colour settings back to DocumentParser.parse from ObjectsParser.parse so it can associate it with the objects they belong to in a map?

The alternative would be something like this:

<doc:document>
  <objects>
    <circle id="1938" radius="10" />
    <circle id="6398" radius="20" />
  </objects>
  <doc:objectViewSettings>
   <doc:objectViewSetting object="1938" colour="red" />
   <doc:objectViewSetting object="6398" colour="blue" />
  </doc:objectViewSettings>
</doc:document>

Ugly!

A: 

What's wrong with

for (ObjType obj : doc.objects)
{
    doc.objectColours.put(obj, obj.getColour())
}

This assumes

  1. ObjectsParser returns a collection instance implementing Iterable
  2. ObjType is usable as a hash key (implements equals() and hashCode() correctly)
Jim Garrison
As can be seen by the namespace prefix "doc" on the colour attribute, it only applies in a Document context. An object as created by ObjectsParser will not contain this property.
Bart van Heukelom
Without a description of ObjectsParser it's hard for us to read your mind. In that case a callback looks like the best solution since you need to get control during parsing.
Jim Garrison
A: 

Here's an idea of my own:

interface ObjectCreatedFromXmlCallback {
     created(Object object, Element source);
}

// class DocumentParser
public Document parse(Element edoc) {
     doc = new Document();
     doc.objects = ObjectsParser.parse(edoc.getChild("objects"), new ObjectCreatedFromXmlCallback() {
      created(Object o, Element s) {
       if (o instanceof Circle) {
        // read the colour property from s
        doc.objectColours.put(o, colour);
       }
      }
     });

     return doc;
}

// ObjectsParser.parse
c = new Circle();
c.radius = ecircle.getAttribute(...);
callback.created(c, ecircle);
Bart van Heukelom