Commit in lcsim/src/org/lcsim/job on MAIN
JobControlManager.java+100-561.8 -> 1.9
JM: add support for overloaded methods using type attribute on parameter elements

lcsim/src/org/lcsim/job
JobControlManager.java 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- JobControlManager.java	25 Sep 2008 22:16:16 -0000	1.8
+++ JobControlManager.java	26 Sep 2008 23:31:14 -0000	1.9
@@ -4,6 +4,7 @@
 import hep.physics.vec.Hep3Vector;
 
 import java.beans.BeanInfo;
+import java.beans.MethodDescriptor;
 import java.beans.PropertyDescriptor;
 import java.io.File;
 import java.io.FileInputStream;
@@ -42,7 +43,7 @@
 //TODO: additional parameter types (SymmetricMatrix, etc.)
 //TODO: 2d parameter arrays
 //TODO: simple expressions as in compact description
-//TODO: output of example XML steering file (e.g. like Marlin)
+//TODO: example XML steering file generation (e.g. like Marlin)
 //TODO: basic command line arg support (no args then expect steering file loc):
 //      -s steeringFile
 //      -e exampleSteeringOutput.xml
@@ -313,8 +314,7 @@
 				}
 			}
 		}
-		URL[] urls = urlList.toArray(new URL[]
-		                                     {});
+		URL[] urls = urlList.toArray(new URL[]{});
 		loader = new LCSimClassLoader(urls);
 
 		// Print user's classpath entries.
@@ -358,21 +358,19 @@
 			// BeanInfo for the Driver class.
 			BeanInfo beaninfo;
 
-			// Constructor for the class.
-			Constructor constructor;
-
-			// The actual Driver instance.
+			// The Driver instance.
 			Driver newDriver;
 
-			// Get Class, BeanInfo, and Constructor, and setup new Driver instance.
+			// Get Class, BeanInfo, and Constructor, and setup the new Driver instance.
 			try
 			{
 				driverClass = loader.loadClass(type);
 				if (printDriversDetailed)
-					System.out.println(driverClass.getCanonicalName());
+					logStream.println(driverClass.getCanonicalName());
 				beaninfo = java.beans.Introspector.getBeanInfo(driverClass);
 				newDriver = (Driver) driverClass.newInstance();
-			} catch (Exception x)
+			} 
+			catch (Exception x)
 			{
 				throw new RuntimeException(x);
 			}
@@ -381,61 +379,93 @@
 			List<Element> parameters = driver.getChildren();
 
 			// Process the parameters.
