}
String type = child.getAttribute("type");
if (Util.isEmptyString(type)) {
// TODO should we use String by default? Or guess from the property type?
throw new CayenneRuntimeException("No type specified for tag '"
+ child.getNodeName()
+ "'.");
}
// temp hack to support primitives...
Class objectClass = (Class) classMapping.get(type);
if (null == objectClass) {
try {
objectClass = Class.forName(type);
}
catch (Exception e) {
throw new CayenneRuntimeException("Unrecognized class '"
+ objectClass
+ "'", e);
}
}
try {
// This crazy conditional checks if we're decoding a collection. There are two
// ways
// to enter into this body:
// 1) If there are two elements at the same level with the same name, then
// they should
// part of a collection.
// 2) If a single occurring element has the "forceList" attribute set to
// "YES", then it
// too should be treated as a collection.
//
// The final part checks that we have not previously attempted to decode this
// collection,
// which is necessary to prevent infinite loops .
if ((((null != child.getParentNode()) && (XMLUtil.getChildren(
child.getParentNode(),
child.getNodeName()).size() > 1)) || (child
.getAttribute("forceList")
.toUpperCase().equals("YES")))
&& (!decodedCollections.contains(child))) {
return decodeCollection(child);
}
// If the object implements XMLSerializable, delegate decoding to the class's
// implementation of decodeFromXML().
if (XMLSerializable.class.isAssignableFrom(objectClass)) {
XMLSerializable ret = (XMLSerializable) objectClass.newInstance();
ret.decodeFromXML(this);
return ret;
}
// If we hit here, then we should be encoding "simple" properties, which are
// basically
// objects that take a single arg String constructor.
Constructor c = objectClass.getConstructor(new Class[] {
String.class
});
if (c != null) {
// Create a new object of the type supplied as the "type" attribute
// in the XML element that
// represents the XML element's text value.
// E.g., for <count type="java.lang.Integer">13</count>, this is
// equivalent to new Integer("13");
return c.newInstance(new Object[] {
XMLUtil.getText(child)
});
}
}
catch (Exception e) {
throw new CayenneRuntimeException("Error decoding tag '"
+ child.getNodeName()
+ "'", e);
}
// If we hit here, then we're trying to decode something we're not equipped to
// handle.
// E.g., a complex object that does not implement XMLSerializable.
throw new CayenneRuntimeException(
"Error decoding tag '"
+ child.getNodeName()
+ "': "
+ "specified class does not have a constructor taking either a String or an XMLDecoder");
}