Print

Print


Commit in java/trunk/conditions/src on MAIN
main/config/conditions_database_testrun_2012_connection.properties+5added 342
main/java/org/hps/conditions/AbstractConditionsObject.java+13-10341 -> 342
                            /ConditionsConverterLoader.java-45341 removed
                            /ConditionsObjectCollection.java+45-27341 -> 342
                            /ConditionsObjectConverter.java+35-16341 -> 342
                            /ConditionsRecord.java+48-144341 -> 342
                            /ConditionsRecordCollection.java-26341 removed
                            /ConditionsRecordConverter.java+27-15341 -> 342
                            /ConnectionManager.java-157341 removed
                            /ConnectionParameters.java+30-38341 -> 342
                            /DatabaseConditionsManager.java+244-67341 -> 342
                            /DatabaseConditionsReader.java+4-22341 -> 342
                            /DefaultTestSetup.java+61added 342
                            /TableMetaData.java+49-6341 -> 342
main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml+34-27341 -> 342
test/java/org/hps/conditions/ConditionsDriverTest.java+3-4341 -> 342
                            /ConditionsObjectTest.java+10-17341 -> 342
                            /DatabaseConditionsManagerTest.java+6-12341 -> 342
test/java/org/hps/conditions/beam/BeamCurrentTest.java+2-2341 -> 342
test/java/org/hps/conditions/ecal/EcalConditionsConverterTest.java+6-17341 -> 342
                                 /EcalConditionsLoaderTest.java+8-22341 -> 342
test/java/org/hps/conditions/svt/SvtConditionsConverterTest.java+4-17341 -> 342
                                /SvtConditionsLoaderTest.java+4-18341 -> 342
+638-709
2 added + 3 removed + 18 modified, total 23 files
Work from today on the conditions system.

java/trunk/conditions/src/main/config
conditions_database_testrun_2012_connection.properties added at 342
--- java/trunk/conditions/src/main/config/conditions_database_testrun_2012_connection.properties	                        (rev 0)
+++ java/trunk/conditions/src/main/config/conditions_database_testrun_2012_connection.properties	2014-03-25 01:37:50 UTC (rev 342)
@@ -0,0 +1,5 @@
+user: rd_hps_cond_ro
+password: 2jumpinphotons.
+database: rd_hps_cond
+hostname: mysql-node03.slac.stanford.edu
+port: 3306
\ No newline at end of file

