[jdom-interest] Architecture advice sought (long)

Kyle F. Downey kdowney at amberarcher.com
Fri Jul 27 07:18:00 PDT 2001


Sasha,

Personally, I would avoid doing what you're describing on general
principles. What you want are objects that represent your problem domain.
Your problem domain is not, conceptually, a specialization of the XML
parsing problem domain. A CreatureElement isn't a "better" Element--it's a
use of an Element that uses it via inheritance for convenience only.

[This is especially irksome in Java, because you're using a precious
resource (the single base class given to you) for a convenience.]

In short, you're representing a "uses-a" relationship with "is-a" design.

For our JDOM-related code, we use a pair of interfaces:

public interface Xmlizable {
  void unmarshal();
  Element marshal();
}

for an object that controls its own XML format, and

public interface Xmlizer {
  void marshal(Element parentElem, Object val);
  Object unmarshal(Element srcElem);
}

for an object that defines an XML format for another object.
For instance, this is how I fit primitives into the system that
are not already Xmlizable.

In our framework, we've added in an XML-driven factory that completes the
system by automatically discovering the correct Xmlizable/Xmlizer when
unmarshalling and marshalling objects.

There are always trade-offs. The Xmlizer design is nice because you're not
entangling the XML formatting information with your domain/data object,
so if you ever ditch JDOM the impact is limited to certain areas of code.
It's also cleaner: it would be easy to have a Sqlizer class alongside that
did object-relational translation, while adding Xmlizable and Sqlizable
to the same class gets messy. BUT because Java has no friend class
concept, you're forced to expose at least package-locally the attributes
and accessors of your class, which Xmlizable objects have full
private-level access. The only way around this would require (yick)
Reflection and Java 2's setAccessible(boolean) API, which lets you
access private fields.

FYI, my company is coming out with the system based on this mechanism
that can handle marshal/unmarshal of arbitrary small objects to a
hierarchical storage system (like the Windows registry, but for Java,
and a lot more flexible).

--kd


> Hi, I'm new to this list and I'll apologise straight away for not lurking
> for a bit - no excuse, but I'm fired up this morning!
>
> I'm at the early stages of designing an API/Engine that needs to be losely
> coupled to data and yet allow easy access to that data. XML is a no brainer
> as it also allows me to hand code and import parts of the data set. Also I
> want to transform the resulting data set into HTML as well as first pass
> validate it using DTD. JDOM is very attractive to me as my experience is
> very OO based - i've been craving a XML API like JDOM for some time.
>
> My ideas so far are to extend Element into a class class called MapElement
> so that it implements the java.util.Map interface. This works by  making
> keys of all sub elements, with their value as the value object. e.g
>
> <creature>
> 	<name>Oliphant</name>
> 	<weight>3.2</weight>
> 	<speed>
> 		<walking>10</walking>
> 		<running>30<running>
> 	</speed>
> </creature>
>
> maps out like this
>
> key		object
> ---		------
> name		(String)Oliphant
> weight	(String)3.2
> speed		(Element)xxx
>
> What this means is that I can do stuff like
>
> 	final static String NAME = "name";
> 	String name = (String)creature.get(NAME);
> 	creature.put(NAME,"Sam's Oliphant");
>
> The map interface means I can very easily access sub elements and their
> contents.
>
> I can subclass the MapElement to more specific classes like CreatureElement
> that might have getName() and getWeight() and can also contain engine logic
> based on the data.
>
> So does that seem reasonable so far?
> Should I use wrapper classes instead of extending them?
>
> Next - should I write a JDOMFactory to produce these subclasses?
>
> An idea is to take the super element name e.g <creature> and use it with a
> class factory to make my CreatureElement rather than plan MapElement - e.g
> to take an existing Element and make specialised Element from it...
>
> public Element createNamedElementSpecialisation(Element basicElement)
> {
> 	String superElementName = basicElement.getName();
> 	String className = "com.eoi.engine."+superElementName+"Element";
> 	//e.g	com.eoi.engine.CreatureElement
>
> 	Class c = Class.forName(className); // Create the class object
>
> 	Element e = c.newInstance(c); // Create an instance of
> CreatureElement
>
> 	(MapElement)e.initaliseFromElement(basicElement); //copy this
> elements XML to the new class
>
> 	return e;	//
> }
>
> I can detach() the old basic Element and null it for eventual garbage
> collection, so the extra object count shouldn't be too high.
>
> Does this sound feasible, does it make sense?
>
> Once again apologise for being such a bore first time out...
>
> Sasha Bilton
>
>
>
>
>
>
>
>
> _________________________________________________________________________
>
> Alison Associates
>
> The information contained in this e-mail and any attached files is intended only for the use of the person(s) to whom it is addressed and may be privileged, confidential and exempt from disclosure under applicable law. The views of the author may not necessarily reflect the views of the Company. If you are not the intended recipient please do not copy or convey this message or any attached files to any other person but delete this message and any attached files and notify us of incorrect receipt via e-mail to mailadmin at alisonassociates.com.
>
> _____________________________________________________________________
> This message has been checked for all known viruses by MessageLabs.
> _______________________________________________
> To control your jdom-interest membership:
> http://lists.denveronline.net/mailman/options/jdom-interest/youraddr@yourhost.com
>




More information about the jdom-interest mailing list