dlr 02/01/15 05:04:14
Modified: src/java/org/apache/stratum/xo Mapper.java
Log:
o Clarified JavaDoc for basePackage instance member.
o Added map(String, String) overload which (again) tries reading from
the classpath before going to the file system. Now wrappers
InputStream overload (which incidently may not get a usable value for
basePath if called directly).
o Added createInstance(Element, String) method to create Java
instances of XML descriptor elements. It first tries to use any value
passed in via the String parameter. If that is null, it tries the
value for the element's className attribute. Lastly, it tries the
simple heuristic which assumes that the class's name can be derived
from the XML element's name, and is in the parent element's package.
o Removed old duplicate inclusion() method.
o Removed elementClassName() and elementToClassName() (subsumed by
createInstance()).
o Added parsePrefix() helper to deal with classes which have no
package.
Revision Changes Path
1.9 +127 -108
jakarta-turbine-stratum/src/java/org/apache/stratum/xo/Mapper.java
Index: Mapper.java
===================================================================
RCS file:
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/xo/Mapper.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -u -r1.8 -r1.9
--- Mapper.java 15 Jan 2002 10:49:15 -0000 1.8
+++ Mapper.java 15 Jan 2002 13:04:14 -0000 1.9
@@ -69,6 +69,7 @@
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.util.FileUtils;
+import org.apache.commons.util.StringUtils;
import java.lang.reflect.Method;
import org.apache.stratum.introspection.Introspector;
@@ -139,7 +140,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
- * @version $Id: Mapper.java,v 1.8 2002/01/15 10:49:15 dlr Exp $
+ * @version $Id: Mapper.java,v 1.9 2002/01/15 13:04:14 dlr Exp $
*/
// How to use the resources package to pull in the
@@ -192,8 +193,8 @@
private String basePath;
/**
- * Base package of all the classes we may need to
- * create the specified object.
+ * Base package of all the classes we may need to create instances
+ * of.
*/
private String basePackage;
@@ -228,6 +229,24 @@
}
/**
+ * Loads a XML document (from the file system), maps it to an
+ * instance of the JavaBean <code>beanClass</code>, and returns
+ * the instance.
+ *
+ * @param xmlInput The file system path to the XML data file to
+ * process.
+ * @see #map(InputStream, String)
+ */
+ public Object map(File xmlInput, String beanClass)
+ throws Exception
+ {
+ // Get the base directory
+ basePath = FileUtils.dirname(xmlInput.getAbsolutePath());
+
+ return map(new FileInputStream(xmlInput), beanClass);
+ }
+
+ /**
* Loads a XML document (first trying the classpath, then the file
* system), maps it to an instance of the JavaBean
* <code>beanClass</code>, and returns the instance.
@@ -236,13 +255,22 @@
* system) to the XML data file to process.
* @see #map(InputStream, String)
*/
- public Object map(File xmlInput, String beanClass)
+ public Object map(String xmlInput, String beanClass)
throws Exception
{
+ // Use the source path to grab a stream from the classpath.
+ InputStream xmlStream =
+ getClass().getClassLoader().getResourceAsStream(xmlInput);
+ if (xmlStream == null)
+ {
+ // Couldn't load from the classpath -- try the file system.
+ xmlStream = new FileInputStream(xmlInput);
+ }
+
// Get the base directory
- basePath = FileUtils.dirname(file.getAbsolutePath());
-
- return map(new FileInputStream(xmlInput), beanClass);
+ basePath = FileUtils.dirname(xmlInput);
+
+ return map(xmlStream, beanClass);
}
/**
@@ -264,19 +292,27 @@
SAXReader xmlReader = new SAXReader();
document = xmlReader.read(xmlInput);
- // Assure we have the beanClass
+ // Create the parent bean.
Element rootElement = document.getRootElement();
+ basePackage = parsePackage(beanClass);
+ Object bean = createInstance(rootElement, beanClass);
+
+ // Assure we have the fully qualified class of the bean.
if (beanClass == null)
{
- beanClass = elementClassName(rootElement);
+ beanClass = bean.getClass().getName();
}
- // Create the parent bean.
- Object bean = Class.forName(beanClass).newInstance();
+ // Infer the base package to use for object creation when
+ // CLASS_NAME attribute is not specified from bean class.
+ basePackage = parsePackage(beanClass);
+
+ if (basePath == null)
+ {
+ // Overloads were not called, assuming classpath loading.
+ basePath = StringUtils.replace(basePackage, ".", "/");
+ }
- // Determine the base package to use for object creation.
- basePackage = beanClass.substring(0,beanClass.lastIndexOf("."));
-
// Determine the base package to use for object creation.
return treeWalk(rootElement, bean);
}
@@ -329,31 +365,27 @@
if (hasChildren(node))
{
debug("Node " + node.getName() + " has children");
-
+
// We now have the situation where we need to
- // instantiate a parent object so that elements
- // that are subsequently processed can have their
- // values assigned to the above mentioned object.
- // Using the example listed above, we would want
- // to create an Address object (1) so that the
- // 'street', 'city', and 'country' properties
- // can be populated. We assume here that the
- // object that we are creating is in the same
- // package as the parent object.
- String className = basePackage + "." +
elementToClassName(name);
-
+ // instantiate a parent object so that
+ // elements that are subsequently processed
+ // can have their values assigned to the above
+ // mentioned object. Using the example listed
+ // above, we would want to create an Address
+ // object (1) so that the 'street', 'city',
+ // and 'country' properties can be populated.
+
// We have to check for inclusion rules and build
// and object from an external XML file if that's
// the case.
- Object o = inclusion(node,name,bean);
+ Object o = inclusion((Element) node);
if (o == null)
{
// Catch this
try
{
- // Should probably use the factory manager.
- o = Class.forName(className).newInstance();
+ o = createInstance((Element) node, null);
}
catch (Exception e)
{
@@ -394,26 +426,20 @@
if (((Element)node).attributeValue(CLASS_NAME) != null)
{
debug("Using className metadata to build object");
-
- String className = elementClassName((Element) node);
-
+
try
{
- // Should probably use the factory manager.
- Class c = Class.forName(className);
- debug("c=" + c);
- o = c.newInstance();
- debug("o=" + o);
+ o = createInstance((Element) node, null);
}
catch (Exception e)
{
- debug("Problem instantiating class " +
- className + ": " + e);
+ debug("Problem instantiating class: " + e);
}
if (o != null)
{
- debug("Created new object -> " + className);
+ debug("Created new object -> " +
+ o.getClass().getName());
}
}
else
@@ -482,46 +508,85 @@
inclusionRules.put(elementName, rule);
}
- // -------------------------------------------------------------------
- // P R I V A T E M E T H O D S
- // -------------------------------------------------------------------
-
/**
- * Returns the fully qualified class name of <code>element</code>
- * from its <code>className</code> attribute, or if that doesn't
- * exist, then from its nested <code><pre><className></pre></code>
- * element.
+ * Returns an instance of the class represented by
+ * <code>element</code>. First tries the (fully qualified) class
+ * name from any <code>className</code> attribute, or if that
+ * doesn't exist, then assumes the class is in the same package as
+ * the enclosing element and is named using the name of the
+ * current node with its first letter capitalized.
+ *
+ * @param element The XML element to create an instance of.
+ * @param className An override for the name of the class to use,
+ * or <code>null</code> to try heuristics.
+ * @return The newly created instance.
+ * @exception Exception Unable to determine class name or create
+ * instance.
*/
- private String elementClassName(Element element)
+ protected Object createInstance(Element element, String className)
throws Exception
{
- String beanClass = element.attributeValue(CLASS_NAME);
- if (beanClass == null)
+ // Should probably use the factory manager.
+ try
{
- // Try for a nested element of the same name.
-
- debug(element.toString());
-
- beanClass = element.element(CLASS_NAME).getText();
- if (beanClass == null)
+ if (className == null || className.length() == 0)
+ {
+ className = element.attributeValue(CLASS_NAME);
+ }
+ return Class.forName(className).newInstance();
+ }
+ catch (Exception noAttrib)
+ {
+ // We assume here that the object that we are creating is
+ // in the same package as the parent object.
+ String nodeName = element.getName();
+ System.out.println("nodeName=" + nodeName + ", basePackage=" +
+ basePackage);
+ if (basePackage == null)
+ {
+ throw new Exception("Base package not known and " + CLASS_NAME +
+ " attribute not specified");
+ }
+ className = (basePackage.length() == 0 ? "" : basePackage + '.') +
+ nodeName.substring(0, 1).toUpperCase() + nodeName.substring(1);
+ // TODO: Check class name validity
+ try
+ {
+ return Class.forName(className).newInstance();
+ }
+ catch (Exception unknownClass)
{
throw new Exception
("No class name for node '" + element.getName() +
"': This can be resolved by adding a " + CLASS_NAME +
- " attribute or child node");
+ " attribute");
}
}
- return beanClass;
+ }
+
+
+ // -------------------------------------------------------------------
+ // P R I V A T E M E T H O D S
+ // -------------------------------------------------------------------
+
+
+ /**
+ * Parses the default package from <code>className</code>.
+ */
+ private final String parsePackage(String className)
+ {
+ int i = className.lastIndexOf('.');
+ return (i != -1 ? className.substring(0, i) : null);
}
/**
* Does the node in question have child nodes?
*
- * @param node
+ * @param node The element to check for children.
*/
private boolean hasChildren(Node node)
{
- return ((Element)node).nodeCount() > 1;
+ return (((Element) node).nodeCount() > 1);
}
/**
@@ -558,46 +623,12 @@
if (x == null)
{
- debug("ERROR: Problem loading -> " + node.getName() + ":" + x);
+ debug("ERROR: Problem loading -> " + node.getName() + ':' + x);
}
return x;
}
/**
- * Build up and object by pulling in an external XML
- * document.
- *
- * @param node
- * @param name
- * @param bean
- * @return Object The Java object build up by the inclusion process
- */
- private Object inclusion(Node node,String name, Object bean)
- throws Exception
- {
- String inclusionRule = (String) inclusionRules.get(name);
- Object x = null;
-
- if (inclusionRule == null)
- {
- return x;
- }
-
- String className = basePackage + "." +
- elementToClassName(name);
-
- String id = ((Element)node).attributeValue(EID);
- x = map(new File(basePath + "/" + inclusionRule + "/" + id + ".xml"),
className);
-
- if (x == null)
- {
- debug("ERROR: Problem loading -> " + node.getName() + ":" + x);
- }
-
- return x;
- }
-
- /**
* Add an object to a parent object
*
* @param bean
@@ -712,18 +743,6 @@
{
return (text == null ? null : prefix +
text.substring(0, 1).toUpperCase() + text.substring(1));
- }
-
- /**
- * Makes the first letter capital and leaves the rest as is.
- *
- * @param text The text to modify.
- * @return The modified text.
- */
- private String elementToClassName(String text)
- {
- return (text == null ? null :
- text.substring(0, 1).toUpperCase() + text.substring(1));
}
/**
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>