lcsim/src/org/lcsim/job
diff -N JobControlManager.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ JobControlManager.java 4 Sep 2008 23:01:34 -0000 1.1
@@ -0,0 +1,360 @@
+package org.lcsim.job;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.beans.BeanInfo;
+import java.beans.PropertyDescriptor;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.StringTokenizer;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.lcsim.util.Driver;
+import org.lcsim.util.loop.LCIOEventSource;
+import org.lcsim.util.loop.LCSimLoop;
+
+// TODO: implement global parameters such as numberToRun as
+// T getParameter(name,Class<T>)
+//
+// TODO: handle additional parameter types such as SymmetricMatrix
+//
+// TODO: handle 2d array parameters
+//
+// TODO: turn on/off driverStatistics (does this require Driver changes?)
+//
+// TODO: expressions as in compact description for simple arithmetic with units
+//
+// TODO: handle constructor arguments (no idea how to do this)
+//
+public class JobControlManager {
+
+ Map<String,Driver> driverMap;
+ List<Driver> driverExec;
+ List<File> inputFiles;
+ Map<String,String> availableDrivers = new HashMap<String,String>();
+
+ JobControlManager()
+ {
+ findAvailableDrivers();
+ }
+
+ public static void main(String args[])
+ {
+ if (args.length == 0)
+ throw new RuntimeException("Missing XML input file!");
+ File xmlRunControlFile = new File(args[0]);
+ if (!xmlRunControlFile.exists())
+ throw new RuntimeException("File " + args[0] + " does not exist!");
+ JobControlManager mgr = new JobControlManager();
+ mgr.setup(xmlRunControlFile);
+ mgr.run();
+ }
+
+ public void run()
+ {
+ LCSimLoop loop = new LCSimLoop();
+ for (Driver driver : driverExec) {
+ loop.add(driver);
+ }
+ try {
+ loop.setLCIORecordSource(new LCIOEventSource("test",inputFiles));
+ loop.loop(-1,null);
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ loop.dispose();
+ }
+
+ // setup from embedded resource
+ public void setup(String resource)
+ {
+ setup(JobControlManager.class.getResourceAsStream(resource));
+ }
+
+ // setup from file
+ public void setup(File file)
+ {
+ try {
+ setup((new FileInputStream(file)));
+ } catch (FileNotFoundException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ // setup from InputStream (primary setup routine)
+ public void setup(InputStream in)
+ {
+ // clear data structures for next job
+ clear();
+
+ // build the steering xml document
+ SAXBuilder builder = new SAXBuilder();
+ Document doc = null;
+ try {
+ doc = builder.build(in);
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+
+ // get the root element
+ Element root = doc.getRootElement();
+
+ // get list of driver elements from the file
+ List<Element> drivers = root.getChild("drivers").getChildren("driver");
+
+ // process list of drivers
+ for (Element driver : drivers) {
+
+ // get the name of driver
+ String name = driver.getAttributeValue("name");
+
+ String type = driver.getAttributeValue("type");
+
+ // translate from short name if applicable
+ if (availableDrivers.get(type) != null)
+ {
+ type = availableDrivers.get(type);
+ }
+
+ // get the class of driver
+ Class driverClass;
+
+ // the BeanInfo for this class
+ BeanInfo beaninfo;
+
+ // the constructor for this class
+ Constructor constructor;
+
+ // instantiated object
+ Driver newDriver;
+
+ // a lot of exceptions to catch for introspection so just wrap
+ // the next 4 gets in a try block
+ try {
+ driverClass = Class.forName(type);
+
+ // get bean info for driver
+ beaninfo = java.beans.Introspector.getBeanInfo(driverClass);
+
+ // create a new instance of this driver
+ constructor = driverClass.getConstructors()[0];
+ newDriver = (Driver)constructor.newInstance(null);
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+
+ // get list of parameter elements
+ List<Element> parameters = driver.getChildren();
+
+ // process the parameters
+ for (Element parameter : parameters) {
+
+ // get parameter name
+ String pname = parameter.getName();
+
+ // find the correct property descriptor for this parameter
+ PropertyDescriptor propFind = null;
+ for (PropertyDescriptor prop : beaninfo.getPropertyDescriptors()) {
+ if (prop.getName().equals(pname)) {
+ propFind = prop;
+ break;
+ }
+ }
+
+ // found a valid property?
+ if (propFind != null) {
+
+ // get the class of the property
+ Class propertyType = propFind.getPropertyType();
+
+ // create Object for next Driver parameter
+ //System.out.println("converting: " + propFind.getName());
+ Object nextParameter = convertParameter(parameter.getText(), propertyType);
+
+ // TODO: use set property
+
+ // if got a valid parameter value, then invoke the setter with its value
+ if (nextParameter != null) {
+ Method propWrite = propFind.getWriteMethod();
+ Object pargs[] = new Object[1];
+ pargs[0] = nextParameter;
+ try {
+ propWrite.invoke(newDriver, pargs);
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ }
+ else {
+ System.out.println("WARNING: failed to create parameter object with value: " + parameter.getText());
+ }
+ }
+ else {
+ System.out.println("WARNING: no property descriptor found: " + pname);
+ }
+ }
+
+ // add this driver to Driver map
+ addDriver(name,newDriver);
+ }
+
+ // add driver references to list for execution order
+ List<Element> exec = root.getChild("execute").getChildren("driver");
+ for (Element execDriver : exec) {
+ String driverName = execDriver.getAttributeValue("name");
+ Driver driverFind = driverMap.get(driverName);
+ if (driverFind != null)
+ driverExec.add(driverFind);
+ else
+ throw new RuntimeException("driver not found: " + driverName);
+ }
+
+ // process list of input LCIO files
+ List<Element> files = root.getChild("inputFiles").getChildren("file");
+ for (Element file : files) {
+ String fileLoc = file.getText();
+ File nextFile = new File(fileLoc);
+ inputFiles.add(nextFile);
+ }
+ }
+
+ // reset internal data structures
+ public void clear() {
+ inputFiles = new ArrayList<File>();
+ driverExec = new ArrayList<Driver>();
+ driverMap = new LinkedHashMap<String,Driver>();
+ }
+
+ // generic parameter conversion to int, String, double, float
+ private Object convertParameter(String value, Class propertyType) {
+
+ //System.out.println("converting type: <" + propertyType.getName() +">");
+
+ Object o = null;
+
+ // int
+ if (propertyType.equals(int.class)) {
+ o = Integer.valueOf(value);
+ }
+ // String
+ else if (propertyType.equals(String.class)) {
+ o = value;
+ }
+ // double
+ else if (propertyType.equals(double.class)) {
+ o = Double.valueOf(value);
+ }
+ // float
+ else if (propertyType.equals(float.class)) {
+ o = Float.valueOf(value);
+ }
+ // boolean
+ else if (propertyType.equals(boolean.class)) {
+ o = Boolean.valueOf(value);
+ }
+ // Hep3Vector
+ else if (propertyType.equals(Hep3Vector.class)) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ double x = Double.valueOf(tokenize.nextToken());
+ double y = Double.valueOf(tokenize.nextToken());
+ double z = Double.valueOf(tokenize.nextToken());
+ o = new BasicHep3Vector(x,y,z);
+ }
+ // 1d array of doubles
+ else if (propertyType.getName().equals("[D")) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ int size = tokenize.countTokens();
+ double da[] = new double[size];
+ int i = 0;
+ while (tokenize.hasMoreTokens()) {
+ da[i] = Double.valueOf(tokenize.nextToken());
+ ++i;
+ }
+ o = da;
+ }
+ // 1d array of ints
+ else if (propertyType.getName().equals("[I")) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ int size = tokenize.countTokens();
+ int ia[] = new int[size];
+ int i = 0;
+ while (tokenize.hasMoreTokens()) {
+ ia[i] = Integer.valueOf(tokenize.nextToken());
+ ++i;
+ }
+ o = ia;
+ }
+ // 1d array of floats
+ else if (propertyType.getName().equals("[F")) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ int size = tokenize.countTokens();
+ float fa[] = new float[size];
+ int i = 0;
+ while (tokenize.hasMoreTokens()) {
+ fa[i] = Float.valueOf(tokenize.nextToken());
+ ++i;
+ }
+ o = fa;
+ }
+ // 1d array of strings
+ else if (propertyType.getName().equals("[Ljava.lang.String;")) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ int size = tokenize.countTokens();
+ String sa[] = new String[size];
+ int i = 0;
+ while (tokenize.hasMoreTokens()) {
+ sa[i] = tokenize.nextToken();
+ ++i;
+ }
+ o = sa;
+ }
+ // 1d array of booleans
+ else if (propertyType.getName().equals("[Z")) {
+ StringTokenizer tokenize = new StringTokenizer(value);
+ int size = tokenize.countTokens();
+ boolean ba[] = new boolean[size];
+ int i = 0;
+ while (tokenize.hasMoreTokens()) {
+ ba[i] = Boolean.valueOf(tokenize.nextToken());
+ ++i;
+ }
+ o = ba;
+ }
+
+ return o;
+ }
+
+ // add a driver with associated name
+ private void addDriver(String name, Driver driver)
+ {
+ if (driverMap.containsKey(name)) {
+ throw new RuntimeException("ERROR: duplicate driver name: " + name);
+ }
+ driverMap.put(name, driver);
+ }
+
+ void findAvailableDrivers()
+ {
+ InputStream in = JobControlManager.class.getResourceAsStream("/META-INF/services/org.lcsim.util.Driver");
+ if (in == null) throw new RuntimeException("driver file not found");
+ Scanner scan = new Scanner(in);
+ while(scan.hasNext())
+ {
+ String fullName = scan.nextLine().trim();
+ String shortName = fullName.substring(fullName.lastIndexOf(".")+1);
+ availableDrivers.put(shortName,fullName);
+ }
+ }
+}