java/trunk/conditions/src/main/java/org/hps/conditions
AbstractConditionsObject.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/AbstractConditionsObject.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/AbstractConditionsObject.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -3,12 +3,12 @@
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
+import java.util.List;
 
 /**
  * The abstract implementation of {@link ConditionsObject}.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-// FIXME: Database query methods need to be rewritten to use QueryBuilder (which itself needs to be written).
 public abstract class AbstractConditionsObject implements ConditionsObject {
 
     private TableMetaData _tableMetaData = null;
@@ -24,7 +24,7 @@
     protected AbstractConditionsObject() {     
         _fieldValues = new FieldValueMap();
     }
-        
+            
     public TableMetaData getTableMetaData() {
         return _tableMetaData;
     }
@@ -54,11 +54,10 @@
             throw new ConditionsObjectException("This object is set to read only.");
         }
         if (isNew()) {
-            throw new ConditionsObjectException("This object is not in the database and cannot be deleted.");
+            throw new ConditionsObjectException("This object is not in the database and so cannot be deleted.");
         }
         String query = QueryBuilder.buildDelete(_tableMetaData.getTableName(), _rowId);
-        ConnectionManager.getConnectionManager().update(query);
-        // TODO: Need to check here if delete was successful!
+        DatabaseConditionsManager.getInstance().update(query);
         _rowId = -1;
     }
     
@@ -75,9 +74,11 @@
                 getCollectionId(),
                 getTableMetaData().getFieldNames(),
                 _fieldValues.valuesToArray());
-        int key = ConnectionManager.getConnectionManager().update(query);
-        // TODO: Need to check here that insert was succcessful!
-        _rowId = key;
+        List<Integer> keys = DatabaseConditionsManager.getInstance().update(query);
+        if (keys.size() == 0 || keys.size() > 1) {
+            throw new ConditionsObjectException("SQL insert returned wrong number of keys: " + keys.size());
+        }
+        _rowId = keys.get(0);
     }
 
     public void select() throws ConditionsObjectException {
@@ -86,7 +87,8 @@
         } 
         String query = QueryBuilder.buildSelect(
                 getTableMetaData().getTableName(), _collectionId, _fieldValues.fieldsToArray(), "id ASC");
-        ResultSet resultSet = ConnectionManager.getConnectionManager().query(query);  
+        DatabaseConditionsManager manager = DatabaseConditionsManager.getInstance();
+        ResultSet resultSet = manager.query(query);  
         try {
             ResultSetMetaData metadata = resultSet.getMetaData();
             int ncolumns = metadata.getColumnCount();
@@ -98,6 +100,7 @@
         } catch (SQLException e) {
             throw new ConditionsObjectException(e.getMessage(), this);
         }
+        DatabaseConditionsManager.close(resultSet);
     }
         
     public void update() throws ConditionsObjectException {
@@ -115,7 +118,7 @@
                 _rowId, 
                 _fieldValues.fieldsToArray(), 
                 _fieldValues.valuesToArray());
-        ConnectionManager.getConnectionManager().update(query);
+        DatabaseConditionsManager.getInstance().update(query);
         setIsDirty(false);
     }
     

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsConverterLoader.java removed after 341
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsConverterLoader.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsConverterLoader.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,45 +0,0 @@
-package org.hps.conditions;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.jdom.Element;
-import org.lcsim.conditions.ConditionsConverter;
-
-/**
- * This class reads in an XML configuration specifying a list of converter classes,
- * e.g. from the config file for the {@link DatabaseConditionsManager}.
- *  
- * @author Jeremy McCormick <[log in to unmask]>
- */
-public class ConditionsConverterLoader {
-    
-    List<ConditionsConverter> _converterList;
-    
-    void load(Element element) {
-        _converterList = new ArrayList<ConditionsConverter>();
-        for (Iterator iterator = element.getChildren("converter").iterator(); iterator.hasNext(); ) {
-            Element converterElement = (Element)iterator.next();
-            try {
-                Class converterClass = Class.forName(converterElement.getAttributeValue("class"));
-                if (ConditionsConverter.class.isAssignableFrom(converterClass)) {
-                    try {
-                        //System.out.println("adding converter: " + converterClass.getSimpleName());
-                        _converterList.add((ConditionsConverter)converterClass.newInstance());
-                    } catch (InstantiationException | IllegalAccessException e) {
-                        throw new RuntimeException(e);
-                    }
-                } else {
-                    throw new RuntimeException("The converter class " + converterClass.getSimpleName() + " does not extend the correct base type.");
-                }
-            } catch (ClassNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-    
-    List<ConditionsConverter> getConverterList() {
-        return _converterList;
-    }
-}

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsObjectCollection.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -5,14 +5,17 @@
 import java.util.Collections;
 import java.util.List;
 
+// TODO: This class should have a reference to its ConditionsRecord.
+// TODO: Collections with a mix of different collection IDs on their objects should always be read only.
 public class ConditionsObjectCollection<T extends ConditionsObject> {
 
-    List<T> objects = new ArrayList<T>();    
-    TableMetaData _tableMetaData;
-    int _collectionId = -1;
-    boolean _isReadOnly;
-    boolean _isDirty;
-    boolean _isNew;
+    protected List<T> _objects = new ArrayList<T>();    
+    protected TableMetaData _tableMetaData;
+    protected int _collectionId = -1;
+    protected boolean _isReadOnly;
+    protected boolean _isDirty;
+    protected boolean _isNew;
+    protected ConditionsRecord _conditionsRecord;
     
     protected ConditionsObjectCollection() {
     }
@@ -27,32 +30,36 @@
     }
     
     public T get(int index) {
-        return objects.get(index);
+        return _objects.get(index);
     }
     
     public List<T> getObjects() {
-        return Collections.unmodifiableList(objects);
+        return Collections.unmodifiableList(_objects);
     }
     
     public boolean contains(Object object) {
         return getObjects().contains(object);
     }
         
+    // TODO: Should check here if object has an existing collection ID that is different 
+    // from this collection's, in which case this collection becomes "mixed" and it should be
+    // flagged as read only.
     public void add(T object) throws ConditionsObjectException {
-        if (objects.contains(object)) {
+        if (_objects.contains(object)) {
             throw new IllegalArgumentException("Collection already contains this object.");
         }
         try {
-            // Only assign a collection ID to the object if this collection has a valid ID.
+            // Only assign a collection ID to the object if this collection has a valid ID
+            // and the object does not have one already.
             if (getCollectionId() != -1)
                 object.setCollectionId(getCollectionId());
         } catch (ConditionsObjectException x) {
             throw new IllegalArgumentException("Error assigning collection ID to object.", x);
         }
-        // Set the table meta data if the object does not have any.
+        // Set the table meta data on the object if it does not have any.
         if (object.getTableMetaData() == null && _tableMetaData != null)
             object.setTableMetaData(_tableMetaData);
-        objects.add(object);
+        _objects.add(object);
         if (!isNew())
             setIsDirty(true);
     }
@@ -64,40 +71,44 @@
     public int getCollectionId() {
         return _collectionId;
     }
-
-    public void updateAll() throws ConditionsObjectException {
-        for (ConditionsObject object : objects) {
+    
+    // TODO: Should this also insert new records that do not exist?
+    // TODO: This operation should lock the table.
+    public void update() throws ConditionsObjectException {
+        for (ConditionsObject object : _objects) {            
             object.update();
         }        
         setIsDirty(false);
     }
 
-    public void deleteAll() throws ConditionsObjectException {
+    // TODO: This does not need to loop.  It should just call delete on the collection ID value. 
+    public void delete() throws ConditionsObjectException {
         if (isReadOnly()) {
             throw new ConditionsObjectException("Collection is read only.");
         }
-        for (ConditionsObject object : objects) {            
+        for (ConditionsObject object : _objects) {            
             object.delete();
         }                
     }
 
-    public void selectAll() throws ConditionsObjectException, SQLException {
-        for (ConditionsObject object : objects) {
+    // TODO: This should not loop.  It should select all the objects with a matching collection ID
+    // from the database.
+    public void select() throws ConditionsObjectException, SQLException {
+        for (ConditionsObject object : _objects) {
             object.select();
         }
     }
 
-    // TODO: This method needs to get the next collection ID if it doesn't have one already.
-    public void insertAll() throws ConditionsObjectException, SQLException {
+    // TODO: This method needs to get the next collection ID from the conditions manager.
+    // TODO: This operation should lock the table.
+    public void insert() throws ConditionsObjectException, SQLException {
         if (!isNew()) {
             throw new ConditionsObjectException("Collection already exists in the database.");
         }
-        // FIXME: Should get the next global collection ID from the database here,
-        //        if collection ID is -1 (for new collection being added).
-        for (ConditionsObject object : objects) {
-            if (object.isNew()) {
-                object.insert();
-            }
+        for (ConditionsObject object : _objects) {
+            //if (object.isNew()) {
+            object.insert();
+            //}
         }
         _isNew = false;
     }
@@ -114,6 +125,7 @@
         _isDirty = isDirty;
     }
     
+    // TODO: This can probably just check if collection ID is not valid e.g. equals -1.    
     public boolean isNew() {
         return _isNew;
     }
@@ -131,4 +143,10 @@
     public void setIsReadOnly(boolean isReadOnly) {
         _isReadOnly = isReadOnly;
     }    
+    
+    public void setConditionsRecord(ConditionsRecord conditionsRecord) throws ConditionsObjectException {
+        if (_conditionsRecord != null)
+            throw new ConditionsObjectException("The ConditionsRecord is already set on this collection.");
+        _conditionsRecord = conditionsRecord;
+    }
 }

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsObjectConverter.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectConverter.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectConverter.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -5,9 +5,23 @@
 import java.sql.SQLException;
 
 import org.hps.conditions.ConditionsObject.FieldValueMap;
+import org.hps.conditions.ConditionsRecord.ConditionsRecordCollection;
 import org.lcsim.conditions.ConditionsConverter;
 import org.lcsim.conditions.ConditionsManager;
 
+/**
+ * <p>
+ * Implementation of default conversion from database tables to a {@link ConditionsObject} class.
+ * </p>
+ * <p>
+ * This class actually returns collections and not individual objects.
+ * </p> 
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+
+ * @param <T> The type of the returned data which should be a class extending 
+ * {@link ConditionsObjectCollection}. 
+ */
 public abstract class ConditionsObjectConverter<T> implements ConditionsConverter<T> {
     
     public ConditionsObjectConverter() {        
@@ -22,14 +36,11 @@
     
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public T getData(ConditionsManager conditionsManager, String name) {
+
+        //System.out.println("finding conditions for key " + name + " ...");
         
-        // This type of converter only works with the DatabaseConditionsManager class.
-        DatabaseConditionsManager databaseConditionsManager = null;
-        if (conditionsManager instanceof DatabaseConditionsManager) {
-            databaseConditionsManager = (DatabaseConditionsManager)conditionsManager;
-        } else {
-            throw new RuntimeException("This converter requires a ConditionsManager of type DatabaseConditionsManager.");
-        }
+        // Get the DatabaseConditionsManager which is required for using this converter.
+        DatabaseConditionsManager databaseConditionsManager = getDatabaseConditionsManager(conditionsManager);
         
         // Get the table meta data from the key given by the caller.
         TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(name);
@@ -45,29 +56,30 @@
         }
         
         // Get the ConditionsRecord with the meta-data, which will use the current run number from the manager.        
-        ConditionsRecordCollection conditionsRecords = ConditionsRecord.find(conditionsManager, name);
+        ConditionsRecordCollection conditionsRecords = databaseConditionsManager.findConditionsRecords(name);
                 
-        if (conditionsRecords.size() == 0) {
+        if (conditionsRecords.getObjects().size() == 0) {
             // There were no records returned, which is a fatal error.
             throw new RuntimeException("No conditions found with key: " + name);
-        } else if (conditionsRecords.size() > 1) {            
+        } else if (conditionsRecords.getObjects().size() > 1) {      
+            // There were multiple records returned.
             if (!allowMultipleCollections())
                 // If there are multiple records returned but this is not allowed by the converter, 
                 // then this is a fatal error.
                 throw new RuntimeException("Multiple conditions records returned but this is not allowed.");
         } else {
-            // The collection ID and table meta data are only set on the collection object 
-            // if all rows have the same collection ID.
+            // There was a single conditions record so the collection information can be set meaningfully.
             try {
                 collection.setCollectionId(conditionsRecords.get(0).getCollectionId());
                 collection.setTableMetaData(tableMetaData);
+                collection.setConditionsRecord(conditionsRecords.get(0));
             } catch (ConditionsObjectException e) {
                 throw new RuntimeException(e);
             }
         }
 
         // Loop over conditions records.  This will usually just be one record.
-        for (ConditionsRecord conditionsRecord : conditionsRecords) {
+        for (ConditionsRecord conditionsRecord : conditionsRecords.getObjects()) {
                     
             // Get the table name.
             String tableName = conditionsRecord.getTableName();
@@ -79,8 +91,7 @@
             String query = QueryBuilder.buildSelect(tableName, collectionId, tableMetaData.getFieldNames(), "id ASC");
         
             // Query the database.
-            // TODO: Get the connection from the manager rather than the static instance.
-            ResultSet resultSet = ConnectionManager.getConnectionManager().query(query);
+            ResultSet resultSet = databaseConditionsManager.query(query);
             
             try {
                 // Loop over rows.
@@ -101,7 +112,7 @@
         return (T)collection;
     }
 
-    private ConditionsObject createConditionsObject(ResultSet resultSet, 
+    protected ConditionsObject createConditionsObject(ResultSet resultSet, 
             TableMetaData tableMetaData) throws SQLException {
         ResultSetMetaData metaData = resultSet.getMetaData();
         int rowId = resultSet.getInt(1);
@@ -130,6 +141,14 @@
         return newObject;
     }
     
+    protected DatabaseConditionsManager getDatabaseConditionsManager(ConditionsManager conditionsManager) {
+        if (conditionsManager instanceof DatabaseConditionsManager) {
+            return (DatabaseConditionsManager)conditionsManager;
+        } else {
+            throw new RuntimeException("This converter requires a ConditionsManager of type DatabaseConditionsManager.");
+        }
+    }
+    
     public boolean allowMultipleCollections() {
         return false;
     }

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsRecord.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecord.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecord.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,84 +1,41 @@
 package org.hps.conditions;
 
-import static org.hps.conditions.TableConstants.CONDITIONS_RECORD;
-
-import java.sql.Blob;
-import java.sql.ResultSet;
-import java.sql.SQLException;
 import java.util.Date;
 
-import org.lcsim.conditions.CachedConditions;
-import org.lcsim.conditions.ConditionsManager;
-
 /**
  * This class represents a single record from the primary conditions data table,
  * which defines the validity range for a specific collection of conditions objects.
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
-public class ConditionsRecord {
+// TODO: Check behavior of select, delete, update and insert operations.
+// TODO: Override default behavior of methods in super class that don't make sense.
+public class ConditionsRecord extends AbstractConditionsObject {
 
-    int id;
-    int runStart;
-    int runEnd;
-    Date updated;
-    Date created;
-    Date validFrom;
-    Date validTo;
-    String createdBy;
-    String notes;
-    String name;
-    String formatVersion;
-    String tableName;
-    int collectionId;    
-                
-    protected ConditionsRecord() {        
-    }
-    
     /**
-     * Load state into this object from a ResultSet, which must be positioned a priori
-     * to the correct row number.
-     * @param rs The ResultSet containing database records from the conditions table.
+     * Collection type.
      */
-    void load(ResultSet rs) {
-        try {            
-            id = rs.getInt(1);
-            runStart = rs.getInt(2);
-            runEnd = rs.getInt(3);
-            updated = rs.getTimestamp(4);
-            created = rs.getTimestamp(5); // ??
-            validFrom = rs.getDate(6);
-            validTo = rs.getDate(7);
-            createdBy = rs.getString(8);
-            Blob blob = rs.getBlob(9);
-            if (blob != null) {
-                byte[] blobData = blob.getBytes(1, (int)blob.length());
-                notes = new String(blobData);
-            }
-            name = rs.getString(10);
-            formatVersion = rs.getString(11);
-            tableName = rs.getString(12);
-            collectionId = rs.getInt(13);
-            
-        } catch (SQLException e) {
-            throw new RuntimeException(e);
+    public static class ConditionsRecordCollection extends ConditionsObjectCollection<ConditionsRecord> {
+        /**
+         * Since ConditionsRecord collections are always "mixed", meaning the collection ID values
+         * are usually all going to be different, the default behavior of the super class is overridden.
+         */
+        public void add(ConditionsRecord record) {
+            _objects.add(record);
         }
+        
+        // FIXME: Should probably override more methods here that don't make sense for this type!
     }
-     
-    /**
-     * Get the unique ID.
-     * @return The unique ID.
-     */
-    public int getId() {
-        return id;
+                      
+    protected ConditionsRecord() {        
     }
-    
+                   
     /**
      * Get the starting run number.
      * @return The starting run number.
      */
     public int getRunStart() {
-        return runStart;
+        return getFieldValue("run_start");
     }
     
     /**
@@ -86,7 +43,7 @@
      * @return The ending run number.
      */
     public int getRunEnd() {
-        return runEnd;
+        return getFieldValue("run_end");
     }
     
     /**
@@ -94,7 +51,7 @@
      * @return The date this record was updated.
      */
     public Date getUpdated() {
-        return updated;
+        return getFieldValue("updated");
     }
     
     /**
@@ -102,7 +59,7 @@
      * @return The date this record was created.
      */
     public Date getCreated() {
-        return created;
+        return getFieldValue("created");
     }
     
     /**
@@ -110,7 +67,7 @@
      * @return The starting valid time.
      */
     public Date getValidFrom() {
-        return validFrom;
+        return getFieldValue("valid_from");
     }
     
     /**
@@ -118,7 +75,7 @@
      * @return The ending valid time.
      */
     public Date getValidTo() {
-        return validTo;
+        return getFieldValue("valid_to");                
     }
 
     /**
@@ -126,7 +83,7 @@
      * @return The name of the person who created the record.
      */
     public String getCreatedBy() {
-        return createdBy;
+        return getFieldValue("created_by");
     }
 
     /**
@@ -134,15 +91,16 @@
      * @return The notes about this condition.
      */
     public String getNotes() {
-        return notes;
+        return getFieldValue("notes");
     }
     
     /**
      * Get the name of these conditions, which should be unique by run number.
+     * This is called the "key" in the table meta data to distinguish it from "table name".
      * @return The name of the conditions.
      */
     public String getName() {
-        return name;
+        return getFieldValue("name");
     }
     
     /**
@@ -150,7 +108,7 @@
      * @return The conditions version.
      */
     public String getFormatVersion() {
-        return formatVersion;
+        return getFieldValue("format_version");
     }
     
     /**
@@ -158,90 +116,36 @@
      * @return The name of the table with the conditions data. 
      */
     public String getTableName() {
-        return tableName;
+        return getFieldValue("table_name");
     }
-        
+    
     /**
-     * Get the value of the identifying field.
-     * @return The value of identifying field for these conditions.
+     * Get the collection ID, overriding this method from the parent class.
+     * @return The collection ID.
      */
     public int getCollectionId() {
-        return collectionId;
-    }    
-    
+        return getFieldValue("collection_id");
+    }
+           
     /**
      * Convert this record to a human readable string, one field per line.
      * @return This object represented as a string.
      */
     public String toString() {
         StringBuffer buff = new StringBuffer();
-        buff.append("id: " + id + '\n');
-        buff.append("runStart: " + runStart + '\n');
-        buff.append("runEnd: " + runEnd + '\n');
-        buff.append("updated: " + updated + '\n');
-        buff.append("created: " + created + '\n');
-        buff.append("validFrom: " + validFrom + '\n');
-        buff.append("validTo: " + validTo + '\n');
-        buff.append("createdBy: " + createdBy + '\n');
-        buff.append("notes: " + notes + '\n');
-        buff.append("formatVersion: " + formatVersion + '\n');
-        buff.append("tableName: " + tableName + '\n');
-        buff.append("collectionId: " + collectionId + '\n');
+        buff.append("id: " + getRowId() + '\n');
+        buff.append("name: " + getName() + '\n');
+        buff.append("runStart: " + getRunStart() + '\n');
+        buff.append("runEnd: " + getRunEnd() + '\n');
+        buff.append("tableName: " + getTableName() + '\n');
+        buff.append("collectionId: " + getCollectionId() + '\n');
+        buff.append("updated: " + getUpdated() + '\n');
+        buff.append("created: " + getCreated() + '\n');
+        buff.append("validFrom: " + getValidFrom() + '\n');
+        buff.append("validTo: " + getValidTo() + '\n');
+        buff.append("createdBy: " + getCreatedBy() + '\n');
+        buff.append("formatVersion: " + getFormatVersion() + '\n');
+        buff.append("notes: " + getNotes() + '\n');        
         return buff.toString();
-    }
-    
-    /**
-     * Find a ConditionsRecord with conditions key matching <code>name</code>.
-     * @param manager The current conditions manager.
-     * @param name The name of the conditions key.
-     * @return The matching ConditionsRecord.
-     * @throws IllegalArgumentException if no records are found.
-     * @throws IllegalArgumentException if more than one record is found.
-     */
-    public static ConditionsRecordCollection find(ConditionsManager manager, String name) {
-        CachedConditions<ConditionsRecordCollection> c = manager.getCachedConditions(ConditionsRecordCollection.class, CONDITIONS_RECORD);
-        ConditionsRecordCollection conditionsRecords = c.getCachedData();
-        conditionsRecords = conditionsRecords.find(name);
-        if (conditionsRecords.size() == 0) {
-            throw new IllegalArgumentException("No ConditionsRecord with name: " + name);
-        }              
-        return conditionsRecords;
-    }
-    
-    /**
-     * Find conditions records of all types in the database by run number.
-     * @param run The run number.
-     * @return The set of matching ConditionsRecords.
-     */
-    public static ConditionsRecordCollection find(int run) {
-        
-        ConditionsRecordCollection conditionsRecords = new ConditionsRecordCollection();
-        
-        ConnectionManager manager = ConnectionManager.getConnectionManager();
-        String db = manager.getConnectionParameters().getDatabase();
-        String table = manager.getConnectionParameters().getConditionsTable();
-                
-        String query = "SELECT * FROM " 
-                + db + "." + table                       
-                + " WHERE "
-                + "run_start <= "
-                + run
-                + " AND run_end >= "
-                + run;
-        
-        ResultSet resultSet = manager.query(query);
-            
-        // Iterate over conditions records.
-        try {
-            while (resultSet.next()) {
-                ConditionsRecord record = new ConditionsRecord();
-                record.load(resultSet);
-                conditionsRecords.add(record);
-            } 
-        } catch (SQLException x) {
-            throw new RuntimeException("Database error", x);
-        } 
-                   
-        return conditionsRecords;
-    }
+    }          
 }
\ No newline at end of file

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsRecordCollection.java removed after 341
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecordCollection.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecordCollection.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,26 +0,0 @@
-package org.hps.conditions;
-
-import java.util.ArrayList;
-
-/**
- * This is a simple container class for objects with the type <code>ConditionsRecord</code>.
- * @author Jeremy McCormick <[log in to unmask]>
- */
-public class ConditionsRecordCollection extends ArrayList<ConditionsRecord> {
-            
-    /**
-     * Find a ConditionsRecord by its name or key in this collection.  
-     * This is the 'name' field from the conditions database table. 
-     * @param name The name of the conditions set, e.g. 'svt_calibrations' etc.
-     * @return The collection of ConditionsRecords, which can be empty if none were found.
-     */
-    public ConditionsRecordCollection find(String name) {
-        ConditionsRecordCollection records = new ConditionsRecordCollection();
-        for (ConditionsRecord rec : this) {
-            if (rec.getName().equals(name)) {
-                records.add(rec);
-            }
-        }
-        return records;
-    }        
-}
\ No newline at end of file

java/trunk/conditions/src/main/java/org/hps/conditions
ConditionsRecordConverter.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecordConverter.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsRecordConverter.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -3,7 +3,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
-import org.lcsim.conditions.ConditionsConverter;
+import org.hps.conditions.ConditionsRecord.ConditionsRecordCollection;
 import org.lcsim.conditions.ConditionsManager;
 
 /**
@@ -11,44 +11,52 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @version $Id: ConditionsRecordConverter.java,v 1.5 2013/10/15 23:24:47 jeremy Exp $
  */
-public class ConditionsRecordConverter implements ConditionsConverter<ConditionsRecordCollection> {
+public class ConditionsRecordConverter extends ConditionsObjectConverter<ConditionsRecordCollection> {
                        
     /**
-     * Get the ConditionsRecords for a run.  This method ignores the name argument 
-     * and will fetch all conditions records for the current run.
+     * Get the ConditionsRecords for a run based on current configuration of the
+     * <code>DatabaseConditionsManager</code>.   
      * @param manager The current conditions manager.
      * @param name The name of the conditions set.
      * @return The matching ConditionsRecords.
      */
     public ConditionsRecordCollection getData(ConditionsManager manager, String name) {
                                 
-        ConditionsRecordCollection records = new ConditionsRecordCollection();
+        DatabaseConditionsManager databaseConditionsManager = getDatabaseConditionsManager(manager);
+        TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(name);
         
-        ConnectionManager connectionManager = ConnectionManager.getConnectionManager();
-        
-        String tableName = connectionManager.getConnectionParameters().getConditionsTable();
-        
         String query = "SELECT * from " 
-                + tableName
+                + name
                 + " WHERE "
                 + "run_start <= "
                 + manager.getRun()
                 + " AND run_end >= "
                 + manager.getRun();
                
-        ResultSet resultSet = connectionManager.query(query);
+        ResultSet resultSet = databaseConditionsManager.query(query);
         
+        // Create a collection to return.
+        ConditionsObjectCollection collection;
         try {
+             collection = tableMetaData.getCollectionClass().newInstance();
+        } catch (InstantiationException | IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+        
+        try {
             while(resultSet.next()) {                  
-                ConditionsRecord record = new ConditionsRecord();
-                record.load(resultSet);
-                records.add(record);
+                ConditionsObject conditionsRecord = createConditionsObject(resultSet, tableMetaData);
+                try {
+                    collection.add(conditionsRecord);
+                } catch (ConditionsObjectException e) {
+                    throw new RuntimeException(e);
+                }
             }            
         } catch (SQLException x) {
             throw new RuntimeException("Database error", x);
         } 
         
-        return records;
+        return getType().cast(collection);
     }
 
     /**
@@ -58,4 +66,8 @@
     public Class<ConditionsRecordCollection> getType() {
         return ConditionsRecordCollection.class;
     }        
+    
+    public boolean allowMultipleCollections() {
+        return true;
+    }
 }
\ No newline at end of file

java/trunk/conditions/src/main/java/org/hps/conditions
ConnectionManager.java removed after 341
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConnectionManager.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConnectionManager.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,157 +0,0 @@
-package org.hps.conditions;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-/**
- * This class provides various database utilities for the conditions system, primarily the
- * converter classes.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
- */
-public class ConnectionManager {
-
-    private ConnectionParameters _connectionParameters;
-    private static ConnectionManager _instance = null;
-    private Connection _connection = null;
-
-    /**
-     * Class constructor.  Override at your own risk!
-     */
-    protected ConnectionManager() {
-    }
-    
-    /**
-     * Get the singleton instance of this class.
-     * @return The instance of this class.
-     */
-    public static ConnectionManager getConnectionManager() {
-        if (_instance == null) {
-            _instance = new ConnectionManager();
-        }
-        return _instance;
-    }
-
-    /**
-     * Set the connection parameters.
-     * @param connectionParameters The connection parameters.
-     */
-    void setConnectionParameters(ConnectionParameters connectionParameters) {
-        this._connectionParameters = connectionParameters;
-    }
-
-    /**
-     * Get the connection parameters.
-     * @return The connection parameters.
-     */
-    public ConnectionParameters getConnectionParameters() {
-        return _connectionParameters;
-    }
-
-    /**
-     * Create a connection to the database.
-     * @return The database connection.
-     */
-    Connection createConnection() {
-        if (_connectionParameters == null)
-            throw new RuntimeException("Connection parameters have not been set.");
-        Connection newConnection = _connectionParameters.createConnection();
-        try {
-            System.out.println("USE " + _connectionParameters.getDatabase());
-            newConnection.createStatement().execute("USE " + _connectionParameters.getDatabase());
-        } catch (SQLException e) {
-            throw new RuntimeException("Failed to connect to database.", e);
-        }
-        return newConnection;
-    }
-
-    /**
-     * Cleanup a connection.
-     * @param connection The Connection to cleanup.
-     */
-    public void cleanup(Connection connection) {
-        if (connection != null) {
-            try {
-                if (!connection.isClosed())
-                    connection.close();
-                else
-                    System.err.println("Connection already closed!");
-            } catch (SQLException x) {
-                throw new RuntimeException("Failed to close connection.", x);
-            }
-        }
-    }
-
-    /**
-     * Cleanup a result set, or the Statement connected to it.
-     * @param resultSet The ResultSet to cleanup.
-     */
-    public void cleanup(ResultSet resultSet) {
-        if (resultSet != null) {
-            try {
-                // This should close the ResultSet itself, too.
-                Statement statement = resultSet.getStatement();
-                if (statement != null)
-                    if (!statement.isClosed())
-                        statement.close();
-                    else
-                        System.err.println("Statement already closed!");
-            } catch (SQLException x) {
-                throw new RuntimeException("Failed to close statement.", x);
-            }
-        }
-    }
-
-    /**
-     * This method can be used to perform a database query. 
-     * @param query The SQL query string.
-     * @return The ResultSet from the query or null.
-     */
-    public ResultSet query(String query) {
-        
-        System.out.println(query);
-        
-        if (_connection == null)
-            _connection = createConnection();
-        ResultSet result = null;
-        try {
-            Statement statement = _connection.createStatement();
-            result = statement.executeQuery(query);
-        } catch (SQLException x) {
-            throw new RuntimeException("Error in query: " + query, x);
-        }
-        return result;
-    }
-    
-    /**
-     * Perform a query with an update SQL command like INSERT, DELETE or UPDATE.
-     * @return query The SQL query string.
-     * @return The number of rows affected.
-     */
-    public int update(String query) {
-        
-        System.out.println(query);
-        
-        if (_connection == null)
-            _connection = createConnection();
-        int key = -1;
-        try {
-            // NOTE: Assumes only one row is updated!
-            Statement statement = _connection.createStatement();
-            statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS); 
-            ResultSet resultSet = statement.getGeneratedKeys();
-            if (resultSet.next()) {
-                key = resultSet.getInt(1);
-            }
-        } catch (SQLException x) {
-            throw new RuntimeException("Error in query: " + query, x);
-        }
-        return key;
-    }
-        
-    public void disconnect() {
-        cleanup(_connection);
-    }  
-}

java/trunk/conditions/src/main/java/org/hps/conditions
ConnectionParameters.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConnectionParameters.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConnectionParameters.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,12 +1,13 @@
 package org.hps.conditions;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.Properties;
 
-import org.jdom.Element;
-
 /**
  * This class encapsulates the parameters for connecting to a database, 
  * including hostname, port, user and password.  It can also create and 
@@ -21,7 +22,6 @@
     private int port;
     private String hostname;
     private String database;
-    private String conditionsTable;
 
     /**
      * Fully qualified constructor.
@@ -31,20 +31,19 @@
      * @param port The port number.
      * @param conditionsTable The table containing conditions validity data.
      */
-    ConnectionParameters(String user, String password, String database, String hostname, int port, String conditionsTable) {
+    ConnectionParameters(String user, String password, String database, String hostname, int port) {
         this.user = user;
         this.password = password;
         this.database = database;
         this.hostname = hostname;
         this.port = port;
-        this.conditionsTable = conditionsTable;
     }
 
     /**
      * Get Properties object for this connection.
      * @return The Properties for this connection.
      */
-    public Properties getConnectionProperties() {
+    Properties getConnectionProperties() {
         Properties p = new Properties();
         p.put("user", user);
         p.put("password", password);
@@ -55,7 +54,7 @@
      * Get the hostname.
      * @return The hostname.
      */
-    public String getHostname() {
+    String getHostname() {
         return hostname;
     }
 
@@ -63,7 +62,7 @@
      * Get the port number.
      * @return The port number.
      */
-    public int getPort() {
+    int getPort() {
         return port;
     }
     
@@ -71,21 +70,21 @@
      * Get the name of the database.
      * @return The name of the database.
      */
-    public String getDatabase() {
+    String getDatabase() {
         return database;
     }
     
     /**
      * Get the user name.
      */
-    public String getUser() {
+    String getUser() {
         return user;
     }
     
     /**
      * Get the password.
      */
-    public String getPassword() {
+    String getPassword() {
         return password;
     }
 
@@ -93,28 +92,21 @@
      * Get the connection string for these parameters.
      * @return The connection string.
      */
-    public String getConnectionString() {
+    String getConnectionString() {
         return "jdbc:mysql://" + hostname + ":" + port + "/";
     }       
     
     /**
-     * Get the name of the conditions validity data.
-     * @return The name of the conditions validity data table. 
-     */
-    public String getConditionsTable() {
-        return conditionsTable;
-    }
-    
-    /**
      * Create a database connection from these parameters.  
-     * The caller is responsible for closing it when finished.
+     * The caller becomes the "owner" and is responsible for closing it when finished.
      * @return The Connection object.
      */
-    public Connection createConnection() {
+    Connection createConnection() {               
         Properties connectionProperties = getConnectionProperties();
         Connection connection = null;
         try {
             connection = DriverManager.getConnection(getConnectionString(), connectionProperties);
+            connection.createStatement().execute("USE " + getDatabase());
         } catch (SQLException x) {
             throw new RuntimeException("Failed to connect to database: " + getConnectionString(), x);
         }
@@ -122,22 +114,22 @@
     }
     
     /**
-     * Create the connection parameters from an XML container node 
-     * with the appropriate child elements.    
-     * @param element The connection XML element.
-     * @return The ConnectionParameters created from XML.
+     * Configure the connection parameters from a properties file. 
+     * @param file The properties file.
+     * @return The connection parameters.
      */
-    public static final ConnectionParameters fromXML(Element element) {
-        if (element.getChild("user") == null)
-            throw new IllegalArgumentException("missing user element");
-        String user = element.getChild("user").getText();
-        if (element.getChild("password") == null)
-            throw new IllegalArgumentException("missing password element");
-        String password = element.getChild("password").getText();
-        String database = element.getChild("database").getText();
-        String hostname = element.getChild("hostname").getText();
-        int port = Integer.parseInt(element.getChild("port").getText());
-        String conditionsTable = element.getChild("conditions_table").getText();
-        return new ConnectionParameters(user, password, database, hostname, port, conditionsTable);        
+    public static final ConnectionParameters fromProperties(File file) {
+        Properties properties = new Properties();
+        try {
+            properties.load(new FileInputStream(file));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        String user = properties.getProperty("user");
+        String password = properties.getProperty("password");
+        String database = properties.getProperty("database");
+        String hostname = properties.getProperty("hostname");
+        int port = Integer.parseInt(properties.getProperty("port"));
+        return new ConnectionParameters(user, password, database, hostname, port);
     }
 }

java/trunk/conditions/src/main/java/org/hps/conditions
DatabaseConditionsManager.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/DatabaseConditionsManager.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/DatabaseConditionsManager.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -5,8 +5,10 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -16,6 +18,7 @@
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 
+import org.hps.conditions.ConditionsRecord.ConditionsRecordCollection;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
@@ -38,19 +41,20 @@
  * </p>
  * 
  * @author Jeremy McCormick <[log in to unmask]>
- */
-// TODO: Move query methods from ConnectionManager to this API so that ConnectionManager need not 
-// be itself statically accessible.  Add access to ConnectionManager object to this class.
+ */ 
 public class DatabaseConditionsManager extends LCSimConditionsManagerImplementation {
 
     static DatabaseConditionsManager _instance;
     int _runNumber = -1;
     String _detectorName;
-    List<TableMetaData> _tableData;
+    List<TableMetaData> _tableMetaData;
     List<ConditionsConverter> _converters;
+    File _connectionPropertiesFile;
     ConditionsReader _baseReader;    
     static Logger _logger = null;
-    ConnectionManager _connectionManager;
+    ConnectionParameters _connectionParameters;
+    Connection _connection;
+    String _conditionsTableName;
 
     /**
      * Constructor is set to private as this class should not be instantiated directly. Use
@@ -72,16 +76,17 @@
     }
 
     /**
-     * Setup the logger.
+     * Setup the logger for this class.
      */
     static {
         _logger = Logger.getLogger(DatabaseConditionsManager.class.getSimpleName());
         _logger.setUseParentHandlers(false);
         _logger.setLevel(Level.ALL);
         ConsoleHandler handler = new ConsoleHandler();
+        handler.setLevel(Level.ALL);
         handler.setFormatter(new LogFormatter());
         _logger.addHandler(handler);
-        _logger.info("setup logger");
+        _logger.config("logging initialized with level " + handler.getLevel());
     }
 
     /**
@@ -115,16 +120,18 @@
                 if (_baseReader == null)
                     // Setup the default base reader to handle classpath resources.
                     _baseReader = new BaseClasspathConditionsReader(_detectorName);
-
                 _logger.config("using base conditions reader: " + _baseReader.getClass().getSimpleName());
+                
                 // Set the ConditionsReader on the manager.
                 setConditionsReader(new DatabaseConditionsReader(_baseReader), _detectorName);
+                                
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
 
-            _logger.config("setting up with detector: " + _detectorName);
-            _logger.config("setting up with run number: " + _runNumber);
+            _logger.config("setting detector: " + _detectorName);
+            _logger.config("setting run number: " + _runNumber);
+            
             // Setup the manager with the detector and run number.
             setDetector(_detectorName, _runNumber);
         } catch (ConditionsNotFoundException e) {
@@ -133,7 +140,7 @@
     }
 
     /**
-     * Set the run number. This will not trigger conditions change until {@link #setup()} is
+     * Set the run number. This will not trigger conditions change until {@link #setup()} is
      * called.
      * @param runNumber The new run number.
      */
@@ -142,7 +149,7 @@
     }
 
     /**
-     * Set the detector name. This will not trigger conditions change until {@link #setup()} is
+     * Set the detector name. This will not trigger conditions change until {@link #setup()} is
      * called.
      * @param detectorName The name of the new detector.
      */
@@ -167,7 +174,7 @@
     }
 
     /**
-     * Get the lcsim compact Detector object from the conditions system.
+     * Get the lcsim compact <code>Detector</code> object from the conditions system.
      * @return The detector object.
      */
     public Detector getDetectorObject() {
@@ -178,10 +185,11 @@
      * Get conditions data by class and name.
      * @param type The class of the conditions.
      * @param name The name of the conditions set.
-     * @return The conditions or null (???) if does not exist.
+     * @return The conditions or null if does not exist.
      */
+    // TODO: Need to check if this returns null or will throw an exception if does not exist.
     public <T> T getConditionsData(Class<T> type, String name) {
-        _logger.info("getting conditions " + name + " of type " + type.getSimpleName());
+        _logger.fine("getting conditions " + name + " of type " + type.getSimpleName());
         return getCachedConditions(type, name).getCachedData();
     }
 
@@ -209,12 +217,22 @@
      * @param resource The embedded XML resource.
      */
     public void configure(String resource) {
-        _logger.config("configuring from resource: " + resource);
+        _logger.config("configuring manager from resource: " + resource);
         InputStream in = getClass().getResourceAsStream(resource);
         if (in == null)
             throw new IllegalArgumentException("The resource does not exist.");
         configure(in);
     }
+    
+    /**
+     * Set the path to a properties file containing connection settings.
+     * @param path
+     */
+    public void setConnectionProperties(String path) {
+        _connectionPropertiesFile = new File(path);
+        if (!_connectionPropertiesFile.exists())
+            throw new IllegalArgumentException("The connection properties file does not exist: " + _connectionPropertiesFile.getPath());
+    }
 
     /**
      * Set externally the base ConditionsReader that will be used to find non-database conditions
@@ -226,15 +244,17 @@
     }
 
     /**
-     * Get the next collection ID for a database table.
+     * Get the next collection ID for a database conditions table.
      * @param tableName The name of the table.
      * @return The next collection ID.
      */
+    // TODO: If there are no collections that exist, this method should simply return the value '1'
+    // or it could throw an exception.
     public int getNextCollectionId(String tableName) {
         TableMetaData tableData = findTableMetaData(tableName);
         if (tableData == null)
             throw new IllegalArgumentException("There is no meta data for table " + tableName);
-        ResultSet resultSet = ConnectionManager.getConnectionManager().query("SELECT MAX(collection_id)+1 FROM " + tableName);
+        ResultSet resultSet = query("SELECT MAX(collection_id)+1 FROM " + tableName);
         int collectionId = -1;
         try {
             resultSet.next();
@@ -242,6 +262,7 @@
         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
+        _logger.fine("new collection ID " + collectionId + " created for table " + tableName);
         return collectionId;
     }
 
@@ -250,7 +271,7 @@
      * @return The list of table meta data.
      */
     public List<TableMetaData> getTableMetaDataList() {
-        return _tableData;
+        return _tableMetaData;
     }
 
     /**
@@ -259,28 +280,174 @@
      * @return The table's meta data or null if does not exist.
      */
     public TableMetaData findTableMetaData(String name) {
-        for (TableMetaData meta : _tableData) {
+        for (TableMetaData meta : _tableMetaData) {
             if (meta.getTableName().equals(name))
                 return meta;
         }
         return null;
     }
+    
+    /**
+     * Find meta data by collection class type.
+     * @param type The collection class.
+     * @return The table meta data.
+     */
+    public TableMetaData findTableMetaData(Class type) {
+        for (TableMetaData meta : _tableMetaData) {
+            if (meta.getCollectionClass().equals(type)) {
+                return meta;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * This method can be used to perform a database SELECT query. 
+     * @param query The SQL query string.
+     * @return The ResultSet from the query or null.
+     */
+    public ResultSet query(String query) {
+        _logger.fine(query);
+        ResultSet result = null;
+        Statement statement = null;
+        try {
+            statement = _connection.createStatement();
+            result = statement.executeQuery(query);
+        } catch (SQLException x) {
+            throw new RuntimeException("Error in query: " + query, x);
+        } 
+        return result;
+    }
+    
+    /**
+     * Perform a SQL query with an update command like INSERT, DELETE or UPDATE.
+     * @param query The SQL query string.
+     * @return The keys of the rows affected.
+     */
+    public List<Integer> update(String query) {        
+        _logger.fine(query);
+        List<Integer> keys = new ArrayList<Integer>();
+        Statement statement = null;
+        try {
+            statement = _connection.createStatement();
+            statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS); 
+            ResultSet resultSet = statement.getGeneratedKeys();            
+            while (resultSet.next()) {
+                int key = resultSet.getInt(1);
+                keys.add(key);
+            }
+        } catch (SQLException x) {
+            throw new RuntimeException("Error in SQL query: " + query, x);
+        } finally {
+            close(statement);
+        }
+        return keys;
+    }
+                
+    /**
+     * Set the log level.
+     * @param level The log level.
+     */
+    public void setLogLevel(Level level) {
+        _logger.setLevel(level);
+        _logger.getHandlers()[0].setLevel(level);
+        _logger.config("set log level to " + level);
+    }
+    
+    /**
+     * Get the name of the conditions table containing validity data.
+     * @return The name of the conditions table with validity data.
+     */
+    public String getConditionsTableName() {
+        return _conditionsTableName;
+    }
 
+    /**
+     * Find a collection of conditions validity records by key name.
+     * The key name is distinct from the table name, but they are usually
+     * set to the same value in the XML configuration.    
+     * @param name The conditions key name.
+     * @return The set of matching conditions records.
+     */
+    public ConditionsRecordCollection findConditionsRecords(String name) {
+        ConditionsRecordCollection runConditionsRecords = getConditionsData(ConditionsRecordCollection.class, getConditionsTableName());
+        _logger.fine("searching for condition " + name + " in " + runConditionsRecords.getObjects().size() + " records ...");
+        ConditionsRecordCollection foundConditionsRecords = new ConditionsRecordCollection();
+        for (ConditionsRecord record : runConditionsRecords.getObjects()) {
+            if (record.getName().equals(name)) {
+                foundConditionsRecords.add(record);
+            }
+        }
+        if (foundConditionsRecords.getObjects().size() > 0) {
+            for (ConditionsRecord record : foundConditionsRecords.getObjects()) {
+                _logger.fine("found ConditionsRecord with key " + name + " ..." 
+                        + '\n' + foundConditionsRecords.get(0).toString());
+            }
+            _logger.fine("");
+        }
+        return foundConditionsRecords;
+    }    
+        
+    /**
+     * Close a JDBC <code>Statement</code>.
+     * @param statement The Statement to close.
+     */
+    static void close(Statement statement) {
+        if (statement != null) {
+            try {
+                if (!statement.isClosed())
+                    statement.close();
+                else
+                    _logger.log(Level.WARNING, "Statement is already closed!");
+            } catch (SQLException x) {
+                throw new RuntimeException("Failed to close statement.", x);
+            }
+        }
+    }
+    
+    /**
+     * Close a JDBC <code>ResultSet</code>, or rather the Statement connected to it.
+     * @param resultSet The ResultSet to close.
+     */
+    static void close(ResultSet resultSet) {        
+        if (resultSet != null) {
+            try {
+                Statement statement = resultSet.getStatement();
+                if (!statement.isClosed())
+                    statement.close();
+                else
+                    _logger.log(Level.WARNING, "Statement is already closed!");
+            } catch (SQLException x) {
+                throw new RuntimeException("Failed to close statement.", x);
+            }
+        }
+    }
+
+    /**
+     * Configure this class from an <code>InputStream</code> which should point 
+     * to an XML document.
+     * @param in The InputStream.
+     */
     private void configure(InputStream in) {
 
         // Create XML document.
         Document config = createDocument(in);
 
-        // Load the connection parameters from XML.
-        loadConnectionParameters(config);
-
         // Load the table meta data from XML.
         loadTableMetaData(config);
 
         // Load the converter classes from XML.
-        loadConverters(config);
+        loadConverters(config);        
+        
+        // Open a connection to the database.
+        openConnection();
     }
-
+    
+    /**
+     * Create an XML document from an <code>InputStream</code>.
+     * @param in The InputStream.
+     * @return The XML document.
+     */
     private Document createDocument(InputStream in) {
         // Create an XML document from an InputStream.
         SAXBuilder builder = new SAXBuilder();
@@ -293,40 +460,69 @@
         return config;
     }
 
+    /**
+     * Load data converters from an XML document.
+     * @param config The XML document.
+     */
     private void loadConverters(Document config) {
+        
         // Load the list of converters from the "converters" section of the config document.
         (this.new ConditionsConverterLoader()).load(config.getRootElement().getChild("converters"));
 
         // Register the list of converters with this manager.
-        // FIXME: Should this happen here or when setup is called?
+        // FIXME: Should this happen here or when setup is called on the manager?
         for (ConditionsConverter converter : _converters) {
             registerConditionsConverter(converter);
-            _logger.config("registered converter " + converter.getClass().getSimpleName() + " which handles type " + converter.getType().getSimpleName());
+            _logger.config("registered converter " + converter.getClass().getSimpleName());
         }
+        
+        // Find the mandatory converter for ConditionsRecord class which must be present in the configuration.
+        TableMetaData conditionsTableMetaData = findTableMetaData(ConditionsRecordCollection.class);
+        if (conditionsTableMetaData == null) {
+            throw new RuntimeException("No conditions converter found for ConditionsRecord type in the supplied configuration.");            
+        }
+        _conditionsTableName = conditionsTableMetaData.getTableName();
+        _logger.config("conditions validity table set to " + _conditionsTableName);
     }
-
+    
+    /**
+     * Load table meta data configuration from an XML document.
+     * @param config The XML document.
+     */
     private void loadTableMetaData(Document config) {
         // Load table meta data from the "tables" section of the config document.
         (this.new TableMetaDataLoader()).load(config.getRootElement().getChild("tables"));
     }
-
-    private void loadConnectionParameters(Document config) {
-        // Setup the connection parameters from the "connection" section of the config document.
-        _connectionManager = ConnectionManager.getConnectionManager();
-        _connectionManager.setConnectionParameters(
-                ConnectionParameters.fromXML(config.getRootElement().getChild("connection")));
-        ConnectionParameters p = _connectionManager.getConnectionParameters();
-        
-        _logger.config("set connection parameters ...");
-        _logger.config("database: " + p.getDatabase());
-        _logger.config("user: " + p.getUser());
-        _logger.config("password: " + p.getPassword());
-        _logger.config("hostname: " + p.getHostname());
-        _logger.config("port: " + p.getPort());
-        _logger.config("connection: " + p.getConnectionString());
+    
+    /**
+     * Open the database connection.
+     */
+    private void openConnection() {
+        if (_connectionPropertiesFile == null)
+            throw new RuntimeException("Connection properties were not set.");
+        _connectionParameters = ConnectionParameters.fromProperties(_connectionPropertiesFile); 
+        _connection = _connectionParameters.createConnection();
+        _logger.config("created connection: " + _connectionParameters.getConnectionString());
     }
-
+    
     /**
+     * Close the database connection.
+     */
+    private void closeConnection() {
+        if (_connection != null) {
+            try {
+                if (!_connection.isClosed()) {
+                    _connection.close();
+                }
+            } catch (SQLException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        _connection = null;
+        _connectionParameters = null;
+    }
+       
+    /**
      * This class loads an XML configuration of conditions table meta data.
      * 
      * @author Jeremy McCormick <[log in to unmask]>
@@ -340,14 +536,13 @@
          */
         void load(Element element) {
 
-            _tableData = new ArrayList<TableMetaData>();
+            _tableMetaData = new ArrayList<TableMetaData>();
 
             for (Iterator<?> iterator = element.getChildren("table").iterator(); iterator.hasNext();) {
                 Element tableElement = (Element) iterator.next();
                 String tableName = tableElement.getAttributeValue("name");
+                String key = tableElement.getAttributeValue("key");
 
-                // System.out.println("tableName: " + tableName);
-
                 Element classesElement = tableElement.getChild("classes");
                 Element classElement = classesElement.getChild("object");
                 Element collectionElement = classesElement.getChild("collection");
@@ -355,21 +550,14 @@
                 String className = classElement.getAttributeValue("class");
                 String collectionName = collectionElement.getAttributeValue("class");
 
-                // System.out.println("className: " + className);
-                // System.out.println("collectionName: " + collectionName);
-
                 Class<? extends ConditionsObject> objectClass;
                 Class<?> rawObjectClass;
                 try {
                     rawObjectClass = Class.forName(className);
-                    // System.out.println("created raw object class: " +
-                    // rawObjectClass.getSimpleName());
                     if (!ConditionsObject.class.isAssignableFrom(rawObjectClass)) {
                         throw new RuntimeException("The class " + rawObjectClass.getSimpleName() + " does not extend ConditionsObject.");
                     }
                     objectClass = (Class<? extends ConditionsObject>) rawObjectClass;
-                    // System.out.println("created ConditionsObject class: " +
-                    // objectClass.getSimpleName());
                 } catch (ClassNotFoundException e) {
                     throw new RuntimeException(e);
                 }
@@ -378,8 +566,6 @@
                 Class<?> rawCollectionClass;
                 try {
                     rawCollectionClass = Class.forName(collectionName);
-                    // System.out.println("created raw collection class: " +
-                    // rawCollectionClass.getSimpleName());
                     if (!ConditionsObjectCollection.class.isAssignableFrom(rawCollectionClass))
                         throw new RuntimeException("The class " + rawCollectionClass.getSimpleName() + " does not extend ConditionsObjectCollection.");
                     collectionClass = (Class<? extends ConditionsObjectCollection<?>>) rawCollectionClass;
@@ -387,22 +573,15 @@
                     throw new RuntimeException(e);
                 }
 
-                TableMetaData tableData = new TableMetaData(tableName, objectClass, collectionClass);
-
+                TableMetaData tableData = new TableMetaData(key, tableName, objectClass, collectionClass);
                 Element fieldsElement = tableElement.getChild("fields");
-
                 for (Iterator<?> fieldsIterator = fieldsElement.getChildren("field").iterator(); fieldsIterator.hasNext();) {
                     Element fieldElement = (Element) fieldsIterator.next();
-
                     String fieldName = fieldElement.getAttributeValue("name");
-                    // System.out.println("field: " + fieldName);
-
                     tableData.addField(fieldName);
                 }
 
-                _tableData.add(tableData);
-
-                // System.out.println();
+                _tableMetaData.add(tableData);
             }
         }      
     }
@@ -423,8 +602,6 @@
                     Class converterClass = Class.forName(converterElement.getAttributeValue("class"));
                     if (ConditionsConverter.class.isAssignableFrom(converterClass)) {
                         try {
-                            // System.out.println("adding converter: " +
-                            // converterClass.getSimpleName());
                             _converters.add((ConditionsConverter) converterClass.newInstance());
                         } catch (InstantiationException | IllegalAccessException e) {
                             throw new RuntimeException(e);

java/trunk/conditions/src/main/java/org/hps/conditions
DatabaseConditionsReader.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/DatabaseConditionsReader.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/DatabaseConditionsReader.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.sql.SQLException;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Level;
@@ -14,11 +13,11 @@
 
 /**
  * This is more-or-less a placeholder class for a database conditions reader.
+ * The {@link DatabaseConditionsManager} and the converter classes perform
+ * the real work.
  * 
  * @author Jeremy McCormick <[log in to unmask]>
- * @version $Id: DatabaseConditionsReader.java,v 1.21 2013/10/18 06:08:55 jeremy Exp $ 
  */
-// TODO: Add a multi reader class that can have an arbitrary number of readers it may call, with precedence.
 public class DatabaseConditionsReader extends ConditionsReader {
             
     /** Base ConditionsReader for getting the Detector. */
@@ -83,14 +82,7 @@
             _logger.warning("Conditions already cached for run <" + run + ">.");
             return false;
         }
-                                    
-        // Cache the ConditionsRecords.
-        try {
-            setup(run);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-                                               
+                                                                                   
         return true;
     }
 
@@ -107,15 +99,5 @@
      */
     public InputStream open(String name, String type) throws IOException {
         return _reader.open(name, type);
-    }
-     
-    /**
-     * This will cache the ConditionsRecords for the run.
-     * @param run The run number.
-     * @throws SQLException
-     * @throws IOException
-     */
-    private final void setup(int run) throws SQLException, IOException {
-        ConditionsRecord.find(run); // FIXME: Does this even need to happen here?
-    }
+    }    
 }

java/trunk/conditions/src/main/java/org/hps/conditions
DefaultTestSetup.java added at 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/DefaultTestSetup.java	                        (rev 0)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/DefaultTestSetup.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -0,0 +1,61 @@
+package org.hps.conditions;
+
+/**
+ * <p>
+ * This is a static utility class for setting up the conditions system for test cases
+ * in this package and sub-packages.
+ * </p>
+ * <p>
+ * It uses the SLAC Test Run 2012 conditions database, with a relative reference to a file
+ * containing connection parameters in the hps-conditions module.  The XML configuration
+ * is read from a classpath resource in the same module.
+ * </p>
+ * <p>
+ * The detector is set to <i>HPS-conditions-test</i>, which is a test detector without real data
+ * associated to it.  There are a few files used in the test cases that use this detector.
+ * </p>
+ * <p>
+ * The run number is initially set to <i>1351</i> which is one of the "good runs".
+ * </p>
+ * <p>
+ * Full setup can be performed with this method chain:
+ * <code>
+ * DatabaseConditionsManager manager = new DefaultTestSetup().configure().setup();
+ * </code>
+ * </p>
+ * <p>
+ * To only configure the system without setting up detector and run, use the following:
+ * <code>
+ * new DefaultTestSetup().configure();
+ * </code>
+ * </p>
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public final class DefaultTestSetup {
+
+    static String _detectorName = "HPS-conditions-test";
+    static int _runNumber = 1351;
+    static String _connectionProperties = "./src/main/config/conditions_database_testrun_2012_connection.properties";
+    static String _conditionsConfig = "/org/hps/conditions/config/conditions_database_testrun_2012.xml";
+    
+    DatabaseConditionsManager _conditionsManager;
+    boolean _wasConfigured = false;
+    
+    public DefaultTestSetup configure() {        
+        _conditionsManager = DatabaseConditionsManager.createInstance();
+        _conditionsManager.setConnectionProperties(_connectionProperties);
+        _conditionsManager.configure(_conditionsConfig);
+        _wasConfigured = true;
+        return this;
+    }
+    
+    public DatabaseConditionsManager setup() {
+        if (!_wasConfigured)
+            configure();
+        _conditionsManager.setDetectorName(_detectorName);
+        _conditionsManager.setRunNumber(_runNumber);
+        _conditionsManager.setup();
+        return _conditionsManager;
+    }
+}

java/trunk/conditions/src/main/java/org/hps/conditions
TableMetaData.java 341 -> 342
--- java/trunk/conditions/src/main/java/org/hps/conditions/TableMetaData.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/TableMetaData.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -4,11 +4,15 @@
 import java.util.Set;
 
 /**
+ * <p>
  * This class provides meta data about a conditions table, including a
- * list of conditions data fields (not including collection ID or row ID
- * which are assumed).  It also has references to the classes which are
- * used to map the data onto Java classes via the {@link ConditionsObject}
- * and {@link ConditionsObjectCollection} APIs.
+ * list of conditions data fields.  The list of fields does not include
+ * the collection ID or row ID, which are implicitly assumed to exist.
+ * </p>  
+ * <p>
+ * It also has references to the implementation classes which are used to 
+ * map the data onto {@link ConditionsObject} and {@link ConditionsObjectCollection}s.
+ * </p>
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  *
@@ -16,11 +20,20 @@
 public class TableMetaData {
     
     String _tableName;
+    String _key;
     Class<? extends ConditionsObject> _objectClass;
     Class<? extends ConditionsObjectCollection<?>> _collectionClass;
     Set<String> _fieldNames = new LinkedHashSet<String>();
         
-    TableMetaData(String tableName, 
+    /**
+     * The fully qualified constructor.
+     * @param tableName The name of the table in the conditions database.
+     * @param objectClass The type of object for the data mapping.
+     * @param collectionClass The type of collection for the data mapping.
+     */
+    TableMetaData(
+            String key,
+            String tableName, 
             Class<? extends ConditionsObject> objectClass, 
             Class<? extends ConditionsObjectCollection<?>> collectionClass) {
         _tableName = tableName;
@@ -28,18 +41,35 @@
         _collectionClass = collectionClass;
     }
     
+    /**
+     * Get the type of object this table maps onto.
+     * @return The type of object.
+     */
     Class<? extends ConditionsObject> getObjectClass() {
         return _objectClass;
     }
     
+    /**
+     * Get the type of collection this table maps onto.
+     * @return
+     */
     Class<? extends ConditionsObjectCollection<?>> getCollectionClass() {
         return _collectionClass;
     }
     
+    /**
+     * Get the names of the fields.
+     * Types are implied from the database tables.
+     * @return The names of the fields.
+     */
     String[] getFieldNames() {
         return _fieldNames.toArray(new String[]{});
     }
-       
+     
+    /**
+     * Add a field.
+     * @param name The name of the field.
+     */
     void addField(String name) {
         if (_fieldNames.contains(name)) {
             throw new RuntimeException("The table meta data already has a field called " + name);
@@ -47,7 +77,20 @@
         _fieldNames.add(name);
     }
     
+    /**
+     * Get the name of the table.
+     * @return The name of the table.
+     */
     public String getTableName() {
         return _tableName;
     }
+    
+    /**
+     * Get the key of this conditions type.  May be different from table name 
+     * but is usually the same.
+     * @return The key name of the conditions type.
+     */
+    public String getKey() {
+        return _key;
+    }
 }
\ No newline at end of file

java/trunk/conditions/src/main/resources/org/hps/conditions/config
conditions_database_testrun_2012.xml 341 -> 342
--- java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,19 +1,5 @@
 <conditions_database name="hps_conditions_test" version="1.0" author="jeremym">
-
-    <connection>
-        <user>rd_hps_cond_ro</user>
-        <password>2jumpinphotons.</password>
-        <database>rd_hps_cond</database>
-        <hostname>mysql-node03.slac.stanford.edu</hostname>
-        <port>3306</port>
-        <read_only>true</read_only>
-        <conditions_table>conditions_dev</conditions_table>
-    </connection>
-    
-    <readers>
-        <reader class="org.lcsim.conditions.readers.BaseClasspathConditionsReader" />
-    </readers>
-
+      
     <converters>
 
         <!-- ConditionsRecord converter -->
@@ -42,7 +28,28 @@
 
     <tables>
     
-        <table name="svt_channels">
+        <table key="conditions_records" name="conditions_dev">
+            <classes> 
+                <object class="org.hps.conditions.ConditionsRecord"/>
+                <collection class="org.hps.conditions.ConditionsRecord$ConditionsRecordCollection"/>
+            </classes>
+            <fields>
+                <field name="run_start" />
+                <field name="run_end" />
+                <field name="updated" />
+                <field name="created" />
+                <field name="valid_from" />
+                <field name="valid_to" />
+                <field name="created_by" />
+                <field name="notes" />
+                <field name="name" />
+                <field name="format_version" />
+                <field name="table_name" />
+                <field name="collection_id" />
+            </fields>
+        </table>
+    
+        <table key="svt_channels" name="svt_channels">
             <classes>
                 <object class="org.hps.conditions.svt.SvtChannel"/>
                 <collection class="org.hps.conditions.svt.SvtChannel$SvtChannelCollection"/>
@@ -55,7 +62,7 @@
             </fields>
         </table>
     
-        <table name="svt_gains">
+        <table key="svt_gains" name="svt_gains">
             <classes>
                 <object class="org.hps.conditions.svt.SvtGain"/> 
                 <collection class="org.hps.conditions.svt.SvtGain$SvtGainCollection"/>
@@ -67,7 +74,7 @@
             </fields>
         </table>
         
-        <table name="svt_pulse_parameters">
+        <table key="svt_pulse_parameters" name="svt_pulse_parameters">
             <classes>
                 <object class="org.hps.conditions.svt.SvtPulseParameters"/>
                 <collection class="org.hps.conditions.svt.SvtPulseParameters$SvtPulseParametersCollection"/>
@@ -81,7 +88,7 @@
             </fields>        
         </table>
         
-        <table name="svt_calibrations">
+        <table key="svt_calibrations" name="svt_calibrations">
             <classes>
                 <object class="org.hps.conditions.svt.SvtCalibration"/>
                 <collection class="org.hps.conditions.svt.SvtCalibration$SvtCalibrationCollection"/>
@@ -93,7 +100,7 @@
             </fields>        
         </table>
         
-        <table name="svt_time_shifts">
+        <table key="svt_time_shifts" name="svt_time_shifts">
             <classes>
                 <object class="org.hps.conditions.svt.SvtTimeShift"/>
                 <collection class="org.hps.conditions.svt.SvtTimeShift$SvtTimeShiftCollection"/>
@@ -105,7 +112,7 @@
             </fields>        
         </table>
         
-        <table name="svt_bad_channels">
+        <table key="svt_bad_channels" name="svt_bad_channels">
             <classes>
                 <object class="org.hps.conditions.svt.SvtBadChannel"/>
                 <collection class="org.hps.conditions.svt.SvtBadChannel$SvtBadChannelCollection"/>
@@ -115,7 +122,7 @@
             </fields>        
         </table>
         
-        <table name="svt_daq_map">
+        <table key="svt_daq_map" name="svt_daq_map">
             <classes>
                 <object class="org.hps.conditions.svt.SvtDaqMapping"/>
                 <collection class="org.hps.conditions.svt.SvtDaqMapping$SvtDaqMappingCollection"/>
@@ -128,7 +135,7 @@
             </fields>  
         </table>
         
-        <table name="ecal_bad_channels">
+        <table key="ecal_bad_channels" name="ecal_bad_channels">
             <classes>
                 <object class="org.hps.conditions.ecal.EcalBadChannel"/>
                 <collection class="org.hps.conditions.ecal.EcalBadChannel$EcalBadChannelCollection"/>
@@ -138,7 +145,7 @@
             </fields>  
         </table>
         
-        <table name="ecal_gains">
+        <table key="ecal_gains" name="ecal_gains">
             <classes>
                 <object class="org.hps.conditions.ecal.EcalGain"/>
                 <collection class="org.hps.conditions.ecal.EcalGain$EcalGainCollection"/>
@@ -149,7 +156,7 @@
             </fields>  
         </table>
         
-        <table name="ecal_calibrations">
+        <table key="ecal_calibrations" name="ecal_calibrations">
             <classes>
                 <object class="org.hps.conditions.ecal.EcalCalibration"/>
                 <collection class="org.hps.conditions.ecal.EcalCalibration$EcalCalibrationCollection"/>
@@ -161,7 +168,7 @@
             </fields>  
         </table>
         
-        <table name="ecal_channels">
+        <table key="ecal_channels" name="ecal_channels">
             <classes>
                 <object class="org.hps.conditions.ecal.EcalChannel"/>
                 <collection class="org.hps.conditions.ecal.EcalChannel$EcalChannelCollection"/>
@@ -176,7 +183,7 @@
             </fields>  
         </table>
         
-        <table name="beam_current">
+        <table key="beam_current" name="beam_current">
             <classes>
                 <object class="org.hps.conditions.beam.BeamCurrent"/>
                 <collection class="org.hps.conditions.beam.BeamCurrent$BeamCurrentCollection"/>

java/trunk/conditions/src/test/java/org/hps/conditions
ConditionsDriverTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -53,10 +53,9 @@
         // Create the record loop.        
         LCSimLoop loop = new LCSimLoop();
         
-        // Reconfigure the conditions system to override the manager created by LCSimLoop.
-        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        
+        // Reconfigure the conditions system.
+        new DefaultTestSetup().configure();
+                
         // Configure the loop.
         loop.setLCIORecordSource(testFile);
         loop.add(new ConditionsDriver());  

java/trunk/conditions/src/test/java/org/hps/conditions
ConditionsObjectTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsObjectTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsObjectTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -1,7 +1,5 @@
 package org.hps.conditions;
 
-import java.sql.SQLException;
-
 import junit.framework.TestCase;
 
 import org.hps.conditions.svt.SvtGain;
@@ -14,26 +12,20 @@
  * @author Jeremy McCormick <[log in to unmask]>
  *
  */
+// TODO: Add test of collection operations similar to the one for individual objects.
 public class ConditionsObjectTest extends TestCase {
     
-    String detectorName = "HPS-conditions-test";
-    int runNumber = 1351;
-    DatabaseConditionsManager conditionsManager;
+    DatabaseConditionsManager _conditionsManager;
     
-    public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_dev.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+    public void setUp() {        
+        _conditionsManager = new DefaultTestSetup().configure().setup();
     }
     
     public void testBasicOperations() throws ConditionsObjectException {    
-        
-        // Create a new collection.
-        TableMetaData tableMetaData = conditionsManager.findTableMetaData(TableConstants.SVT_GAINS);
-        int collectionId = conditionsManager.getNextCollectionId(tableMetaData.getTableName());        
+                
+        // Create a new collection, setting its table meta data and collection ID.
+        TableMetaData tableMetaData = _conditionsManager.findTableMetaData(TableConstants.SVT_GAINS);
+        int collectionId = _conditionsManager.getNextCollectionId(tableMetaData.getTableName());        
         SvtGainCollection collection = new SvtGainCollection();
         collection.setTableMetaData(tableMetaData);
         try {
@@ -65,6 +57,7 @@
         selectGain.setRowId(gain.getRowId());
         selectGain.setTableMetaData(tableMetaData);
         selectGain.select();
+        // TODO: Check values here against the original object.
         
         // Update the value in the database.
         double newValue = 2.345;
@@ -74,7 +67,7 @@
         
         // Delete the object.
         gain.delete();
-        assertEquals("The deleted object still has a row ID.", -1, gain.getRowId());
+        assertEquals("The deleted object still has a valid row ID.", -1, gain.getRowId());
         
         // Try an update which should fail.
         try {

java/trunk/conditions/src/test/java/org/hps/conditions
DatabaseConditionsManagerTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/DatabaseConditionsManagerTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/DatabaseConditionsManagerTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -4,26 +4,20 @@
 
 public class DatabaseConditionsManagerTest extends TestCase {
     
-    String detectorName = "HPS-conditions-test";
-    int runNumber = 1351;
-    DatabaseConditionsManager conditionsManager;
+    DatabaseConditionsManager _conditionsManager;    
     
     public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+        _conditionsManager = new DefaultTestSetup().configure().setup();
     }
     
     @SuppressWarnings("rawtypes")
-    public void testLoad() {                       
+    public void testLoad() {     
+        
         // Load data from every table registered with the manager.
-        for (TableMetaData metaData : conditionsManager.getTableMetaDataList()) {
+        for (TableMetaData metaData : _conditionsManager.getTableMetaDataList()) {
             System.out.println(">>>> loading conditions from table: " + metaData.getTableName());
             ConditionsObjectCollection conditionsObjects = 
-                    conditionsManager.getConditionsData(metaData.getCollectionClass(), metaData.getTableName());
+                    _conditionsManager.getConditionsData(metaData.getCollectionClass(), metaData.getTableName());
             System.out.println("  " + conditionsObjects.getObjects().size() + " " + conditionsObjects.get(0).getClass().getSimpleName() + " objects were created.");
         }
     }        

java/trunk/conditions/src/test/java/org/hps/conditions/beam
BeamCurrentTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/beam/BeamCurrentTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/beam/BeamCurrentTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -10,6 +10,7 @@
 import junit.framework.TestCase;
 
 import org.hps.conditions.DatabaseConditionsManager;
+import org.hps.conditions.DefaultTestSetup;
 import org.hps.conditions.beam.BeamCurrent.BeamCurrentCollection;
 import org.lcsim.conditions.ConditionsManager;
 import org.lcsim.event.EventHeader;
@@ -56,8 +57,7 @@
         LCSimLoop loop = new LCSimLoop();
         
         // Reconfigure the conditions system to override the manager created by LCSimLoop.
-        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
+        new DefaultTestSetup().configure();
         
         // Configure and run the loop.
         loop.setLCIORecordSource(testFile);

java/trunk/conditions/src/test/java/org/hps/conditions/ecal
EcalConditionsConverterTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalConditionsConverterTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalConditionsConverterTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -2,37 +2,26 @@
 
 import junit.framework.TestCase;
 
-import org.hps.conditions.ConnectionManager;
 import org.hps.conditions.DatabaseConditionsManager;
+import org.hps.conditions.DefaultTestSetup;
 
 /**
  * Tests that a {@link EcalConditions} objects loads without errors.
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public class EcalConditionsConverterTest extends TestCase {
-    
-    final String detectorName = "HPS-conditions-test";
-    final int runNumber = 777;
-    
-    DatabaseConditionsManager conditionsManager;
-    
+      
     public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+        new DefaultTestSetup().configure().setup();
     }
             
     public void test() {
-                                                
+        
+        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+        
         // Test that the manager gets ECAL conditions.
         EcalConditions conditions = conditionsManager.getCachedConditions(EcalConditions.class, "ecal_conditions").getCachedData();        
         assertNotNull(conditions);
         System.out.println(conditions);
-        
-        // Cleanup the connection.
-        ConnectionManager.getConnectionManager().disconnect();
     }    
 }

java/trunk/conditions/src/test/java/org/hps/conditions/ecal
EcalConditionsLoaderTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalConditionsLoaderTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalConditionsLoaderTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -4,8 +4,8 @@
 
 import junit.framework.TestCase;
 
-import org.hps.conditions.ConnectionManager;
 import org.hps.conditions.DatabaseConditionsManager;
+import org.hps.conditions.DefaultTestSetup;
 import org.lcsim.detector.converter.compact.EcalCrystal;
 import org.lcsim.geometry.Detector;
 
@@ -15,13 +15,7 @@
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public class EcalConditionsLoaderTest extends TestCase {
-    
-    /** An example detector from hps-detectors. */
-    private static final String detectorName = "HPS-conditions-test";
-    
-    /** The run number of the conditions set in the database. */
-    private static final int runNumber = 1351;
-    
+        
     /** Expected number of crystals. */
     private static final int CRYSTAL_COUNT_ANSWER = 442;
     
@@ -38,23 +32,18 @@
     
     // The total number of crystals that should be processed.
     private static final int CRYSTAL_COUNT = 442;
-    
-    DatabaseConditionsManager conditionsManager;
-    
+        
     public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+        new DefaultTestSetup().configure().setup();
     }
                                            
     /**
      * Load SVT conditions data onto the detector and perform basic checks afterwards.
      */
-    public void test() {
-                
+    public void testLoad() {
+        
+        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+        
         // Get the detector.
         Detector detector = conditionsManager.getCachedConditions(Detector.class, "compact.xml").getCachedData();
         
@@ -112,8 +101,5 @@
         assertEquals("Wrong number of bad channels.", BAD_CHANNELS_ANSWER, badChannelCount);
 
         System.out.println("Successfully loaded conditions onto " + ncrystals + " ECal crystals!");
-        
-        // Cleanup the database connection.
-        ConnectionManager.getConnectionManager().disconnect();
     }
 }

java/trunk/conditions/src/test/java/org/hps/conditions/svt
SvtConditionsConverterTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtConditionsConverterTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtConditionsConverterTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -2,8 +2,8 @@
 
 import junit.framework.TestCase;
 
-import org.hps.conditions.ConnectionManager;
 import org.hps.conditions.DatabaseConditionsManager;
+import org.hps.conditions.DefaultTestSetup;
 
 /**
  * This test loads and prints {@link SvtConditions}, which internally uses the  
@@ -13,35 +13,22 @@
  */
 public class SvtConditionsConverterTest extends TestCase {
     
-    /** An example detector from hps-detectors. */
-    private static final String detectorName = "HPS-conditions-test";
     
-    /** The run number of the conditions set in the database. */
-    private static final int runNumber = 777;
-    
-    DatabaseConditionsManager conditionsManager;
-    
     public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+        new DefaultTestSetup().configure().setup();
     }
     
     /**
      * Load and print all SVT conditions for a certain run number.
      */
     public void test() {
+        
+        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
                 
         // Get conditions and print them out.
         SvtConditions svt = conditionsManager.getCachedConditions(SvtConditions.class, "svt_conditions").getCachedData();
         assertNotNull(svt);
         System.out.println(svt);
         System.out.println("Successfully loaded SVT conditions!");
-        
-        // Cleanup the connection.
-        ConnectionManager.getConnectionManager().disconnect();
     }
 }

java/trunk/conditions/src/test/java/org/hps/conditions/svt
SvtConditionsLoaderTest.java 341 -> 342
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtConditionsLoaderTest.java	2014-03-25 01:23:45 UTC (rev 341)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtConditionsLoaderTest.java	2014-03-25 01:37:50 UTC (rev 342)
@@ -4,8 +4,8 @@
 
 import junit.framework.TestCase;
 
-import org.hps.conditions.ConnectionManager;
 import org.hps.conditions.DatabaseConditionsManager;
+import org.hps.conditions.DefaultTestSetup;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.geometry.Detector;
 
@@ -16,13 +16,7 @@
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public class SvtConditionsLoaderTest extends TestCase {
-    
-    /** An example detector from hps-detectors. */
-    private static final String detectorName = "HPS-conditions-test";
-    
-    /** The run number of the conditions set in the database. */
-    private static final int runNumber = 1351;
-    
+        
     /**
      * The number of bad channels that should be returned for the run.
      * One of these is a duplicate so the row count is actually 442 in the database. 
@@ -36,14 +30,9 @@
     private static final int SENSOR_COUNT = 12800;
     
     DatabaseConditionsManager conditionsManager;
-    
+            
     public void setUp() {
-        // Create and configure the conditions manager.
-        conditionsManager = DatabaseConditionsManager.createInstance();
-        conditionsManager.configure("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
-        conditionsManager.setDetectorName(detectorName);
-        conditionsManager.setRunNumber(runNumber);
-        conditionsManager.setup();
+        conditionsManager = new DefaultTestSetup().configure().setup();
     }
     
     /**
@@ -121,8 +110,5 @@
         assertEquals("The number of channels for which pulse was not set is wrong.", PULSE_NOT_SET_ANSWER, pulseNotSet);
                 
         System.out.println("Successfully loaded conditions data onto " + nsensors + " SVT sensors!");
-        
-        // Cleanup the database connection.
-        ConnectionManager.getConnectionManager().disconnect();
     }
 }
SVNspam 0.1