-			for (Element parameter : parameters)
+			for (Element parameterElement : parameters)
 			{
+				// The parameter's setter method that we will find.
+				Method setter = null;
+				
+				// The parameter's type that will be inferred from the method or is given by a type string in
+				// the case of an overloaded method.
+				Class propertyType = null;
+				
 				// Get the parameter name.
-				String pname = parameter.getName();
+				String pname = parameterElement.getName();
 
-				// Find the property descriptor for this parameter.
-				PropertyDescriptor propFind = null;
-				for (PropertyDescriptor prop : beaninfo.getPropertyDescriptors())
+				// Manually create a list of methods that might be associated with this parameter.
+				List<MethodDescriptor> methList = new ArrayList<MethodDescriptor>();
+				for (MethodDescriptor meth : beaninfo.getMethodDescriptors())
 				{
-					if (prop.getName().equals(pname))
+					if (meth.getName().startsWith("set"))
 					{
-						propFind = prop;
-						break;
-					}
-				}
-
-				// Found a valid property?
-				if (propFind != null)
-				{
-					// Get the class of the property.
-					Class propertyType = propFind.getPropertyType();
-
-					// Create an Object for next Driver parameter using conversion method.
-					Object nextParameter = convertParameter(parameter.getText(), propertyType);
-
-					// If got a valid parameter value, then invoke the setter with its value.
-					if (nextParameter != null)
-					{
-
-						if (printDriversDetailed)
-						{
-							logStream.println("    " + pname + " = " + parameter.getText());
-						}
-
-						Method propWrite = propFind.getWriteMethod();
-						Object pargs[] = new Object[1];
-						pargs[0] = nextParameter;
-						try
-						{
-							propWrite.invoke(newDriver, pargs);
-						} catch (Exception x)
+						String propHack = meth.getName().replace("set", "");
+						propHack = propHack.substring(0, 1).toLowerCase() + propHack.substring(1);
+						if (propHack.equals(pname))
 						{
-							throw new RuntimeException(x);
+							methList.add(meth);
 						}
-					} else
+					}						
+				}
+				
+				// No method was found, so we need to bail out of the job.
+				if (methList.size() == 0)
+				{
+					throw new RuntimeException("Error!  A set method for parameter " + pname + " was not found!");
+				}				
+				// In this case, need to figure out which overloaded method to use.
+				else if (methList.size() > 1)
+				{
+					if (parameterElement.getAttribute("type") == null)
+						throw new RuntimeException("Parameter " + pname + " is overloaded but type field is missing from parameter!");
+					try 
 					{
-						throw new RuntimeException("Error!  Failed to create parameter " + pname + " with value: " + parameter.getText());
+						// Try a primitive type first.
+						propertyType = getPrimitiveType(parameterElement.getAttribute("type").getValue());
+						
+						// If type is null, then parameter is an Object and not a primitive, or it is not a valid type.
+						if (propertyType == null)
+							propertyType = Class.forName(parameterElement.getAttribute("type").getValue());
+					}
+					catch (ClassNotFoundException x)
+					{						
+						throw new RuntimeException("Error!  Bad user type " + parameterElement.getAttribute("type").getValue() + " for parameter " + pname + "!");
+					}
+					// Find a method that matches the user type.
+					for (MethodDescriptor meth : methList)
+					{
+						Method m = meth.getMethod();
+						if (m.getParameterTypes().length == 1 && m.getParameterTypes()[0].equals(propertyType))
+						{
+							setter = meth.getMethod();
+							break;
+						}						
 					}
-				} else
-				{
-					throw new RuntimeException("Error! No property descriptor found: " + pname);
 				}
-			}
+				// Use the single method that was found.
+				else if (methList.size() == 1)
+				{
+					setter = methList.get(0).getMethod();
+					propertyType = setter.getParameterTypes()[0];
+				}														
+				
+				// Create an Object for next Driver parameter using the conversion method.
+				Object nextParameter = convertParameter(parameterElement.getText(), propertyType);
+				
+				// Invoke the setter.
+				Object pargs[] = new Object[1];
+				pargs[0] = nextParameter;
+				try
+				{
+					if (printDriversDetailed)
+						logStream.println(pname + " = " + parameterElement.getText());
+					setter.invoke(newDriver, pargs);
+				} 
+				catch (Exception x)
+				{
+					throw new RuntimeException(x);
+				}									
+			} // parameter loop
 			addDriver(name, newDriver);
-		}
+		} // driver loop
 		if (printDriversDetailed)
 		{
 			logStream.println("--- End Drivers ---");
@@ -451,7 +481,7 @@
 			if (driverFind != null)
 				driverExec.add(driverFind);
 			else
-				throw new RuntimeException("driver not found: " + driverName);
+				throw new RuntimeException("Driver not found: " + driverName);
 		}
 
 		// Setup the file cache.
@@ -519,7 +549,7 @@
 	}
 
 	/**
-	 * Reset all private variables.
+	 * Reset all private variables before next execution.
 	 */
 	private void clear()
 	{
@@ -717,4 +747,18 @@
 		logStream.println("-- End System Properties");
 		logStream.println();
 	}	
+	
+	private static Class getPrimitiveType(String name)
+	{
+		if (name.equals("byte")) return byte.class;
+		if (name.equals("short")) return short.class;
+		if (name.equals("int")) return int.class;
+		if (name.equals("long")) return long.class;
+		if (name.equals("char")) return char.class;
+		if (name.equals("float")) return float.class;
+		if (name.equals("double")) return double.class;
+		if (name.equals("boolean")) return boolean.class;
+		if (name.equals("String")) return String.class;
+		return null;
+	}
 }
\ No newline at end of file
CVSspam 0.2.8