Print

Print


Author: [log in to unmask]
Date: Tue Dec 30 16:44:44 2014
New Revision: 1815

Log:
Revise conditions system to use annotations and other improvements.  HPSJAVA-372

Added:
    java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/Converter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/ConverterRegistry.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/Field.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/MultipleCollectionsAction.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/Table.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/TableRegistry.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/TestRunEcalConditionsConverter.java
    java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_engrun.xml
    java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_prod.xml
    java/trunk/conditions/src/test/java/org/hps/conditions/database/
    java/trunk/conditions/src/test/java/org/hps/conditions/database/ConverterRegistryTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/database/TableRegistryTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalDetectorSetupTest.java
      - copied, changed from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/EcalDetectorSetupTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java
      - copied, changed from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/SvtDetectorSetupTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java
      - copied, changed from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/TestRunSvtDetectorSetupTest.java
Removed:
    java/trunk/conditions/src/main/java/org/hps/conditions/beam/BeamConverterRegistry.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConverterRegistry.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtConverterRegistry.java
    java/trunk/conditions/src/test/java/org/hps/conditions/EcalDetectorSetupTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/SvtDetectorSetupTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/TestRunSvtDetectorSetupTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/api/
    java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalConditionsConverterTest.java
Modified:
    java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java
    java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java
    java/trunk/conditions/src/main/java/org/hps/conditions/beam/BeamCurrent.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/TableConstants.java
    java/trunk/conditions/src/main/java/org/hps/conditions/database/TableMetaData.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalBadChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCalibration.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalGain.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalLed.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalTimeShift.java
    java/trunk/conditions/src/main/java/org/hps/conditions/ecal/package-info.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtConditionsConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtDaqMapping.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtT0Shift.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtAlignmentConstant.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtBadChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtCalibration.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtConfiguration.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDaqMapping.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtGain.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtShapeFitParameters.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtT0Shift.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtChannel.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditions.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditionsConverter.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java
    java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtT0Shift.java
    java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml
    java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalLedTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDaqMappingTest.java
    java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDaqMappingTest.java

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java	Tue Dec 30 16:44:44 2014
@@ -18,11 +18,12 @@
  * <pre>
  * {@code
  * <driver name="ConditionsDriver" type="org.hps.conditions.ConditionsDriver">
- *     <freeze>true</freeze>
  *     <detectorName>HPS-TestRun-v5</detectorName>
+ *     <runNumber>1351</runNumber>
+ *     <xmlConfigResource>/org/hps/conditions/config/conditions_database_testrun_2012.xml</xmlConfigResource>
  *     <ecalName>Ecal</ecalName>
  *     <svtName>Tracker</svtName>
- *     <runNumber>1351</runNumber>
+ *     <freeze>true</freeze>
  * </driver>
  * }
  * </pre> 
@@ -39,10 +40,12 @@
  */
 public class ConditionsDriver extends Driver {
 
+    DatabaseConditionsManager conditionsManager;
     String detectorName = null;
     String ecalName = null;
     String svtName = null;
     String tag = null;
+    String xmlConfigResource = null;
     int runNumber = 0;
     boolean freeze;    
     
@@ -50,12 +53,11 @@
      * Default constructor.
      */
     public ConditionsDriver() {
-        new DatabaseConditionsManager();
+        conditionsManager = new DatabaseConditionsManager();
     }
     
     /**
      * Set the name of the detector to use.
-     * 
      * @param detectorName The name of the detector.
      */
     public void setDetectorName(String detectorName) {
@@ -67,7 +69,6 @@
      * detector name and run number are set.  When frozen, the conditions system
      * will ignore subsequent calls to {@link org.lcsim.conditions.ConditionsManager#setDetector(String, int)}
      * and instead use the user supplied detector and run for the whole job.
-     * 
      * @param freeze True to freeze the conditions system after it is setup.
      */
     public void setFreeze(boolean freeze) {
@@ -82,7 +83,6 @@
      * 
      * The method {@link #setDetectorName(String)} needs to be called before this one
      * or an exception will be thrown.
-     * 
      * @param runNumber The user supplied run number for the job.
      */
     public void setRunNumber(int runNumber) {
@@ -116,11 +116,23 @@
     }
     
     /**
+     * Set an XML configuration resource.
+     * @param xmlConfigResource The XML configuration resource.
+     */
+    public void setXmlConfigResource(String xmlConfigResource) {
+        this.xmlConfigResource = xmlConfigResource;
+    }
+    
+    /**
      * Setup the conditions system based on the Driver parameters.
      * @throws RuntimeException If there is a problem setting up the conditions system.
      */
     public void initialize() {
-        DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+        if (xmlConfigResource != null) {
+            // Set a custom XML configuration resource.
+            conditionsManager.setXmlConfig(xmlConfigResource);
+        }
+
         if (ecalName != null) {
             // Set custom ECAL name.
             conditionsManager.setEcalName(ecalName);
@@ -134,7 +146,7 @@
             conditionsManager.setTag(tag);
         }
         if (detectorName != null) {
-            // The manager can only be initialized if there is a user supplied detector name.
+            // The manager can only be initialized here if there is a user supplied detector name.
             try {
                 // Initialize the conditions manager.
                 conditionsManager.setDetector(detectorName, runNumber);

Added: java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,101 @@
+package org.hps.conditions.api;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+import javassist.Modifier;
+
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.Table;
+import org.reflections.Reflections;
+
+/**
+ * This is a collection of utility methods for {@link ConditionsObject}.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public final class ConditionsObjectUtilities {
+    
+    private ConditionsObjectUtilities() {       
+    }
+    
+    /**
+     * Get the list of table names for the class.
+     * @param type The class.
+     * @return The list of table names.
+     */
+    public static String[] getTableNames(Class<? extends ConditionsObject> type) {
+        Table tableAnnotation = type.getAnnotation(Table.class);
+        if (tableAnnotation != null) {
+            return tableAnnotation.names(); 
+        } else {
+            return new String[]{};
+        }
+    }
+    
+    /**
+     * Get the list of database field names for the class.
+     * @param type The class.
+     * @return The list of field names.
+     */
+    public static Set<String> getFieldNames(Class<? extends ConditionsObject> type) {
+        Set<String> fieldNames = new HashSet<String>();
+        for (Method method : type.getMethods()) {
+            if (!method.getReturnType().equals(Void.TYPE)) {
+                for (Annotation annotation : method.getAnnotations()) {
+                    if (annotation.annotationType().equals(Field.class)) {
+                        if (!Modifier.isPublic(method.getModifiers())) {
+                            throw new RuntimeException("The method " + type.getName() + "." + method.getName() + " has a Field annotation but is not public.");
+                        }
+                        Field field = (Field) annotation;
+                        for (String fieldName : field.names()) {
+                            if (fieldName != null && !fieldName.equals("")) {
+                                fieldNames.add(fieldName);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return fieldNames;
+    }
+    
+    /**
+     * Get the class for the collection of the ConditionsObject type.
+     * @param type The class of the ConditionsObject.
+     * @return The class of the collection.
+     */
+    @SuppressWarnings("unchecked")
+    public static Class<? extends AbstractConditionsObjectCollection<? extends ConditionsObject>> getCollectionType(Class<? extends ConditionsObject> type) {
+        String collectionClassName = type.getCanonicalName() + "$" + type.getSimpleName() + "Collection";
+        Class<?> rawCollectionClass;
+        try {
+            rawCollectionClass = Class.forName(collectionClassName);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("The type does not define a nested collection class.", e);
+        }
+        if (!AbstractConditionsObjectCollection.class.isAssignableFrom(rawCollectionClass))
+            throw new RuntimeException("The class " + rawCollectionClass.getSimpleName() + " does not extend ConditionsObjectCollection.");
+        return (Class<? extends AbstractConditionsObjectCollection<? extends ConditionsObject>>) rawCollectionClass;
+    }
+    
+    /**
+     * Find all available classes that extend ConditionsObject.
+     * @return The set of all available classes that extend ConditionsObject.
+     */
+    public static Set<Class<? extends ConditionsObject>> findConditionsObjectTypes() {
+        Reflections reflections = new Reflections("org.hps.conditions");    
+        Set<Class<? extends ConditionsObject>> objectTypes = new HashSet<Class<? extends ConditionsObject>>();
+        for (Class<? extends ConditionsObject> objectType : reflections.getSubTypesOf(ConditionsObject.class)) {
+            if (Modifier.isAbstract(objectType.getModifiers())) {
+                continue;
+            }
+            if (objectType.getAnnotation(Table.class) == null) {
+                continue;
+            }
+            objectTypes.add(objectType);
+        }
+        return objectTypes;
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java	Tue Dec 30 16:44:44 2014
@@ -8,8 +8,12 @@
 import java.util.List;
 import java.util.Set;
 
+import org.hps.conditions.database.ConditionsRecordConverter;
+import org.hps.conditions.database.Converter;
 import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.database.Field;
 import org.hps.conditions.database.QueryBuilder;
+import org.hps.conditions.database.Table;
 import org.hps.conditions.database.TableMetaData;
 
 /**
@@ -19,6 +23,8 @@
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"conditions"})
+@Converter(converter = ConditionsRecordConverter.class)
 public final class ConditionsRecord extends AbstractConditionsObject {
     
     /**
@@ -157,7 +163,7 @@
     public void insert() throws ConditionsObjectException {
         if (fieldValues.size() == 0)
             throw new ConditionsObjectException("There are no field values to insert.");
-        TableMetaData tableMetaData = DatabaseConditionsManager.getInstance().findTableMetaData(ConditionsRecordCollection.class).get(0);
+        TableMetaData tableMetaData = DatabaseConditionsManager.getInstance().findTableMetaData("conditions");
         String query = QueryBuilder.buildInsert(tableMetaData.getTableName(), this.getFieldValues());
         //System.out.println(query);
         List<Integer> keys = DatabaseConditionsManager.getInstance().updateQuery(query);
@@ -171,6 +177,7 @@
      * Get the starting run number.
      * @return The starting run number.
      */
+    @Field(names = {"run_start"})
     public int getRunStart() {
         return getFieldValue("run_start");
     }
@@ -179,6 +186,7 @@
      * Get the ending run number.
      * @return The ending run number.
      */
+    @Field(names = {"run_end"})
     public int getRunEnd() {
         return getFieldValue("run_end");
     }
@@ -187,6 +195,7 @@
      * Get the date this record was last updated.
      * @return The date this record was updated.
      */
+    @Field(names = {"updated"})
     public Date getUpdated() {
         return getFieldValue("updated");
     }
@@ -195,6 +204,7 @@
      * Get the date this record was created.
      * @return The date this record was created.
      */
+    @Field(names = {"created"})
     public Date getCreated() {
         return getFieldValue("created");
     }
@@ -203,6 +213,7 @@
      * Get the name of the user who created this record.
      * @return The name of the person who created the record.
      */
+    @Field(names = {"created_by"})
     public String getCreatedBy() {
         return getFieldValue("created_by");
     }
@@ -211,6 +222,7 @@
      * Get the notes.
      * @return The notes about this condition.
      */
+    @Field(names = {"notes"})
     public String getNotes() {
         return getFieldValue("notes");
     }
@@ -221,6 +233,7 @@
      * "table name".
      * @return The name of the conditions.
      */
+    @Field(names = {"name"})
     public String getName() {
         return getFieldValue("name");
     }
@@ -229,6 +242,7 @@
      * Get the name of the table containing the actual raw conditions data.
      * @return The name of the table with the conditions data.
      */
+    @Field(names = {"table_name"})
     public String getTableName() {
         return getFieldValue("table_name");
     }
@@ -237,6 +251,7 @@
      * Get the collection ID, overriding this method from the parent class.
      * @return The collection ID.
      */
+    @Field(names = {"collection_id"})
     public int getCollectionId() {
         return getFieldValue("collection_id");
     }
@@ -245,6 +260,7 @@
      * Get the string tag associated with these conditions.
      * @return The string tag.
      */
+    @Field(names = {"tag"})
     public String getTag() {
         return getFieldValue("tag");
     }
@@ -268,4 +284,4 @@
         buff.append("notes: " + getNotes() + '\n');
         return buff.toString();
     }
-}
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/beam/BeamCurrent.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/beam/BeamCurrent.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/beam/BeamCurrent.java	Tue Dec 30 16:44:44 2014
@@ -2,11 +2,17 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
- * This class is a simple data holder for the integrated beam current condition.
+ * This class is a conditions object for integrated beam current values.
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"beam_current"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class BeamCurrent extends AbstractConditionsObject {
 
     public static class BeamCurrentCollection extends AbstractConditionsObjectCollection<BeamCurrent> {
@@ -16,7 +22,8 @@
      * Get the integrated beam current.
      * @return The integrated beam current.
      */
-    double getIntegratedBeamCurrent() {
+    @Field(names = {"beam_current"})
+    public double getIntegratedBeamCurrent() {
         return getFieldValue("beam_current");
     }
 }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java	Tue Dec 30 16:44:44 2014
@@ -3,7 +3,6 @@
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
-import java.sql.Statement;
 
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
 import org.hps.conditions.api.ConditionsObject;
@@ -27,78 +26,91 @@
  */
 public abstract class ConditionsObjectConverter<T> implements ConditionsConverter<T> {
 
-    // This is the strategy used for disambiguating multiple overlapping conditions sets.
-    enum MultipleRecordsStrategy {
-        LAST_UPDATED,
-        LAST_CREATED,
-        LATEST_RUN_START,
-        COMBINE,
-        ERROR
-    }
-    
-    MultipleRecordsStrategy multiStrat = MultipleRecordsStrategy.LAST_UPDATED;
+    MultipleCollectionsAction multipleCollections;
     
     public ConditionsObjectConverter() {
     }
     
-    public void setMultipleRecordsStrategy(MultipleRecordsStrategy multiStrat) {
-        this.multiStrat = multiStrat;
-    }
-
-    /**
-     * Child classes must extend this method to specify what type the converter handles.
-     * @return The Class that this converter handles.
+    /**
+     * Set the action that the converter will use to disambiguate when multiple 
+     * conditions sets are found.
+     * @param multipleCollections The multiple collections action.
+     */
+    void setMultipleCollectionsAction(MultipleCollectionsAction multipleCollections) {
+        this.multipleCollections = multipleCollections;
+    }
+    
+    /** 
+     * Get the multiple collections action.
+     * @return The multiple collections action.
+     */
+    public MultipleCollectionsAction getMultipleCollectionsAction() {
+        return this.multipleCollections;
+    }
+    
+    /**
+     * Get the specific type converted by this class.
+     * @return The class that this converter handles.
      */
     public abstract Class<T> getType();
 
+    /**
+     * Get the conditions data based on the name, e.g. "ecal_channels".
+     * The table information is found using the type handled by the Converter.
+     * @return The conditions data.
+     */
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public T getData(ConditionsManager conditionsManager, String name) {
-        
+                
         // Get the DatabaseConditionsManager which is required for using this converter.
-        DatabaseConditionsManager databaseConditionsManager = DatabaseConditionsManager.getInstance();
-        
-        // Get the table meta data from the key given by the caller.
-        TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(name);
-        if (tableMetaData == null)
-            throw new RuntimeException("Table meta data for " + name + " was not found.");
-
+        DatabaseConditionsManager databaseConditionsManager = (DatabaseConditionsManager) conditionsManager;
+        
+        // Get the TableMetaData for the type.
+        TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(getType());    
+        
         // Get the ConditionsRecordCollection with the run number assignments.
         ConditionsRecordCollection conditionsRecords = databaseConditionsManager.findConditionsRecords(name);
-        
-        // By default use all conditions records, which works if there is a single one, or if the COMBINE strategy is being used.
+                
+        // The records to use will be added to this collection, which may depend on multiple record disambiguation.
         ConditionsRecordCollection filteredConditionsRecords = new ConditionsRecordCollection();
-        filteredConditionsRecords.addAll(conditionsRecords);
         
         // Now we need to determine which ConditionsRecord objects to use according to configuration.
         if (conditionsRecords.size() == 0) {
             // No conditions records were found for the key.
-            throw new RuntimeException("No conditions were found with key " + name);
-        } else {           
-            if (multiStrat.equals(MultipleRecordsStrategy.LAST_UPDATED)) {
+            throw new RuntimeException("No conditions were found with key: " + name);
+        } else if (conditionsRecords.size() > 1) {           
+            if (multipleCollections.equals(MultipleCollectionsAction.LAST_UPDATED)) {
                 // Use the conditions set with the latest updated date.
-                filteredConditionsRecords = conditionsRecords.sortedByUpdated();
-            } else if (multiStrat.equals(MultipleRecordsStrategy.LAST_CREATED)){
+                filteredConditionsRecords.add(conditionsRecords.sortedByUpdated().get(conditionsRecords.size() - 1));
+            } else if (multipleCollections.equals(MultipleCollectionsAction.LAST_CREATED)){
                 // Use the conditions set with the latest created date.
-                filteredConditionsRecords = conditionsRecords.sortedByCreated();                
-            } else if (multiStrat.equals(MultipleRecordsStrategy.LATEST_RUN_START)) {
+                filteredConditionsRecords.add(conditionsRecords.sortedByCreated().get(conditionsRecords.size() - 1));
+            } else if (multipleCollections.equals(MultipleCollectionsAction.LATEST_RUN_START)) {
                 // Use the conditions set with the greatest run start value.
-                filteredConditionsRecords = conditionsRecords.sortedByRunStart();
-            } else if (multiStrat.equals(MultipleRecordsStrategy.ERROR)) {            
+                filteredConditionsRecords.add(conditionsRecords.sortedByRunStart().get(conditionsRecords.size() - 1));
+            } else if (multipleCollections.equals(MultipleCollectionsAction.COMBINE)) {
+                // Combine all the records.
+                filteredConditionsRecords.addAll(conditionsRecords);                
+            } else if (multipleCollections.equals(MultipleCollectionsAction.ERROR)) {            
                 // The converter has been configured to throw an error when this happens!
                 throw new RuntimeException("Multiple ConditionsRecord object found for conditions key " + name);
             }           
-        }             
-        
-        // Create a collection of objects to to return.        
-        AbstractConditionsObjectCollection collection = null;
-        
-        try {
-            ConditionsRecord conditionsRecord = null;
+        } else {
+            // Single record was found.
+            filteredConditionsRecords.addAll(conditionsRecords);
+        }
+                
+        // Create a collection of objects to to return.
+        AbstractConditionsObjectCollection collection = null;        
+        try {
+            // If there is a single ConditionsRecord, then it can be assigned to the collection.
+            ConditionsRecord collectionConditionsRecord = null;
             if (filteredConditionsRecords.size() == 1) {
-                // If there is a single ConditionsRecord, then it can be assigned to the collection.
-                conditionsRecord = filteredConditionsRecords.get(0);
+                collectionConditionsRecord = filteredConditionsRecords.get(0);
             }
-            collection = createCollection(conditionsRecord, tableMetaData);
+            
+            // Create the collection with a ConditionsRecord that might be null.
+            collection = createCollection(collectionConditionsRecord, tableMetaData);
         } catch (ConditionsObjectException e) {
             throw new RuntimeException(e);
         }
@@ -108,7 +120,7 @@
         
         // Loop over all records, which could just be a single one.
         for (ConditionsRecord conditionsRecord : filteredConditionsRecords) {
-        
+                    
             // Get the table name.
             String tableName = conditionsRecord.getTableName();
 
@@ -137,13 +149,20 @@
             // Close the Statement and the ResultSet.
             DatabaseUtilities.cleanup(resultSet);
         }
-                
+        
         // Close the database connection.
         databaseConditionsManager.closeConnection();
         
         return (T) collection;
     }
     
+    /**
+     * Create a conditions object.
+     * @param resultSet The database record.
+     * @param tableMetaData The table data for the object.
+     * @return The conditions object.
+     * @throws SQLException If there is a problem using the database.
+     */
     static final ConditionsObject createConditionsObject(ResultSet resultSet, TableMetaData tableMetaData) throws SQLException {
         ResultSetMetaData metaData = resultSet.getMetaData();
         int rowId = resultSet.getInt(1);
@@ -167,6 +186,13 @@
         return newObject;
     }
     
+    /**
+     * Create a conditions object collection.
+     * @param conditionsRecord The conditions record. 
+     * @param tableMetaData The table data.
+     * @return The conditions object collection.
+     * @throws ConditionsObjectException If there is a problem creating the collection.
+     */
     static final AbstractConditionsObjectCollection<?> createCollection(ConditionsRecord conditionsRecord, TableMetaData tableMetaData) throws ConditionsObjectException {
         AbstractConditionsObjectCollection<?> collection;
         try {
@@ -181,4 +207,9 @@
         }
         return collection;
     }  
-}
+    
+    public String toString() {
+        return "ConditionsObjectConverter: type = " + this.getType() + 
+                ", multipleCollectionsAction = " + this.getMultipleCollectionsAction().toString();
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java	Tue Dec 30 16:44:44 2014
@@ -12,7 +12,7 @@
  * Read ConditionsRecord objects from the conditions database and cache the conditions set.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-class ConditionsRecordConverter extends ConditionsObjectConverter<ConditionsRecordCollection> {
+public class ConditionsRecordConverter extends ConditionsObjectConverter<ConditionsRecordCollection> {
 
     /**
      * Get the ConditionsRecords for a run based on current configuration of the

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java	Tue Dec 30 16:44:44 2014
@@ -49,6 +49,7 @@
      *         which type inferred from target variable.
      */
     @SuppressWarnings({ "unchecked", "rawtypes" })
+    // FIXME: This should take a type name to enforce that all collections returned are of the same class.
     public ConditionsSeries createSeries(String conditionsKey) {
         
         conditionsManager.openConnection();

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/Converter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/Converter.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/Converter.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,30 @@
+package org.hps.conditions.database;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for providing converter configuration for {@link org.hps.conditions.api.ConditionsObject} classes.
+ * 
+ * @see ConditionsObjectConverter
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE) 
+public @interface Converter {
+    /**
+     * Get the action to perform in the converter when multiple conditions are found for the current configuration
+     * of run number, detector and tag in the manager.
+     * @return The multiple collections action.
+     */
+    MultipleCollectionsAction multipleCollectionsAction() default MultipleCollectionsAction.ERROR;
+    
+    /**
+     * Get a custom converter class for the type.  (Optional)
+     * @return The custom converter for the type.
+     */
+    Class<?> converter() default ConditionsObjectConverter.class;
+}

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConverterRegistry.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConverterRegistry.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConverterRegistry.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,90 @@
+package org.hps.conditions.database;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javassist.Modifier;
+
+import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.api.ConditionsObject;
+import org.hps.conditions.api.ConditionsObjectUtilities;
+import org.reflections.Reflections;
+
+/**
+ * This is a registry of all available conditions converters.
+ * These classes are found using reflection.  Only converters
+ * with a {@link Table} annotation are loaded, and the class
+ * must not be abstract.
+ * 
+ * @see ConditionsObjectConverter
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class ConverterRegistry extends HashMap<Class<? extends ConditionsObject>, ConditionsObjectConverter> {
+    
+    private ConverterRegistry() {
+    }
+    
+    /**
+     * Automatically create converters for all conditions object classes.
+     * @return The registry of converters.
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static ConverterRegistry create() {
+        ConverterRegistry registry = new ConverterRegistry();
+        Reflections reflections = new Reflections("org.hps.conditions");
+        Set<Class<? extends ConditionsObject>> objectTypes = reflections.getSubTypesOf(ConditionsObject.class);
+        for (Class<? extends ConditionsObject> objectType : objectTypes) {
+            if (Modifier.isAbstract(objectType.getModifiers())) {
+                continue;
+            }
+            if (objectType.getAnnotation(Table.class) == null) {
+                continue;
+            }
+            MultipleCollectionsAction multipleCollectionsAction = MultipleCollectionsAction.ERROR;
+            Class<?> converterClass = null;
+            Converter converterAnnotation = objectType.getAnnotation(Converter.class);
+            if (converterAnnotation != null) {
+                multipleCollectionsAction = converterAnnotation.multipleCollectionsAction();
+                if (!converterAnnotation.converter().equals(ConditionsObjectConverter.class)) {
+                    converterClass = converterAnnotation.converter();
+                }
+            }
+            
+            final Class<? extends AbstractConditionsObjectCollection<? extends ConditionsObject>> collectionType = 
+                    ConditionsObjectUtilities.getCollectionType(objectType);
+            
+            ConditionsObjectConverter converter = null;
+            if (converterClass == null) {
+                converter = new ConditionsObjectConverter() {
+                    @Override
+                    public Class getType() {
+                        return collectionType;
+                    }
+                };
+            } else {
+                try {
+                    Object object = converterClass.newInstance();
+                    if (!(object instanceof ConditionsObjectConverter)) {
+                        throw new RuntimeException("The Converter has the wrong type: " + object.getClass().getCanonicalName());
+                    }
+                    converter = (ConditionsObjectConverter) object;
+                } catch (InstantiationException | IllegalAccessException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            converter.setMultipleCollectionsAction(multipleCollectionsAction);
+            registry.put(converter.getType(), converter);
+        }        
+        return registry;
+    }
+    
+    public String toString() {
+        StringBuffer buff = new StringBuffer();
+        for (Entry<Class<? extends ConditionsObject>, ConditionsObjectConverter> entry : entrySet()) {
+            buff.append(entry.getValue().toString());
+        }
+        return buff.toString();
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java	Tue Dec 30 16:44:44 2014
@@ -16,7 +16,6 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.logging.Level;
@@ -29,16 +28,19 @@
 import org.hps.conditions.api.ConditionsRecord.ConditionsRecordCollection;
 import org.hps.conditions.api.ConditionsSeries;
 import org.hps.conditions.ecal.EcalConditions;
+import org.hps.conditions.ecal.EcalConditionsConverter;
 import org.hps.conditions.ecal.EcalDetectorSetup;
+import org.hps.conditions.ecal.TestRunEcalConditionsConverter;
 import org.hps.conditions.svt.SvtConditions;
+import org.hps.conditions.svt.SvtConditionsConverter;
 import org.hps.conditions.svt.SvtDetectorSetup;
 import org.hps.conditions.svt.TestRunSvtConditions;
+import org.hps.conditions.svt.TestRunSvtConditionsConverter;
 import org.hps.conditions.svt.TestRunSvtDetectorSetup;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
 import org.jdom.input.SAXBuilder;
-import org.lcsim.conditions.ConditionsConverter;
 import org.lcsim.conditions.ConditionsManager;
 import org.lcsim.conditions.ConditionsManagerImplementation;
 import org.lcsim.geometry.Detector;
@@ -47,14 +49,16 @@
 
 /**
  * <p>
- * This class should be used as the top-level ConditionsManager for database
- * access to conditions data.
- * </p>
+ * This class provides the top-level API for accessing database conditions,
+ * as well as configuring the database connection, initializing all
+ * required components, and loading required converters and table meta data.
+ * It is registered as the global <code>ConditionsManager</code> in the 
+ * constructor.
  * <p>
- * In general, this will be overriding the
- * <code>LCSimConditionsManagerImplementation</code> which is setup from within
- * <code>LCSimLoop</code>.
- * </p>
+ * Differences between Test Run and Engineering Run configurations are handled
+ * automatically.
+ * 
+ * @see org.lcsim.conditions.ConditionsManager
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
@@ -62,7 +66,7 @@
 public class DatabaseConditionsManager extends ConditionsManagerImplementation {
 
     protected static final String CONNECTION_PROPERTY = "org.hps.conditions.connection.file";
-    protected static final String DEFAULT_CONFIG = "/org/hps/conditions/config/conditions_dev.xml";
+    protected static final String DEFAULT_CONFIG = "/org/hps/conditions/config/conditions_database_prod.xml";
     protected static final String TEST_RUN_CONFIG = "/org/hps/conditions/config/conditions_database_testrun_2012.xml";
     protected static final int TEST_RUN_MAX_RUN = 1365;
     
@@ -75,26 +79,40 @@
     protected static Logger logger = LogUtil.create(DatabaseConditionsManager.class);
     
     protected String detectorName;
-    protected List<TableMetaData> tableMetaData;
-    protected List<ConditionsConverter> converters;
+    protected String ecalName = "Ecal";
+    protected String svtName = "Tracker";
+    protected EcalDetectorSetup ecalLoader = new EcalDetectorSetup();
+    protected TestRunSvtDetectorSetup testRunSvtloader = new TestRunSvtDetectorSetup();
+    protected SvtDetectorSetup svtLoader = new SvtDetectorSetup();
+    
+    protected ConverterRegistry converters = ConverterRegistry.create();
+    protected ConditionsSeriesConverter conditionsSeriesConverter = new ConditionsSeriesConverter(this);
+    protected TableRegistry tableRegistry = TableRegistry.create();
+    
     protected File connectionPropertiesFile;
     protected ConnectionParameters connectionParameters;
     protected Connection connection;
     protected boolean isConnected = false;
-    protected ConditionsSeriesConverter conditionsSeriesConverter = new ConditionsSeriesConverter(this);
-    protected boolean isInitialized = false;
+    protected boolean loggedConnectionParameters = false;
+    
+    protected String tag = null;
+
     protected String resourceConfig = null;
     protected File fileConfig = null;
-    protected String ecalName = "Ecal";
-    protected String svtName = "Tracker";
+
+    protected boolean isInitialized = false;
     protected boolean isFrozen = false;
-    protected EcalDetectorSetup ecalLoader = new EcalDetectorSetup();
-    protected TestRunSvtDetectorSetup testRunSvtloader = new TestRunSvtDetectorSetup();
-    protected SvtDetectorSetup svtLoader = new SvtDetectorSetup();
-    protected String tag = null;
-        
+    
+    // Configuration from XML settings.
+    protected boolean setupSvtDetector = true;
+    protected boolean setupEcalDetector = true;
+    protected boolean freezeAfterInitialize = false;
+    protected boolean cacheAllConditions = false;
+            
     /**
      * Class constructor.
+     * Calling this will automatically register this
+     * manager as the global default.
      */
     public DatabaseConditionsManager() {
         logger.setLevel(Level.FINER);
@@ -102,17 +120,21 @@
         setupConnectionFromSystemProperty();
         ConditionsManager.setDefaultConditionsManager(this);
         this.setRun(-1);
-    }
-
-    /**
-     * Get the static instance of this class, which must have been registered
-     * first from a call to {@link #register()}.
+        for (ConditionsObjectConverter converter : converters.values()) {
+            logger.config("registering converter for " + converter.getType());
+            this.registerConditionsConverter(converter);
+        }
+    }
+    
+    /**
+     * Get the static instance of this class.
      * @return The static instance of the manager.
      */
     public static DatabaseConditionsManager getInstance() {
 
-        // Perform default setup if necessary.
+        // Is there no manager installed yet?
         if (!ConditionsManager.isSetup()) {
+            // Perform default setup if necessary.
             new DatabaseConditionsManager();
         }
 
@@ -136,21 +158,21 @@
                 connectionParameters = ConnectionParameters.fromResource(chooseConnectionPropertiesResource());
             }
             
-            // Print out connection info to the log.
-            logger.config("opening connection to " + connectionParameters.getConnectionString());
-            logger.config("host " + connectionParameters.getHostname());
-            logger.config("port " + connectionParameters.getPort());
-            logger.config("user " + connectionParameters.getUser());
-            logger.config("database " + connectionParameters.getDatabase());
+            if (!this.loggedConnectionParameters) {
+                // Print out detailed info to the log on first connection.
+                logger.config("opening connection to " + connectionParameters.getConnectionString());
+                logger.config("host " + connectionParameters.getHostname());
+                logger.config("port " + connectionParameters.getPort());
+                logger.config("user " + connectionParameters.getUser());
+                logger.config("database " + connectionParameters.getDatabase());
+                this.loggedConnectionParameters = true;
+            }
 
             // Create the connection using the parameters.
             connection = connectionParameters.createConnection();
-            
-            logger.config("successfuly created connection");
             isConnected = true;
-        } else {
-            logger.info("using existing connection");
-        }
+        } 
+        logger.info("connection opened");
         return connection;
     }
 
@@ -158,14 +180,11 @@
      * Close the database connection.
      */
     public void closeConnection() {
-        logger.info("closing connection");
         if (connection != null) {
             try {
                 if (!connection.isClosed()) {
                     connection.close();
-                } else {
-                    logger.info("connection was already closed");
-                }
+                } 
             } catch (SQLException e) {
                 throw new RuntimeException(e);
             }
@@ -187,13 +206,13 @@
     }
 
     /**
-     * Get a given collection of the given type from the conditions database.
-     * @param type Class type
-     * @return A collection of objects of the given type from the conditions
-     *         database
+     * Get a given collection of the given type from the conditions database
+     * using the default table name.
+     * @param type The type of the conditions data.
+     * @return A collection of objects of the given type from the conditions database
      */
     public <CollectionType extends AbstractConditionsObjectCollection> CollectionType getCollection(Class<CollectionType> type) {
-        TableMetaData metaData = this.findTableMetaData(type).get(0);
+        TableMetaData metaData = tableRegistry.findByCollectionType(type);
         if (metaData == null) {
             throw new RuntimeException("Table name data for condition of type " + type.getSimpleName() + " was not found.");
         }
@@ -203,10 +222,10 @@
     }
 
     /**
-     * This method catches changes to the detector name and run number. It is
-     * actually called every time an lcsim event is created, so it has internal
-     * logic to figure out if the conditions system actually needs to be
-     * updated.
+     * This method handles changes to the detector name and run number.
+     * It is called every time an LCSim event is created, and so it has 
+     * internal logic to figure out if the conditions system actually
+     * needs to be updated.
      */
     @Override
     public void setDetector(String detectorName, int runNumber) throws ConditionsNotFoundException {
@@ -215,22 +234,22 @@
             throw new IllegalArgumentException("The detectorName argument is null.");
         }
         
-        logger.finest("setDetector - detector " + detectorName + " and run #" + runNumber);
+        //logger.finest("setDetector - detector " + detectorName + " and run #" + runNumber);
         
         if (!isInitialized || !detectorName.equals(this.getDetector()) || runNumber != this.getRun()) {
-            if (!isInitialized) {
-                logger.fine("first time initialization");
-            }
+            //if (!isInitialized) {
+            //    logger.fine("first time initialization");
+            //}
             if (!this.isFrozen) {
-                if (!detectorName.equals(this.getDetector())) {
-                    logger.finest("detector name is different");
-                }
-                if (runNumber != this.getRun()) {
-                    logger.finest("run number is different");
-                }            
+                //if (!detectorName.equals(this.getDetector())) {
+                //    logger.finest("detector name is different");
+                //}
+                //if (runNumber != this.getRun()) {
+                //    logger.finest("run number is different");
+                //}            
                 logger.info("new detector " + detectorName + " and run #" + runNumber);
-                logger.fine("old detector " + this.getDetector() + " and run #" + this.getRun());
-                
+                //logger.fine("old detector " + this.getDetector() + " and run #" + this.getRun());
+             
                 initialize(detectorName, runNumber);
             } else {
                 logger.finest("Conditions changed but will be ignored because manager is frozen.");
@@ -238,83 +257,120 @@
         }
     }
     
+    /**
+     * Utility method to determine if a run number is from the 2012 Test Run.
+     * @param runNumber The run number.
+     * @return True if run number is from the Test Run.
+     */
     public static boolean isTestRun(int runNumber) {
         return runNumber > 0 && runNumber <= TEST_RUN_MAX_RUN;
     }
     
+    /**
+     * True if the current run number is from the Test Run.
+     * @return True if current run is from the Test Run.
+     */
     public boolean isTestRun() {
         return isTestRun(this.getRun());
     }
     
     /**
      * Perform all necessary initialization, including setup of the XML
-     * configuration and opening a connection to the database.
+     * configuration and loading of conditions onto the Detector.
      */
     protected void initialize(String detectorName, int runNumber) throws ConditionsNotFoundException {
 
-        logger.config("initializing " + getClass().getSimpleName() + " with detector " + detectorName + " and run number " + runNumber);
-
-        // Did the user not specify a config?
+        logger.config("initializing with detector " + detectorName + " and run number " + runNumber);
+
+        // Did the user not specify a specific configuration?
         if (resourceConfig == null && fileConfig == null) {
-            // We will try to pick a reasonable config based on the run number...
+            // We will try to pick a reasonable configuration based on the run number.
             if (runNumber > 0 && runNumber <= TEST_RUN_MAX_RUN) {
-                // This looks like the Test Run so use the custom config for it.
+                // This looks like the Test Run so use the custom configuration for it.
                 this.resourceConfig = DatabaseConditionsManager.TEST_RUN_CONFIG;
                 logger.config("using test run XML config " + this.resourceConfig);
             } else { 
-                // This is probably the Engineering Run or later so use the default config.
+                // This is probably the Engineering Run or later so use the default configuration.
                 this.resourceConfig = DatabaseConditionsManager.DEFAULT_CONFIG;
                 logger.config("using default XML config " + this.resourceConfig);
             }
         }
         
+        // Is there both a resource and file configuration specified?
         if (resourceConfig != null && fileConfig != null) {
+            // It is an error if both of these have been set externally.
             throw new RuntimeException("Both resource and file configuration are set.");
         }
                 
         if (this.resourceConfig != null) {
+            // Load the resource configuration.
             this.configure(getClass().getResourceAsStream(this.resourceConfig));
         } else if (this.fileConfig != null) {
             try {
+                // Load the file configuration.
                 this.configure(new FileInputStream(this.fileConfig));
             } catch (FileNotFoundException e) {
                 throw new RuntimeException(e);
             }
         }
         
-        // Open the database connection.
-        if (!isConnected()) {
-            openConnection();
+        // Is this run number from the Test Run?
+        if (isTestRun(runNumber)) {
+            // Load Test Run specific converters.
+            this.registerConditionsConverter(new TestRunSvtConditionsConverter());
+            this.registerConditionsConverter(new TestRunEcalConditionsConverter());
         } else {
-            logger.config("using existing connection " + connectionParameters.getConnectionString());
-        }
-        
+            // Load the default converters.
+            this.registerConditionsConverter(new SvtConditionsConverter());
+            this.registerConditionsConverter(new EcalConditionsConverter());
+        }
+                
         // Call the super class's setDetector method to construct the detector object.
         super.setDetector(detectorName, runNumber);
         
-        // Load conditions onto the ECAL subdetector object. 
-        try {
-            setupEcal();
-        } catch (Exception e) {
-            e.printStackTrace();
-            logger.log(Level.WARNING, "Error loading ECAL conditions onto detector.", e);
-        }
-        
-        // Load conditions onto the SVT subdetector object.
-        try {
-            setupSvt(runNumber);
-        } catch (Exception e) {
-            e.printStackTrace();
-            logger.log(Level.WARNING, "Error loading SVT conditions onto detector.", e);
-        }                       
+        // Should all conditions sets be pre-cached?
+        if (this.cacheAllConditions) {
+            // Cache the conditions sets of all registered converters.
+            logger.info("precaching all conditions sets ...");
+            this.cacheConditionsSets();
+        }
+        
+        // Should the ECAL detector be setup with conditions data?
+        if (this.setupEcalDetector) {
+            try {
+                // Load conditions onto the ECAL subdetector object. 
+                setupEcal();
+            } catch (Exception e) {
+                e.printStackTrace();
+                logger.log(Level.WARNING, "Error loading ECAL conditions onto detector.", e);
+            }
+        }
+        
+        // Should the SVT detector be setup with conditions data? 
+        if (this.setupSvtDetector) {
+            try {
+                // Load conditions onto the SVT subdetector object.
+                setupSvt(runNumber);
+            } catch (Exception e) {
+                e.printStackTrace();
+                logger.log(Level.WARNING, "Error loading SVT conditions onto detector.", e);
+            }                 
+        }
                        
         this.isInitialized = true;
 
-        logger.config(getClass().getSimpleName() + " is initialized");
-    }
-    
-    /**
-     * Get the current lcsim compact <code>Detector</code> object.
+        logger.config("conditions system initialized successfully");
+        
+        // Should the conditions system be frozen now?
+        if (this.freezeAfterInitialize) {
+            logger.info("executing freeze after initialize");
+            // Freeze the conditions system so subsequent updates will be ignored.
+            this.freeze();
+        }
+    }
+    
+    /**
+     * Get the current LCSim compact <code>Detector</code> object.
      * @return The detector object.
      */
     public Detector getDetectorObject() {
@@ -365,7 +421,7 @@
     }
     
     /**
-     * Set the connection parameters to the conditions database.
+     * Set the connection parameters of the conditions database.
      * @param connectionParameters The connection parameters.
      */
     public void setConnectionParameters(ConnectionParameters connectionParameters) {
@@ -386,9 +442,8 @@
      * @param tableName The name of the table.
      * @return The next collection ID.
      */
-    // TODO: If there are no records in the table, this method should simply return 1.  (for first collection)
     public int getNextCollectionID(String tableName) {
-        TableMetaData tableData = findTableMetaData(tableName);
+        TableMetaData tableData = tableRegistry.findByTableName(tableName);
         if (tableData == null)
             throw new IllegalArgumentException("There is no meta data for table " + tableName);
         ResultSet resultSet = selectQuery("SELECT MAX(collection_id)+1 FROM " + tableName);
@@ -431,44 +486,7 @@
             return false;
         }
     }
-
-    /**
-     * Get the list of table meta data.
-     * @return The list of table meta data.
-     */
-    public List<TableMetaData> getTableMetaDataList() {
-        return tableMetaData;
-    }
-
-    /**
-     * Find a table's meta data by key.
-     * @param name The name of the table.
-     * @return The table's meta data or null if does not exist.
-     */
-    public TableMetaData findTableMetaData(String name) {
-        for (TableMetaData meta : tableMetaData) {
-            if (meta.getKey().equals(name)) {
-                return meta;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find meta data by collection class type.
-     * @param type The collection class.
-     * @return The table meta data.
-     */
-    public List<TableMetaData> findTableMetaData(Class type) {
-        List<TableMetaData> metaDataList = new ArrayList<TableMetaData>();
-        for (TableMetaData meta : tableMetaData) {
-            if (meta.getCollectionClass().equals(type)) {
-                metaDataList.add(meta);
-            }
-        }
-        return metaDataList;
-    }
-
+   
     /**
      * This method can be used to perform a database SELECT query.
      * @param query The SQL query string.
@@ -536,7 +554,7 @@
      * @return The set of matching conditions records.
      */
     public ConditionsRecordCollection findConditionsRecords(String name) {
-        ConditionsRecordCollection runConditionsRecords = getConditionsData(ConditionsRecordCollection.class, TableConstants.CONDITIONS_RECORD);
+        ConditionsRecordCollection runConditionsRecords = this.getCollection(ConditionsRecordCollection.class);
         logger.fine("searching for condition " + name + " in " + runConditionsRecords.size() + " records");
         ConditionsRecordCollection foundConditionsRecords = new ConditionsRecordCollection();
         for (ConditionsRecord record : runConditionsRecords) {
@@ -555,45 +573,82 @@
         }
         return foundConditionsRecords;
     }
-    
+
+    /**
+     * Get a list of all the ConditionsRecord objects.
+     * @return The list of all the ConditionsRecord objects.
+     */
     public ConditionsRecordCollection getConditionsRecords() {
         ConditionsRecordCollection conditionsRecords = new ConditionsRecordCollection();
-        for (TableMetaData tableMetaData : this.getTableMetaDataList()) {
-            ConditionsRecordCollection foundConditionsRecords = findConditionsRecords(tableMetaData.getKey());
-            conditionsRecords.addAll(foundConditionsRecords); 
+        for (TableMetaData tableMetaData : tableRegistry.values()) {
+            try {
+                ConditionsRecordCollection foundConditionsRecords = findConditionsRecords(tableMetaData.getKey());
+                conditionsRecords.addAll(foundConditionsRecords); 
+            } catch (Exception e) {
+                logger.warning(e.getMessage());
+            }
         }        
         return conditionsRecords;
     }
     
+    /**
+     * This method can be called to "freeze" the conditions system so that
+     * any subsequent updates to run number or detector name will be ignored.
+     */
     public void freeze() {
         if (this.getDetector() != null && this.getRun() != -1) {
             this.isFrozen = true;
-            logger.config("The conditions manager has been frozen and will ignore subsequent updates until unfrozen.");
+            logger.config("The conditions system has been frozen and will ignore subsequent updates.");
         } else {
-            logger.warning("The conditions manager cannot be frozen now because detector or run number are not valid.");
-        }
-    }
-    
+            logger.warning("The conditions system cannot be frozen now because it is not initialized yet.");
+        }
+    }
+    
+    /**
+     * Un-freeze the conditions system so that updates will be received again.
+     */
     public void unfreeze() {
         this.isFrozen = false;
     }
     
+    /**
+     * True if conditions system is frozen.
+     * @return True if conditions system is frozen.
+     */
     public boolean isFrozen() {
         return this.isFrozen;
     }
     
+    /**
+     * Set the name of the ECAL sub-detector.
+     * @param ecalName The name of the ECAL.
+     */
     public void setEcalName(String ecalName) {
         this.ecalName = ecalName;
     }
     
+    /**
+     * Set the name of the SVT sub-detector.
+     * @param svtName The name of the SVT.
+     */
     public void setSvtName(String svtName) {
         this.svtName = svtName;
     }
     
+    /**
+     * Set a tag used to filter ConditionsRecords.
+     * @param tag The tag value used to filter ConditionsRecords.
+     */
     public void setTag(String tag) {
         this.tag = tag;
     }
 
+    /**
+     * Insert a collection of ConditionsObjects into the database.
+     * @param collection The collection to insert.
+     * @throws SQLException If there is a database error.
+     * @throws ConditionsObjectException If there is a problem with the ConditionsObjects.
+     */
     public <ObjectType extends ConditionsObject> void insertCollection(AbstractConditionsObjectCollection<ObjectType> collection) throws SQLException, ConditionsObjectException {
                 
         if (collection == null) {
@@ -605,15 +660,8 @@
 
         TableMetaData tableMetaData = collection.getTableMetaData();
         if (tableMetaData == null) {            
-            List<TableMetaData> tableMetaDataList = this.findTableMetaData(collection.getClass()); 
-            if (tableMetaDataList.size() == 0) {
-                throw new ConditionsObjectException("The conditions object collection is missing table meta data and none could be found by the conditions manager.");
-            } else {
-                // Use a default meta data object from the manager.
-                tableMetaData = tableMetaDataList.get(0);
-                collection.setTableMetaData(tableMetaData);
-                logger.fine("using default table meta data with table " + tableMetaData.getTableName() + " for collection of type " + collection.getClass().getCanonicalName());
-            }
+            tableMetaData = tableRegistry.findByCollectionType(collection.getClass()); 
+            logger.fine("using default table meta data with table " + tableMetaData.getTableName() + " for collection of type " + collection.getClass().getCanonicalName());
         }
         if (collection.getCollectionId() == -1) {
             try {
@@ -667,25 +715,66 @@
         closeConnection();
     }
     
+    /**
+     * Check if connected to the database.
+     * @return true if connected
+     */
+    public boolean isConnected() {
+        return isConnected;
+    }
+    
+    /**
+     * Get the default detector name for the Test Run.
+     * @return The default detector name for the Test Run.
+     */
+    public static String getDefaultTestRunDetectorName() {
+        return DEFAULT_TEST_RUN_DETECTOR;
+    }
+    
+    /**
+     * Get the default detector name for the Engineering Run.
+     * @return The default detector name for the Engineering Run.
+     */
+    public static String getDefaultEngRunDetectorName() {
+        return DEFAULT_ENG_RUN_DETECTOR;
+    }
+        
+    /**
+     * Get the Logger for this class, which can be used by related sub-classes
+     * if they do not have their own logger.
+     * @return The Logger for this class.
+     */
+    public Logger getLogger() {
+        return logger;
+    }
+    
+    /**
+     * Find table information from the name.
+     * @param name The name of the table.
+     * @return The table information or null if does not exist.
+     */
+    public TableMetaData findTableMetaData(String name) {
+        return this.tableRegistry.findByTableName(name);
+    }
+    
+    /**
+     * Find table information from the collection type.
+     * @param type The collection type.
+     * @return The table information or null if does not exist.
+     */
+    public TableMetaData findTableMetaData(Class<?> type) {
+        return this.tableRegistry.findByCollectionType(type);
+    }
+
     /*
-    public void selectCollection(AbstractConditionsObjectCollection collection) throws ConditionsObjectException {
-        int collectionId = collection.getCollectionId();
-        if (collectionId == -1) {
-            throw new ConditionsObjectException("Missing collection ID for select query.");
-        }
-        TableMetaData tableMetaData = collection.getTableMetaData();
-        String tableName = null;
-        if (tableMetaData != null) {
-            tableName = tableMetaData.getTableName();
-        } else {
-            List<TableMetaData> metaList = this.findTableMetaData(collection.getClass());
-            if (metaList.size() == 0) {
-                throw new ConditionsObjectException("Could not find meta data for collection with type " + collection.getClass().getCanonicalName());
-            }
-        }  
-    }
-    */
+     *******************************
+     * Private methods below here. *
+     *******************************
+     */
                       
+    /**
+     * Setup the ECAL subdetector with conditions information.
+     */
     private void setupEcal() {
         logger.config("setting up ECAL conditions on detector");
         EcalConditions conditions = getCachedConditions(EcalConditions.class, ECAL_CONDITIONS).getCachedData();
@@ -693,6 +782,10 @@
         logger.fine("done setting up ECAL conditions on detector");
     }
     
+    /**
+     * Set the SVT subdetector with conditions information.
+     * @param runNumber The run number.
+     */
     private void setupSvt(int runNumber) {
         if (isTestRun(runNumber)) {
             logger.config("loading Test Run SVT detector conditions");
@@ -707,29 +800,25 @@
     }
     
     /**
-     * Check if connected to the database.
-     * @return true if connected
-     */
-    public boolean isConnected() {
-        return isConnected;
-    }
-    
-    public static String getDefaultTestRunDetectorName() {
-        return DEFAULT_TEST_RUN_DETECTOR;
-    }
-    
-    public static String getDefaultEngRunDetectorName() {
-        return DEFAULT_ENG_RUN_DETECTOR;
-    }
-    
-    public void addTableMetaData(TableMetaData tableMetaData) {
-        this.tableMetaData.add(tableMetaData);
-    }
-    
-    public Logger getLogger() {
-        return logger;
-    }
-        
+     * Cache conditions sets for all known tables.
+     */
+    private void cacheConditionsSets() {
+        for (TableMetaData meta : tableRegistry.values()) {
+            try {
+                logger.fine("caching conditions " + meta.key + " with type "+ meta.collectionClass.getCanonicalName());
+                this.getCachedConditions(meta.collectionClass, meta.key);
+            } catch (Exception e) {
+                logger.warning("could not cache conditions " + meta.key);
+            }
+        }
+     }
+        
+    /**
+     * Choose whether to use the JLAB or SLAC external database
+     * and return a connection properties resource with the appropriate
+     * connection information.
+     * @return The connection properties resource.
+     */
     private String chooseConnectionPropertiesResource() {
         String connectionName = "slac";
         try {
@@ -757,14 +846,10 @@
 
         // Create XML document from stream.
         Document config = createDocument(in);
-
-        // Load the table meta data.
-        loadTableMetaData(config);
-
-        // Load the converter classes.
-        loadConverters(config);
-    }
-
+        
+        loadConfiguration(config);
+    }
+    
     /**
      * Create an XML document from an <code>InputStream</code>.
      * @param in The InputStream.
@@ -780,41 +865,7 @@
             throw new RuntimeException(e);
         }
         return config;
-    }
-
-    /**
-     * Load data converters from an XML document.
-     * @param config The XML document.
-     */
-    private void loadConverters(Document config) {
-
-        if (this.converters != null) {
-            this.converters.clear();
-        }
-
-        // Load the list of converters from the "converters" section of the config document.
-        loadConditionsConverters(config.getRootElement().getChild("converters"));
-
-        // Register the list of converters with this manager.
-        for (ConditionsConverter converter : converters) {
-            registerConditionsConverter(converter);
-            logger.config("registered converter " + converter.getClass().getSimpleName());
-        }
-    }
-
-    /**
-     * Load table meta data configuration from an XML document.
-     * @param config The XML document.
-     */
-    private void loadTableMetaData(Document config) {
-
-        if (this.tableMetaData != null) {
-            this.tableMetaData.clear();
-        }
-
-        // Load table meta data from the "tables" section of the config document.
-        loadTableMetaData(config.getRootElement().getChild("tables"));
-    }
+    }    
 
     /**
      * Setup the database connection from a file specified by a Java system
@@ -833,83 +884,34 @@
     }
 
     /**
-     * Load table meta data from the XML list.
-     * @param element The XML node containing a list of table elements.
-     */
-    @SuppressWarnings("unchecked")
-    void loadTableMetaData(Element element) {
-
-        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");
-
-            Element classesElement = tableElement.getChild("classes");
-            Element classElement = classesElement.getChild("object");
-            Element collectionElement = classesElement.getChild("collection");
-
-            String className = classElement.getAttributeValue("class");
-            String collectionName = collectionElement.getAttributeValue("class");
-
-            Class<? extends ConditionsObject> objectClass;
-            Class<?> rawObjectClass;
-            try {
-                rawObjectClass = Class.forName(className);
-                if (!ConditionsObject.class.isAssignableFrom(rawObjectClass)) {
-                    throw new RuntimeException("The class " + rawObjectClass.getSimpleName() + " does not extend ConditionsObject.");
-                }
-                objectClass = (Class<? extends ConditionsObject>) rawObjectClass;
-            } catch (ClassNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-
-            Class<? extends AbstractConditionsObjectCollection<?>> collectionClass;
-            Class<?> rawCollectionClass;
-            try {
-                rawCollectionClass = Class.forName(collectionName);
-                if (!AbstractConditionsObjectCollection.class.isAssignableFrom(rawCollectionClass))
-                    throw new RuntimeException("The class " + rawCollectionClass.getSimpleName() + " does not extend ConditionsObjectCollection.");
-                collectionClass = (Class<? extends AbstractConditionsObjectCollection<?>>) rawCollectionClass;
-            } catch (ClassNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-
-            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");
-                tableData.addField(fieldName);
-            }
-
-            tableMetaData.add(tableData);
-        }
-    }
-
-    /**
-     * Load conditions converters from the XML list.
-     * @param element The node with a list of child converter elements.
-     */
-    private void loadConditionsConverters(Element element) {
-        converters = 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 {
-                        converters.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);
-            }
-        }
-    }
-}
+     * Load configuration information from an XML document.
+     * @param document The XML document.
+     */
+    private void loadConfiguration(Document document) {
+        
+        Element node = document.getRootElement().getChild("configuration");
+        
+        if (node == null)
+            return;
+        
+        Element element = node.getChild("setupSvtDetector");
+        if (element != null) {
+            this.setupSvtDetector = Boolean.parseBoolean(element.getText());
+        }
+        
+        element = node.getChild("setupEcalDetector");
+        if (element != null) {
+            this.setupEcalDetector = Boolean.parseBoolean(element.getText());
+        }
+        
+        element = node.getChild("freezeAfterInitialize");
+        if (element != null) {
+            this.freezeAfterInitialize = Boolean.parseBoolean(element.getText());
+        }
+        
+        element = node.getChild("cacheAllCondition");
+        if (element != null) {
+            this.cacheAllConditions = Boolean.parseBoolean(element.getText());
+        }
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java	Tue Dec 30 16:44:44 2014
@@ -3,8 +3,20 @@
 import java.sql.ResultSet;
 import java.sql.Statement;
 
+/**
+ * Database utility methods.
+ * @author Jeremy McCormick <[log in to unmask]>
+ *
+ */
 public final class DatabaseUtilities {
+    
+    private DatabaseUtilities() {        
+    }
         
+    /**
+     * Cleanup a JDBC <code>ResultSet</code> by closing it and its <code>Statement</code>
+     * @param resultSet The database ResultSet.
+     */
     static void cleanup(ResultSet resultSet) {
         Statement statement = null;
         try {

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/Field.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/Field.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/Field.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,21 @@
+package org.hps.conditions.database;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This is a java <code>Annotation</code> for assigning a "get" method 
+ * to one or more database table columns.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD) 
+public @interface Field {
+    
+    /**
+     * The names of the table columns associated with this method.
+     * @return The names of the table column associated with this method.
+     */
+    String[] names() default "";
+}

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/MultipleCollectionsAction.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/MultipleCollectionsAction.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/MultipleCollectionsAction.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,14 @@
+package org.hps.conditions.database;
+
+/**
+ * This is the action that should be taken if there are multiple conditions sets
+ * returned from a query on type and name.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public enum MultipleCollectionsAction {
+    LAST_UPDATED,
+    LAST_CREATED,
+    LATEST_RUN_START,
+    COMBINE,
+    ERROR
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java	Tue Dec 30 16:44:44 2014
@@ -17,11 +17,7 @@
 
     private QueryBuilder() {
     }
-    
-    //static String buildSelect(TableMetaData tableMetaData, int collectionId) {  
-    //    return null;
-    //}
-    
+        
     static String buildSelect(String tableName, int collectionId, String[] fields, String order) {
         StringBuffer buff = new StringBuffer();
         buff.append("SELECT ");

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/Table.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/Table.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/Table.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,23 @@
+package org.hps.conditions.database;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be used to assign a class to one
+ * or more database tables.
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE) 
+public @interface Table {
+    
+    /**
+     * Get the names of the tables.
+     * @return The names of the tables.
+     */
+    public String[] names() default "";
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/TableConstants.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/TableConstants.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/TableConstants.java	Tue Dec 30 16:44:44 2014
@@ -6,23 +6,16 @@
  * values for conditions data. The actual table names for the conditions data
  * are defined externally in an XML configuration file read by the
  * {@link DatabaseConditionsManager}.
- * </p>
  * <p>
  * It is possible that the key and table names are defined differently in the
  * XML configuration, e.g. if the name of the key is not exactly the same as the
  * table name, but usually they are the same value.
- * </p>
  */
-// FIXME: This should really be called something like "ConditionsKeys" as the
-// table names
-// are found in the XML configuration only.
+// TODO: This should be removed as these names are all used by default and can be overridden if needed.
 public final class TableConstants {
 
     private TableConstants() {
     }
-
-    /** Conditions key for ConditionsRecord. */
-    public static final String CONDITIONS_RECORD = "conditions_records";
 
     /** Conditions key for combined ECal conditions. */
     public static final String ECAL_CONDITIONS = "ecal_conditions";

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/TableMetaData.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/TableMetaData.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/TableMetaData.java	Tue Dec 30 16:44:44 2014
@@ -1,22 +1,24 @@
 package org.hps.conditions.database;
 
+import java.util.ArrayList;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Set;
 
+import org.hps.conditions.api.AbstractConditionsObjectCollection;
 import org.hps.conditions.api.ConditionsObject;
-import org.hps.conditions.api.AbstractConditionsObjectCollection;
 
 /**
  * <p>
  * This class provides meta data about a conditions table, including a 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 AbstractConditionsObjectCollection}
- * s.
- * </p>
+ * the data onto {@link ConditionsObject} and {@link AbstractConditionsObjectCollection}.
+ * 
+ * @see org.hps.conditions.api.ConditionsObject
+ * @see org.hps.conditions.api.AbstractConditionsObjectCollection
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  * 
@@ -41,7 +43,15 @@
         this.objectClass = objectClass;
         this.collectionClass = collectionClass;
     }
-
+    
+    public TableMetaData(String key, String tableName, Class<? extends ConditionsObject> objectClass, Class<? extends AbstractConditionsObjectCollection<?>> collectionClass, Set<String> fieldNames) {
+        this.key = key;
+        this.tableName = tableName;
+        this.objectClass = objectClass;
+        this.collectionClass = collectionClass;
+        this.fieldNames = fieldNames;
+    }
+    
     /**
      * Get the type of object this table maps onto.
      * @return The type of object.
@@ -71,10 +81,11 @@
      * @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);
-        }
         fieldNames.add(name);
+    }
+    
+    void addFields(List<String> names) {
+        fieldNames.addAll(names);
     }
 
     /**
@@ -84,7 +95,7 @@
     public String getTableName() {
         return tableName;
     }
-
+    
     /**
      * Get the key of this conditions type. May be different from table name but
      * is usually the same.
@@ -93,4 +104,33 @@
     public String getKey() {
         return key;
     }
+    
+    static public List<TableMetaData> findByObjectType(List<TableMetaData> tableMetaDataList, Class<? extends ConditionsObject> objectType) {
+        System.out.println("findByObjectType - " + objectType.getCanonicalName());
+        List<TableMetaData> list = new ArrayList<TableMetaData>();
+        for (TableMetaData tableMetaData : tableMetaDataList) {
+            System.out.println("comparing to " + tableMetaData.getObjectClass().getCanonicalName());
+            if (tableMetaData.getObjectClass().equals(objectType)) {
+                System.out.println("found match");
+                list.add(tableMetaData);
+            } else {
+                System.out.println("does not match");
+            }
+        }
+        return list;
+    }
+    
+    public String toString() {
+        StringBuffer buff = new StringBuffer();
+        buff.append("tableMetaData: tableName = " + this.getTableName());  
+        buff.append(", objectClass = " + this.getObjectClass().getCanonicalName());
+        buff.append(", collectionClass = " + this.getCollectionClass().getCanonicalName());
+        buff.append(", fieldNames = ");
+        for (String field : this.getFieldNames()) {
+            buff.append(field + " ");
+        }
+        buff.setLength(buff.length() - 1);
+        buff.append('\n');
+        return buff.toString();
+    }
 }

Added: java/trunk/conditions/src/main/java/org/hps/conditions/database/TableRegistry.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/TableRegistry.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/TableRegistry.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,60 @@
+package org.hps.conditions.database;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.api.ConditionsObject;
+import org.hps.conditions.api.ConditionsObjectUtilities;
+
+/**
+ * This is a registry providing a map between tables and their meta-data.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public final class TableRegistry extends HashMap<String, TableMetaData> {
+    
+    protected Map<Class<? extends ConditionsObject>, TableMetaData> objectTypeMap =
+            new HashMap<Class<? extends ConditionsObject>, TableMetaData>();
+    
+    protected Map<Class<? extends AbstractConditionsObjectCollection<?>>, TableMetaData> collectionTypeMap =
+            new HashMap<Class<? extends AbstractConditionsObjectCollection<?>>, TableMetaData>();
+    
+    private TableRegistry() {
+    }
+    
+    public static TableRegistry create() {
+        TableRegistry registry = new TableRegistry();
+        for (Class<? extends ConditionsObject> objectType : ConditionsObjectUtilities.findConditionsObjectTypes()) {
+            String name = ConditionsObjectUtilities.getTableNames(objectType)[0];
+            Class<? extends AbstractConditionsObjectCollection<?>> collectionType = 
+                    ConditionsObjectUtilities.getCollectionType(objectType);
+            Set<String> fieldNames = ConditionsObjectUtilities.getFieldNames(objectType);
+            TableMetaData data = new TableMetaData(name, name, objectType, collectionType, fieldNames); 
+            registry.put(name, data);
+            registry.objectTypeMap.put(objectType, data);
+            registry.collectionTypeMap.put(collectionType, data);
+        }
+        return registry;
+    }
+    
+    public TableMetaData findByObjectType(Class<? extends ConditionsObject> objectType) {
+        return objectTypeMap.get(objectType);
+    }
+    
+    public TableMetaData findByCollectionType(Class<?> collectionType) {
+        return collectionTypeMap.get(collectionType);
+    }
+    
+    public TableMetaData findByTableName(String name) {
+        return this.get(name);
+    }
+    
+    public String toString() {  
+        StringBuffer buff = new StringBuffer();
+        for (TableMetaData tableMetaData : this.values()) {
+            buff.append(tableMetaData.toString());
+        }
+        return buff.toString();
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalBadChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalBadChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalBadChannel.java	Tue Dec 30 16:44:44 2014
@@ -2,18 +2,28 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * This class represents an ECAL channel that is considered "bad" which means it
  * should not be used in reconstruction.
  */
+@Table(names = {"ecal_bad_channels"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.COMBINE)
 public final class EcalBadChannel extends AbstractConditionsObject {
 
     public static class EcalBadChannelCollection extends AbstractConditionsObjectCollection<EcalBadChannel> {
     }
 
-    int getChannelId() {
+    /**
+     * Get the channel ID of the bad channel.
+     * @return The channel ID of the bad channel.
+     */
+    @Field(names = {"ecal_channel_id"})
+    public int getChannelId() {
         return getFieldValue("ecal_channel_id");
     }
-
 }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCalibration.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCalibration.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCalibration.java	Tue Dec 30 16:44:44 2014
@@ -2,6 +2,10 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * This class is a simplistic representation of ECal pedestal and noise values
@@ -12,6 +16,8 @@
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"ecal_calibrations"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class EcalCalibration extends AbstractConditionsObject {
 
     public static class EcalCalibrationCollection extends AbstractConditionsObjectCollection<EcalCalibration> {
@@ -30,6 +36,7 @@
      * Get the channel ID.
      * @return The channel ID.
      */
+    @Field(names = {"ecal_channel_id"})
     public int getChannelId() {
         return getFieldValue("ecal_channel_id");
     }
@@ -39,6 +46,7 @@
      * digitized pre-amp output.
      * @return The gain value.
      */
+    @Field(names = {"pedestal"})
     public double getPedestal() {
         return getFieldValue("pedestal");
     }
@@ -48,6 +56,7 @@
      * deviation of the digitized pre-amp output.
      * @return The noise value.
      */
+    @Field(names = {"noise"})
     public double getNoise() {
         return getFieldValue("noise");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java	Tue Dec 30 16:44:44 2014
@@ -10,6 +10,10 @@
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
 import org.hps.conditions.api.AbstractIdentifier;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.lcsim.detector.identifier.ExpandedIdentifier;
 import org.lcsim.detector.identifier.IExpandedIdentifier;
 import org.lcsim.detector.identifier.IIdentifierHelper;
@@ -20,6 +24,8 @@
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"ecal_channels"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.ERROR)
 public final class EcalChannel extends AbstractConditionsObject {
 
     /**
@@ -244,7 +250,9 @@
     /**
      * Get the crate number of the channel.
      * @return The crate number.
-     */
+     * 
+     */
+    @Field(names = {"crate"})
     public int getCrate() {
         return getFieldValue("crate");
     }
@@ -253,6 +261,7 @@
      * Get the slot number of the channel.
      * @return The slot number.
      */
+    @Field(names = {"slot"})
     public int getSlot() {
         return getFieldValue("slot");
     }
@@ -261,6 +270,7 @@
      * Get the channel number of the channel.
      * @return The channel number.
      */
+    @Field(names = {"channel"})
     public int getChannel() {
         return getFieldValue("channel");
     }
@@ -269,6 +279,7 @@
      * Get the x value of the channel.
      * @return The x value.
      */
+    @Field(names = {"x"})
     public int getX() {
         return getFieldValue("x");
     }
@@ -277,6 +288,7 @@
      * Get the y value of the channel.
      * @return The y value.
      */
+    @Field(names = {"y"})
     public int getY() {
         return getFieldValue("y");
     }
@@ -285,6 +297,7 @@
      * Get the ID of the channel.
      * @return The ID of the channel.
      */
+    @Field(names = {"channel_id"})
     public int getChannelId() {
         return getFieldValue("channel_id");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java	Tue Dec 30 16:44:44 2014
@@ -2,9 +2,6 @@
 
 import java.util.logging.Logger;
 
-import org.lcsim.conditions.ConditionsConverter;
-import org.lcsim.conditions.ConditionsManager;
-import org.lcsim.util.log.LogUtil;
 import org.hps.conditions.database.DatabaseConditionsManager;
 import org.hps.conditions.ecal.EcalBadChannel.EcalBadChannelCollection;
 import org.hps.conditions.ecal.EcalCalibration.EcalCalibrationCollection;
@@ -13,6 +10,9 @@
 import org.hps.conditions.ecal.EcalGain.EcalGainCollection;
 import org.hps.conditions.ecal.EcalTimeShift.EcalTimeShiftCollection;
 import org.hps.conditions.svt.AbstractSvtConditionsConverter;
+import org.lcsim.conditions.ConditionsConverter;
+import org.lcsim.conditions.ConditionsManager;
+import org.lcsim.util.log.LogUtil;
 
 /**
  * This class loads all ECal conditions into an {@link EcalConditions} object
@@ -22,19 +22,39 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
-public final class EcalConditionsConverter implements ConditionsConverter<EcalConditions> {
+public class EcalConditionsConverter implements ConditionsConverter<EcalConditions> {
 
     static Logger logger = LogUtil.create(AbstractSvtConditionsConverter.class);
     
+    protected EcalChannelCollection getEcalChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(EcalChannelCollection.class);
+    }
+    
+    protected EcalGainCollection getEcalGainCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(EcalGainCollection.class);
+    }
+    
+    protected EcalBadChannelCollection getEcalBadChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(EcalBadChannelCollection.class);
+    }
+    
+    protected EcalCalibrationCollection getEcalCalibrationCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(EcalCalibrationCollection.class);
+    }
+    
+    protected EcalTimeShiftCollection getEcalTimeShiftCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(EcalTimeShiftCollection.class);
+    }
+        
     /**
      * Create ECAL conditions object containing all data for the current run.
      */
     public EcalConditions getData(ConditionsManager manager, String name) {
 
-        DatabaseConditionsManager dbConditionsManager = (DatabaseConditionsManager) manager;
+        DatabaseConditionsManager databaseConditionsManager = (DatabaseConditionsManager) manager;
 
         // Get the ECal channel map from the conditions database
-        EcalChannelCollection channels = dbConditionsManager.getCollection(EcalChannelCollection.class);
+        EcalChannelCollection channels = getEcalChannelCollection(databaseConditionsManager);
 
         // Create the ECal conditions object that will be used to encapsulate
         // ECal conditions collections
@@ -45,7 +65,7 @@
 
         // Get the ECal gains from the conditions database and add them to the
         // conditions set
-        EcalGainCollection gains = dbConditionsManager.getCollection(EcalGainCollection.class);
+        EcalGainCollection gains = getEcalGainCollection(databaseConditionsManager);
         for (EcalGain gain : gains) {
             ChannelId channelId = new ChannelId(new int[] { gain.getChannelId() });
             EcalChannel channel = channels.findChannel(channelId);
@@ -53,20 +73,26 @@
         }
 
         // Get the ECal bad channels and add them to the conditions set
+        EcalBadChannelCollection badChannels = null;
         try {
-            EcalBadChannelCollection badChannels = dbConditionsManager.getCollection(EcalBadChannelCollection.class);
+            badChannels = getEcalBadChannelCollection(databaseConditionsManager);
+        } catch (RuntimeException e) {
+            databaseConditionsManager.getLogger().warning(e.getMessage());
+        }
+        if (badChannels != null) {
             for (EcalBadChannel badChannel : badChannels) {
+                if (badChannel == null) {
+                    throw new RuntimeException("The badChannel points to null.");
+                }
                 ChannelId channelId = new ChannelId(new int[] { badChannel.getChannelId() });
                 EcalChannel channel = channels.findChannel(channelId);
                 conditions.getChannelConstants(channel).setBadChannel(true);
             }
-        } catch (RuntimeException e) {
-            logger.warning("A set of bad channels were not found.");
         }
 
         // Get the ECal calibrations from the conditions database and add them
         // to the conditions set.
-        EcalCalibrationCollection calibrations = dbConditionsManager.getCollection(EcalCalibrationCollection.class);
+        EcalCalibrationCollection calibrations = getEcalCalibrationCollection(databaseConditionsManager);
         for (EcalCalibration calibration : calibrations) {
             ChannelId channelId = new ChannelId(new int[] { calibration.getChannelId() });
             EcalChannel channel = channels.findChannel(channelId);
@@ -75,9 +101,9 @@
 
         // Get the ECal time shifts from the conditions database and add them to
         // the conditions set.
-        EcalTimeShiftCollection timeShifts = dbConditionsManager.getCollection(EcalTimeShiftCollection.class);
+        EcalTimeShiftCollection timeShifts = getEcalTimeShiftCollection(databaseConditionsManager);
         for (EcalTimeShift timeShift : timeShifts) {
-            ChannelId channelId = new ChannelId(new int[] { timeShift.getChannelId() });
+            ChannelId channelId = new ChannelId(new int[] {timeShift.getChannelId()});
             EcalChannel channel = channels.findChannel(channelId);
             conditions.getChannelConstants(channel).setTimeShift(timeShift);
         }
@@ -93,5 +119,4 @@
     public Class<EcalConditions> getType() {
         return EcalConditions.class;
     }
-
 }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalGain.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalGain.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalGain.java	Tue Dec 30 16:44:44 2014
@@ -2,12 +2,18 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * A simplistic representation of gain values from the ECal conditions database.
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"ecal_gains", "test_run_ecal_gains"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class EcalGain extends AbstractConditionsObject {
 
     public static class EcalGainCollection extends AbstractConditionsObjectCollection<EcalGain> {
@@ -17,6 +23,7 @@
      * Get the gain value in units of MeV/ADC count.
      * @return The gain value.
      */
+    @Field(names = {"gain"})
     public double getGain() {
         return getFieldValue("gain");
     }
@@ -25,6 +32,7 @@
      * Get the ECal channel ID.
      * @return The ECal channel ID.
      */
+    @Field(names = {"ecal_channel_id"})
     public int getChannelId() {
         return getFieldValue("ecal_channel_id");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalLed.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalLed.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalLed.java	Tue Dec 30 16:44:44 2014
@@ -2,12 +2,18 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * A conditions class for representing the setup of the LED system in the ECAL
  * for one channel.
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = "ecal_leds")
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.ERROR)
 public class EcalLed extends AbstractConditionsObject {
 
     /**
@@ -20,6 +26,7 @@
      * Get the ECAL channel ID.
      * @return The ECAL channel ID.
      */
+    @Field(names = {"ecal_channel_id"})
     public int getEcalChannelId() {
         return getFieldValue("ecal_channel_id");
     }
@@ -28,6 +35,7 @@
      * Get the crate number assigned to this crystal.
      * @return The crate number.
      */
+    @Field(names = {"crate"})
     public int getCrateNumber() {
         return getFieldValue("crate");
     }
@@ -36,6 +44,7 @@
      * Get the LED number assigned to this crystal.
      * @return The LED number.
      */
+    @Field(names = {"number"})
     public int getLedNumber() {
         return getFieldValue("number");
     }
@@ -44,6 +53,7 @@
      * Get the time delay of this channel.
      * @return The time delay.
      */
+    @Field(names = {"time_delay"})
     public double getTimeDelay() {
         return getFieldValue("time_delay");
     }
@@ -52,6 +62,7 @@
      * Get the amplitude high setting.
      * @return The amplitude high setting.
      */
+    @Field(names = {"amplitude_high"})
     public double getAmplitudeHigh() {
         return getFieldValue("amplitude_high");
     }
@@ -60,6 +71,7 @@
      * Get the amplitude low setting.
      * @return The amplitude low setting.
      */
+    @Field(names = {"amplitude_low"})
     public double getAmplitudeLow() {
         return getFieldValue("amplitude_low");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalTimeShift.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalTimeShift.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalTimeShift.java	Tue Dec 30 16:44:44 2014
@@ -2,11 +2,17 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * This class represents a time shift calibration value for an ECAL channel.
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"ecal_time_shifts", "test_run_ecal_time_shifts"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class EcalTimeShift extends AbstractConditionsObject {
 
     /**
@@ -19,6 +25,7 @@
      * Get the channel ID.
      * @return The ECAL channel ID.
      */
+    @Field(names = {"ecal_channel_id"})
     public int getChannelId() {
         return getFieldValue("ecal_channel_id");
     }
@@ -27,6 +34,7 @@
      * Get the time shift in nanoseconds.
      * @return The time shift in nanoseconds.
      */
+    @Field(names = {"time_shift"})
     public double getTimeShift() {
         return getFieldValue("time_shift");
     }

Added: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/TestRunEcalConditionsConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/TestRunEcalConditionsConverter.java	(added)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/TestRunEcalConditionsConverter.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,39 @@
+package org.hps.conditions.ecal;
+
+import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.ecal.EcalBadChannel.EcalBadChannelCollection;
+import org.hps.conditions.ecal.EcalCalibration.EcalCalibrationCollection;
+import org.hps.conditions.ecal.EcalChannel.EcalChannelCollection;
+import org.hps.conditions.ecal.EcalGain.EcalGainCollection;
+import org.hps.conditions.ecal.EcalTimeShift.EcalTimeShiftCollection;
+
+/**
+ * This class loads all ECal conditions into an {@link EcalConditions} object
+ * from the database, based on the current run number known by the conditions
+ * manager.
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Omar Moreno <[log in to unmask]>
+ */
+public final class TestRunEcalConditionsConverter extends EcalConditionsConverter {
+    
+    protected EcalChannelCollection getEcalChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(EcalChannelCollection.class, "test_run_ecal_channels").getCachedData();
+    }
+    
+    protected EcalGainCollection getEcalGainCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(EcalGainCollection.class, "test_run_ecal_gains").getCachedData();
+    }
+    
+    protected EcalBadChannelCollection getEcalBadChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(EcalBadChannelCollection.class, "test_run_ecal_bad_channels").getCachedData();
+    }
+    
+    protected EcalCalibrationCollection getEcalCalibrationCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(EcalCalibrationCollection.class, "test_run_ecal_calibrations").getCachedData();
+    }
+    
+    protected EcalTimeShiftCollection getEcalTimeShiftCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(EcalTimeShiftCollection.class, "test_run_ecal_time_shifts").getCachedData();
+    }
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/package-info.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/package-info.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/package-info.java	Tue Dec 30 16:44:44 2014
@@ -1,21 +1,21 @@
 /**
+ * <p>
  * The classes in this package represent detector conditions in the HPS ECAL subsystem.
- * 
+ * <p>
  * Each {@link EcalChannel} represents one physical crystal in the detector.
- * 
+ * <p>
  * The {@link EcalBadChannel} is a channel that is malfunctioning or dead and should not 
  * be used for reconstruction.  It is up to the reconstruction Drivers to filter out 
  * these channels.
- * 
+ * <p>
  * The {@link EcalCalibration} contains the pedestal and noise values for a channel, 
  * which are the mean and the standard deviation of the digitized pre-amp output.
- * 
+ * <p>
  * The {@link EcalGain} is the channel gain in units of MeV/ADC counts.
- * 
- * The energy of a hit is reconstructed by multipling the gain by the pedestal-subtracted
+ * <p>
+ * The energy of a hit is reconstructed by multiplying the gain by the pedestal-subtracted
  * ADC integral (e.g. in Test Run 2012 data). 
  * 
  * @author Jeremy McCormick <[log in to unmask]>
- * @author Sho Uemura <[log in to unmask]>
  */
 package org.hps.conditions.ecal;

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtChannel.java	Tue Dec 30 16:44:44 2014
@@ -6,6 +6,7 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Field;
 import org.hps.util.Pair;
 
 /**
@@ -79,6 +80,7 @@
      * 
      * @return The channel ID.
      */
+    @Field(names = {"channel_id"})
     public int getChannelID() {
         return getFieldValue("channel_id");
     }
@@ -88,8 +90,8 @@
      * 
      * @return The channel number.
      */
+    @Field(names = {"channel"})
     public int getChannel() {
         return getFieldValue("channel");
     }
-
-}
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtConditionsConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtConditionsConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtConditionsConverter.java	Tue Dec 30 16:44:44 2014
@@ -24,6 +24,22 @@
     protected T conditions;
     static Logger logger = LogUtil.create(AbstractSvtConditionsConverter.class);
 
+    protected SvtShapeFitParametersCollection getSvtShapeFitParametersCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(SvtShapeFitParametersCollection.class);
+    }
+    
+    protected SvtBadChannelCollection getSvtBadChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(SvtBadChannelCollection.class);
+    }
+    
+    protected SvtCalibrationCollection getSvtCalibrationCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(SvtCalibrationCollection.class);
+    }
+    
+    protected SvtGainCollection getSvtGainCollection(DatabaseConditionsManager manager) {
+        return manager.getCollection(SvtGainCollection.class);
+    }
+    
     /**
      * Create and return the SVT conditions object.
      * @param manager The current conditions manager.
@@ -33,26 +49,23 @@
 
         DatabaseConditionsManager dbConditionsManager = (DatabaseConditionsManager) manager;
 
-        // Get the SVT calibrations (baseline, noise) from the conditions
-        // database
-        SvtCalibrationCollection calibrations = dbConditionsManager.getCollection(SvtCalibrationCollection.class);
+        // Get the SVT calibrations (baseline, noise) from the conditions database
+        SvtCalibrationCollection calibrations = getSvtCalibrationCollection(dbConditionsManager);
         for (SvtCalibration calibration : calibrations) {
             AbstractSvtChannel channel = conditions.getChannelMap().findChannel(calibration.getChannelID());
             conditions.getChannelConstants(channel).setCalibration(calibration);
         }
 
         // Get the Channel pulse fit parameters from the conditions database
-        SvtShapeFitParametersCollection shapeFitParametersCollection = dbConditionsManager.getCollection(SvtShapeFitParametersCollection.class);
+        SvtShapeFitParametersCollection shapeFitParametersCollection = getSvtShapeFitParametersCollection(dbConditionsManager);
         for (SvtShapeFitParameters shapeFitParameters : shapeFitParametersCollection) {
             AbstractSvtChannel channel = conditions.getChannelMap().findChannel(shapeFitParameters.getChannelID());
             conditions.getChannelConstants(channel).setShapeFitParameters(shapeFitParameters);
         }
 
-        // Get the bad channels from the conditions database. If there aren't
-        // any bad channels,
-        // notify the user and move on.
+        // Get the bad channels from the conditions database. If there aren't any bad channels, notify the user and move on.
         try {
-            SvtBadChannelCollection badChannels = dbConditionsManager.getCollection(SvtBadChannelCollection.class);
+            SvtBadChannelCollection badChannels = getSvtBadChannelCollection(dbConditionsManager);
             for (SvtBadChannel badChannel : badChannels) {
                 AbstractSvtChannel channel = conditions.getChannelMap().findChannel(badChannel.getChannelId());
                 conditions.getChannelConstants(channel).setBadChannel(true);
@@ -62,7 +75,7 @@
         }
 
         // Get the gains and offsets from the conditions database
-        SvtGainCollection channelGains = dbConditionsManager.getCollection(SvtGainCollection.class);
+        SvtGainCollection channelGains = getSvtGainCollection(dbConditionsManager);
         for (SvtGain channelGain : channelGains) {
             int channelId = channelGain.getChannelID();
             AbstractSvtChannel channel = conditions.getChannelMap().findChannel(channelId);
@@ -71,4 +84,4 @@
 
         return conditions;
     }
-}
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtDaqMapping.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtDaqMapping.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtDaqMapping.java	Tue Dec 30 16:44:44 2014
@@ -1,9 +1,10 @@
 package org.hps.conditions.svt;
 
-import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Field;
 import org.hps.util.Pair;
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 
 /**
  * This abstract class provides some of the basic functionality used to access
@@ -47,14 +48,17 @@
 
     }
 
+    @Field(names = {"svt_half"})
     public String getSvtHalf() {
         return getFieldValue("svt_half");
     }
 
+    @Field(names = {"layer"})
     public int getLayerNumber() {
         return getFieldValue("layer");
     }
 
+    @Field(names = {"orientation"})
     public String getOrientation() {
         return getFieldValue("orientation");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtT0Shift.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtT0Shift.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/AbstractSvtT0Shift.java	Tue Dec 30 16:44:44 2014
@@ -2,6 +2,7 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Field;
 import org.hps.util.Pair;
 
 /**
@@ -30,6 +31,7 @@
      * 
      * @return The t0 shift.
      */
+    @Field(names = {"t0_shift"})
     public double getT0Shift() {
         return getFieldValue("t0_shift");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtAlignmentConstant.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtAlignmentConstant.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtAlignmentConstant.java	Tue Dec 30 16:44:44 2014
@@ -2,25 +2,29 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * <p>
  * Encapsulates an SVT alignment constant, which is an encoded key plus a double
  * value.
- * </p>
  * <p>
  * The format of the keys is ABCDE where:<br>
  * A == half == [1,2]<br>
  * B == alignment type == [1,2]<br>
  * C == unit axis == [1,2,3]<br>
  * DE == module number == [1,10]
- * </p>
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
-public class SvtAlignmentConstant extends AbstractConditionsObject {
+@Table(names = "svt_alignments")
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_UPDATED)
+public final class SvtAlignmentConstant extends AbstractConditionsObject {
 
-    public static class SvtAlignmentCollection extends AbstractConditionsObjectCollection<SvtAlignmentConstant> {
+    public static class SvtAlignmentConstantCollection extends AbstractConditionsObjectCollection<SvtAlignmentConstant> {
     }
 
     /** Top or bottom half. */
@@ -72,6 +76,7 @@
      * Get the alignment constant's full key with the encoded information.
      * @return the alignment constant's key
      */
+    @Field(names = {"parameter"})
     public String getParameter() {
         return getFieldValue("parameter");
     }
@@ -80,6 +85,7 @@
      * Get the the alignment constant's value which is always a single double.
      * @return the alignment constant's value as a double
      */
+    @Field(names = {"value"})
     public double getValue() {
         return getFieldValue("value");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtBadChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtBadChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtBadChannel.java	Tue Dec 30 16:44:44 2014
@@ -2,18 +2,25 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
+@Table(names = {"svt_bad_channels", "test_run_svt_bad_channels"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.COMBINE)
 public final class SvtBadChannel extends AbstractConditionsObject {
 
     public static class SvtBadChannelCollection extends AbstractConditionsObjectCollection<SvtBadChannel> {
     }
 
+    @Field(names = {"svt_channel_id"})
     public int getChannelId() {
         return getFieldValue("svt_channel_id");
     }
 
+    @Field(names = {"notes"})
     public int getNote() {
         return getFieldValue("notes");
     }
-
 }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtCalibration.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtCalibration.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtCalibration.java	Tue Dec 30 16:44:44 2014
@@ -2,6 +2,10 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 import static org.hps.conditions.svt.SvtChannel.MAX_NUMBER_OF_SAMPLES;
 
@@ -11,6 +15,8 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"svt_calibrations", "test_run_svt_calibrations"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_UPDATED)
 public final class SvtCalibration extends AbstractConditionsObject {
 
     public static class SvtCalibrationCollection extends AbstractConditionsObjectCollection<SvtCalibration> {
@@ -20,6 +26,7 @@
      * Get the channel ID.
      * @return The channel ID.
      */
+    @Field(names = {"svt_channel_id"})
     public int getChannelID() {
         return getFieldValue("svt_channel_id");
     }
@@ -28,9 +35,10 @@
      * Get the noise value.
      * @return The noise value.
      */
+    @Field(names = {"noise_0", "noise_1", "noise_2", "noise_3", "noise_4", "noise_5"})
     public double getNoise(int sample) {
         if (sample < 0 || sample > MAX_NUMBER_OF_SAMPLES) {
-            throw new RuntimeException("Sample number is not within range.");
+            throw new IllegalArgumentException("Sample number is not within range.");
         }
         return getFieldValue(Double.class, "noise_" + Integer.toString(sample));
     }
@@ -39,9 +47,10 @@
      * Get the pedestal value.
      * @return The pedestal value.
      */
+    @Field(names = {"pedestal_0", "pedestal_1", "pedestal_2", "pedestal_3", "pedestal_4", "pedestal_5"})
     public double getPedestal(int sample) {
         if (sample < 0 || sample > MAX_NUMBER_OF_SAMPLES) {
-            throw new RuntimeException("Sample number is not within range.");
+            throw new IllegalArgumentException("Sample number is not within range.");
         }
         return getFieldValue(Double.class, "pedestal_" + Integer.toString(sample));
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtChannel.java	Tue Dec 30 16:44:44 2014
@@ -4,6 +4,10 @@
 import java.util.Collection;
 import java.util.List;
 
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.hps.util.Pair;
 
 /**
@@ -13,6 +17,8 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"svt_channels"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.ERROR)
 public final class SvtChannel extends AbstractSvtChannel {
 
     public static class SvtChannelCollection extends AbstractSvtChannel.AbstractSvtChannelCollection<SvtChannel> {
@@ -40,6 +46,7 @@
      * Get the FEB ID.
      * @return The FEB ID.
      */
+    @Field(names = {"feb_id"})
     public int getFebID() {
         return getFieldValue("feb_id");
     }
@@ -48,6 +55,7 @@
      * Get the FEB hybrid ID.
      * @return The FEB hybrid ID.
      */
+    @Field(names = {"feb_hybrid_id"})
     public int getFebHybridID() {
         return getFieldValue("feb_hybrid_id");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtConfiguration.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtConfiguration.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtConfiguration.java	Tue Dec 30 16:44:44 2014
@@ -7,6 +7,10 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.jdom.Document;
 import org.jdom.JDOMException;
 import org.jdom.input.SAXBuilder;
@@ -16,6 +20,8 @@
 /**
  * This is a simple class for getting an SVT XML configuration file.
  */
+@Table(names = {"svt_configurations"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_UPDATED)
 public class SvtConfiguration extends AbstractConditionsObject {
 
     public static class SvtConfigurationCollection extends AbstractConditionsObjectCollection<SvtConfiguration> {
@@ -25,8 +31,14 @@
      * Get the filename associated with this configuration.
      * @return The filename associated with the configuration.
      */
+    @Field(names = {"filename"})
     public String getFileName() {
         return getFieldValue("filename");
+    }
+    
+    @Field(names = {"content"})
+    public byte[] getContent() {
+        return getFieldValue("content");
     }
 
     /**

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDaqMapping.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDaqMapping.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDaqMapping.java	Tue Dec 30 16:44:44 2014
@@ -1,7 +1,10 @@
 package org.hps.conditions.svt;
 
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
-
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.hps.util.Pair;
 
 /**
@@ -10,6 +13,8 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"svt_daq_map"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.ERROR)
 public class SvtDaqMapping extends AbstractSvtDaqMapping {
 
     public static class SvtDaqMappingCollection extends AbstractSvtDaqMappingCollection<SvtDaqMapping> {
@@ -95,15 +100,18 @@
         }
     }
 
+    @Field(names = {"feb_id"})
     public int getFebID() {
         return getFieldValue("feb_id");
     }
 
+    @Field(names = {"feb_hybrid_id"})
     public int getFebHybridID() {
         return getFieldValue("feb_hybrid_id");
     }
 
+    @Field(names = {"side"})
     public String getSide() {
         return getFieldValue("side");
     }
-}
+}

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtGain.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtGain.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtGain.java	Tue Dec 30 16:44:44 2014
@@ -2,11 +2,17 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * This class represents gain measurements for a single SVT channel.
  * @author Jeremy McCormick <[log in to unmask]>
  */
+@Table(names = {"svt_gains", "test_run_svt_gains"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class SvtGain extends AbstractConditionsObject {
 
     public static class SvtGainCollection extends AbstractConditionsObjectCollection<SvtGain> {
@@ -16,6 +22,7 @@
      * Get the channel ID.
      * @return The channel ID.
      */
+    @Field(names = {"svt_channel_id"})
     public int getChannelID() {
         return getFieldValue(Integer.class, "svt_channel_id");
     }
@@ -24,6 +31,7 @@
      * Get the gain.
      * @return The gain value.
      */
+    @Field(names = {"gain"})
     public double getGain() {
         return getFieldValue(Double.class, "gain");
     }
@@ -32,6 +40,7 @@
      * Get the offset.
      * @return The offset value.
      */
+    @Field(names = {"offset"})
     public double getOffset() {
         return getFieldValue(Double.class, "offset");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtShapeFitParameters.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtShapeFitParameters.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtShapeFitParameters.java	Tue Dec 30 16:44:44 2014
@@ -2,6 +2,10 @@
 
 import org.hps.conditions.api.AbstractConditionsObject;
 import org.hps.conditions.api.AbstractConditionsObjectCollection;
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 
 /**
  * This class encapsulates the shape fit parameters for an SVT channel.
@@ -9,6 +13,8 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"svt_shape_fit_parameters", "test_run_svt_shape_fit_parameters"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class SvtShapeFitParameters extends AbstractConditionsObject {
 
     public static class SvtShapeFitParametersCollection extends AbstractConditionsObjectCollection<SvtShapeFitParameters> {
@@ -18,7 +24,8 @@
      * Get the SVT channel ID.
      * @return The SVT channel ID.
      */
-    int getChannelID() {
+    @Field(names = {"svt_channel_id"})
+    public int getChannelID() {
         return getFieldValue(Integer.class, "svt_channel_id");
     }
 
@@ -26,7 +33,8 @@
      * Get the amplitude.
      * @return The amplifude.
      */
-    double getAmplitude() {
+    @Field(names = {"amplitude"})
+    public double getAmplitude() {
         return getFieldValue(Double.class, "amplitude");
     }
 
@@ -34,7 +42,8 @@
      * Get t0.
      * @return t0.
      */
-    double getT0() {
+    @Field(names = {"t0"})
+    public double getT0() {
         return getFieldValue(Double.class, "t0");
     }
 
@@ -42,7 +51,8 @@
      * Get tp.
      * @return tp.
      */
-    double getTp() {
+    @Field(names = {"tp"})
+    public double getTp() {
         return getFieldValue(Double.class, "tp");
     }
 

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtT0Shift.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtT0Shift.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtT0Shift.java	Tue Dec 30 16:44:44 2014
@@ -1,5 +1,9 @@
 package org.hps.conditions.svt;
 
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.hps.util.Pair;
 
 /**
@@ -9,6 +13,8 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"svt_t0_shifts"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class SvtT0Shift extends AbstractSvtT0Shift {
 
     public static class SvtT0ShiftCollection extends AbstractSvtT0Shift.AbstractSvtT0ShiftCollection<SvtT0Shift> {
@@ -38,7 +44,8 @@
      * 
      * @return The FEB ID.
      */
-    int getFebID() {
+    @Field(names = {"feb_id"})
+    public int getFebID() {
         return getFieldValue("feb_id");
     }
 
@@ -47,7 +54,8 @@
      *
      * @return The FEB hybrid ID.
      */
-    int getFebHybridID() {
+    @Field(names = {"feb_hybrid_id"})
+    public int getFebHybridID() {
         return getFieldValue("feb_hybrid_id");
     }
 }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtChannel.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtChannel.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtChannel.java	Tue Dec 30 16:44:44 2014
@@ -4,8 +4,14 @@
 import java.util.Collection;
 import java.util.List;
 
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.hps.util.Pair;
 
+@Table(names = {"test_run_svt_channels"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.ERROR)
 public final class TestRunSvtChannel extends AbstractSvtChannel {
 
     public static class TestRunSvtChannelCollection extends AbstractSvtChannel.AbstractSvtChannelCollection<TestRunSvtChannel> {
@@ -29,6 +35,7 @@
      * 
      * @return The FPGA ID
      */
+    @Field(names = {"fpga"})
     public int getFpgaID() {
         return getFieldValue("fpga");
     }
@@ -38,6 +45,7 @@
      * 
      * @return The hybrid ID.
      */
+    @Field(names = {"hybrid"})
     public int getHybridID() {
         return getFieldValue("hybrid");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditions.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditions.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditions.java	Tue Dec 30 16:44:44 2014
@@ -17,7 +17,7 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  */
-public class TestRunSvtConditions extends AbstractSvtConditions {
+public final class TestRunSvtConditions extends AbstractSvtConditions {
 
     /**
      * Get the {@link TestRunSvtDaqMappingCollection} associated with these

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditionsConverter.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditionsConverter.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtConditionsConverter.java	Tue Dec 30 16:44:44 2014
@@ -2,6 +2,10 @@
 
 import org.lcsim.conditions.ConditionsManager;
 import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.svt.SvtBadChannel.SvtBadChannelCollection;
+import org.hps.conditions.svt.SvtCalibration.SvtCalibrationCollection;
+import org.hps.conditions.svt.SvtGain.SvtGainCollection;
+import org.hps.conditions.svt.SvtShapeFitParameters.SvtShapeFitParametersCollection;
 import org.hps.conditions.svt.TestRunSvtChannel.TestRunSvtChannelCollection;
 import org.hps.conditions.svt.TestRunSvtDaqMapping.TestRunSvtDaqMappingCollection;
 import org.hps.conditions.svt.TestRunSvtT0Shift.TestRunSvtT0ShiftCollection;
@@ -10,6 +14,22 @@
 
     public TestRunSvtConditionsConverter() {
         this.conditions = new TestRunSvtConditions();
+    }
+    
+    protected SvtShapeFitParametersCollection getSvtShapeFitParametersCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(SvtShapeFitParametersCollection.class, "test_run_svt_shape_fit_parameters").getCachedData();
+    }
+    
+    protected SvtBadChannelCollection getSvtBadChannelCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(SvtBadChannelCollection.class, "test_run_svt_bad_channels").getCachedData();
+    }
+    
+    protected SvtCalibrationCollection getSvtCalibrationCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(SvtCalibrationCollection.class, "test_run_svt_calibrations").getCachedData();
+    }
+    
+    protected SvtGainCollection getSvtGainCollection(DatabaseConditionsManager manager) {
+        return manager.getCachedConditions(SvtGainCollection.class, "test_run_svt_gains").getCachedData();
     }
 
     /**

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java	Tue Dec 30 16:44:44 2014
@@ -1,16 +1,21 @@
 package org.hps.conditions.svt;
 
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
+import org.hps.util.Pair;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.detector.tracker.silicon.HpsTestRunSiSensor;
-
-import org.hps.util.Pair;
 
 /**
  * This class encapsulates the Test run SVT DAQ map.
  * 
  * @author Omar Moreno <[log in to unmask]>
  */
-public class TestRunSvtDaqMapping extends AbstractSvtDaqMapping {
+@Table(names = {"test_run_svt_daq_map"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
+public final class TestRunSvtDaqMapping extends AbstractSvtDaqMapping {
 
     public static class TestRunSvtDaqMappingCollection extends AbstractSvtDaqMappingCollection<TestRunSvtDaqMapping> {
 
@@ -91,10 +96,12 @@
         }
     }
 
+    @Field(names = {"fpga"})
     public int getFpgaID() {
         return getFieldValue("fpga");
     }
 
+    @Field(names = {"hybrid"})
     public int getHybridID() {
         return getFieldValue("hybrid");
     }

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtT0Shift.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtT0Shift.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtT0Shift.java	Tue Dec 30 16:44:44 2014
@@ -1,5 +1,9 @@
 package org.hps.conditions.svt;
 
+import org.hps.conditions.database.Converter;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.hps.conditions.database.Table;
 import org.hps.util.Pair;
 
 /**
@@ -8,6 +12,8 @@
  * 
  * @author Omar Moreno <[log in to unmask]>
  */
+@Table(names = {"test_run_svt_t0_shifts"})
+@Converter(multipleCollectionsAction = MultipleCollectionsAction.LAST_CREATED)
 public final class TestRunSvtT0Shift extends AbstractSvtT0Shift {
 
     public static class TestRunSvtT0ShiftCollection extends AbstractSvtT0Shift.AbstractSvtT0ShiftCollection<TestRunSvtT0Shift> {
@@ -39,7 +45,8 @@
      * 
      * @return The FPGA ID.
      */
-    int getFpgaID() {
+    @Field(names = {"fpga"})
+    public int getFpgaID() {
         return getFieldValue("fpga");
     }
 
@@ -48,7 +55,8 @@
      * 
      * @return The hybrid ID.
      */
-    int getHybridID() {
+    @Field(names = {"hybrid"})
+    public int getHybridID() {
         return getFieldValue("hybrid");
     }
 }

Added: java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_engrun.xml
 =============================================================================
--- java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_engrun.xml	(added)
+++ java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_engrun.xml	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,8 @@
+<conditions_database>
+    <configuration>
+        <setupSvtDetector>false</setupSvtDetector>
+        <setupEcalDetector>true</setupEcalDetector>
+        <cacheAllConditions>false</cacheAllConditions>
+        <freezeAfterInitialize>false</freezeAfterInitialize>
+    </configuration>
+</conditions_database>

Added: java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_prod.xml
 =============================================================================
--- java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_prod.xml	(added)
+++ java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_prod.xml	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,8 @@
+<conditions_database>
+    <configuration>
+        <setupSvtDetector>true</setupSvtDetector>
+        <setupEcalDetector>true</setupEcalDetector>
+        <cacheAllConditions>false</cacheAllConditions>
+        <freezeAfterInitialize>false</freezeAfterInitialize>
+    </configuration>
+</conditions_database>

Modified: java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml
 =============================================================================
--- java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml	(original)
+++ java/trunk/conditions/src/main/resources/org/hps/conditions/config/conditions_database_testrun_2012.xml	Tue Dec 30 16:44:44 2014
@@ -1,217 +1,8 @@
-<conditions_database name="hps_conditions_test" version="1.0" author="jeremym">
-      
-    <converters>
-
-        <!-- ConditionsRecord converter -->
-        <converter class="org.hps.conditions.database.ConditionsRecordConverter"/>
-
-        <!-- SVT converters -->
-        <converter class="org.hps.conditions.svt.TestRunSvtConditionsConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$TestRunSvtChannelConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$TestRunSvtDaqMappingConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$TestRunSvtT0ShiftConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$SvtCalibrationConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$SvtShapeFitParametersConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$SvtGainConverter"/>
-        <converter class="org.hps.conditions.svt.SvtConverterRegistry$SvtBadChannelConverter"/>
-
-        <!-- ECal converters -->
-        <converter class="org.hps.conditions.ecal.EcalConditionsConverter"/>
-        <converter class="org.hps.conditions.ecal.EcalConverterRegistry$EcalBadChannelConverter"/>
-        <converter class="org.hps.conditions.ecal.EcalConverterRegistry$EcalChannelConverter"/>
-        <converter class="org.hps.conditions.ecal.EcalConverterRegistry$EcalGainConverter"/>
-        <converter class="org.hps.conditions.ecal.EcalConverterRegistry$EcalCalibrationConverter"/>
-        <converter class="org.hps.conditions.ecal.EcalConverterRegistry$EcalTimeShiftConverter"/>
-
-        <!-- Beam conditions converter -->
-        <converter class="org.hps.conditions.beam.BeamConverterRegistry$BeamCurrentConverter"/>
-    </converters>
-
-    <tables>
-    
-        <table key="conditions_records" name="conditions">
-            <classes> 
-                <object class="org.hps.conditions.api.ConditionsRecord"/>
-                <collection class="org.hps.conditions.api.ConditionsRecord$ConditionsRecordCollection"/>
-            </classes>
-            <fields>
-                <field name="run_start" />
-                <field name="run_end" />
-                <field name="updated" />
-                <field name="created" />
-                <field name="created_by" />
-                <field name="notes" />
-                <field name="name" />
-                <field name="table_name" />
-                <field name="collection_id" />
-            </fields>
-        </table>
-
-        <table key="test_run_svt_channels" name="test_run_svt_channels">
-            <classes>
-                <object class="org.hps.conditions.svt.TestRunSvtChannel"/>
-                <collection class="org.hps.conditions.svt.TestRunSvtChannel$TestRunSvtChannelCollection"/>
-            </classes>
-            <fields>
-                <field name="channel_id" />
-                <field name="fpga" />
-                <field name="hybrid" />
-                <field name="channel" />
-            </fields>
-        </table>
-    
-        <table key="test_run_svt_calibrations" name="test_run_svt_calibrations">
-            <classes>
-                <object class="org.hps.conditions.svt.SvtCalibration"/>
-                <collection class="org.hps.conditions.svt.SvtCalibration$SvtCalibrationCollection"/>
-            </classes>
-            <fields>
-                <field name="svt_channel_id" />
-                <field name="pedestal_0" />
-                <field name="pedestal_1" />
-                <field name="pedestal_2" />
-                <field name="pedestal_3" />
-                <field name="pedestal_4" />
-                <field name="pedestal_5" />
-                <field name="noise_0" />
-                <field name="noise_1" />
-                <field name="noise_2" />
-                <field name="noise_3" />
-                <field name="noise_4" />
-                <field name="noise_5" />
-            </fields>        
-        </table>
-
-        <table key="test_run_svt_shape_fit_parameters" name="test_run_svt_shape_fit_parameters">
-            <classes>
-                <object class="org.hps.conditions.svt.SvtShapeFitParameters"/>
-                <collection class="org.hps.conditions.svt.SvtShapeFitParameters$SvtShapeFitParametersCollection"/>
-            </classes>
-            <fields>
-                <field name="svt_channel_id"    />
-                <field name="amplitude"         />
-                <field name="t0"                />
-                <field name="tp"                />
-            </fields>        
-        </table>
-
-        <table key="test_run_svt_gains" name="test_run_svt_gains">
-            <classes>
-                <object class="org.hps.conditions.svt.SvtGain"/> 
-                <collection class="org.hps.conditions.svt.SvtGain$SvtGainCollection"/>
-            </classes>            
-            <fields>
-                <field name="svt_channel_id" />
-                <field name="gain" />
-                <field name="offset" />
-            </fields>
-        </table>       
-         
-        <table key="test_run_svt_t0_shifts" name="test_run_svt_t0_shifts">
-            <classes>
-                <object class="org.hps.conditions.svt.TestRunSvtT0Shift"/>
-                <collection class="org.hps.conditions.svt.TestRunSvtT0Shift$TestRunSvtT0ShiftCollection"/>
-            </classes>
-            <fields>
-                <field name="fpga"        />
-                <field name="hybrid" />
-                <field name="t0_shift"      />
-            </fields>        
-        </table>
-         
-        <table key="test_run_svt_bad_channels" name="test_run_svt_bad_channels">
-            <classes>
-                <object class="org.hps.conditions.svt.SvtBadChannel"/>
-                <collection class="org.hps.conditions.svt.SvtBadChannel$SvtBadChannelCollection"/>
-            </classes>
-            <fields>
-                <field name="svt_channel_id" />
-            </fields>        
-        </table>
-       
-       <table key="test_run_svt_daq_map" name="test_run_svt_daq_map">
-            <classes>
-                <object class="org.hps.conditions.svt.TestRunSvtDaqMapping"/>
-                <collection class="org.hps.conditions.svt.TestRunSvtDaqMapping$TestRunSvtDaqMappingCollection"/>
-            </classes>
-            <fields>
-                <field name="fpga" />
-                <field name="hybrid" />
-                <field name="svt_half" />
-                <field name="layer" />
-                <field name="orientation" />
-            </fields>  
-        </table>   
-        
-        <table key="test_run_ecal_bad_channels" name="test_run_ecal_bad_channels">
-            <classes>
-                <object class="org.hps.conditions.ecal.EcalBadChannel"/>
-                <collection class="org.hps.conditions.ecal.EcalBadChannel$EcalBadChannelCollection"/>
-            </classes>
-            <fields>
-                <field name="ecal_channel_id" />
-            </fields>  
-        </table>
-        
-        <table key="test_run_ecal_gains" name="test_run_ecal_gains">
-            <classes>
-                <object class="org.hps.conditions.ecal.EcalGain"/>
-                <collection class="org.hps.conditions.ecal.EcalGain$EcalGainCollection"/>
-            </classes>
-            <fields>
-                <field name="ecal_channel_id" />
-                <field name="gain" />
-            </fields>  
-        </table>
-        
-        <table key="test_run_ecal_calibrations" name="test_run_ecal_calibrations">
-            <classes>
-                <object class="org.hps.conditions.ecal.EcalCalibration"/>
-                <collection class="org.hps.conditions.ecal.EcalCalibration$EcalCalibrationCollection"/>
-            </classes>
-            <fields>
-                <field name="ecal_channel_id" />
-                <field name="noise" />
-                <field name="pedestal" />
-            </fields>  
-        </table>
-        
-        <table key="test_run_ecal_channels" name="test_run_ecal_channels">
-            <classes>
-                <object class="org.hps.conditions.ecal.EcalChannel"/>
-                <collection class="org.hps.conditions.ecal.EcalChannel$EcalChannelCollection"/>
-            </classes>
-            <fields>
-                <field name="channel_id" />                
-                <field name="crate" />
-                <field name="slot" />
-                <field name="channel" />
-                <field name="x" />
-                <field name="y" />
-            </fields>  
-        </table>
-        
-        <table key="test_run_ecal_time_shifts" name="test_run_ecal_time_shifts">
-            <classes>
-                <object class="org.hps.conditions.ecal.EcalTimeShift"/>
-                <collection class="org.hps.conditions.ecal.EcalTimeShift$EcalTimeShiftCollection"/>
-            </classes>
-            <fields>
-                <field name="ecal_channel_id" />
-                <field name="time_shift" />
-            </fields>  
-        </table>
-        
-        <table key="beam_current" name="beam_current">
-            <classes>
-                <object class="org.hps.conditions.beam.BeamCurrent"/>
-                <collection class="org.hps.conditions.beam.BeamCurrent$BeamCurrentCollection"/>
-            </classes>
-            <fields>
-                <field name="beam_current" />
-            </fields>
-        </table>
-                       
-    </tables>
-
+<conditions_database>
+    <configuration>
+        <setupSvtDetector>true</setupSvtDetector>
+        <setupEcalDetector>true</setupEcalDetector>
+        <cacheAllConditions>false</cacheAllConditions>
+        <freezeAfterInitialize>false</freezeAfterInitialize>
+    </configuration>
 </conditions_database>

Modified: java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ConditionsDriverTest.java	Tue Dec 30 16:44:44 2014
@@ -37,7 +37,6 @@
         loop.add(new EventMarkerDriver());
         loop.add(new CheckDriver());
         loop.loop(-1);
-        
     }
     
     static class CheckDriver extends Driver {

Added: java/trunk/conditions/src/test/java/org/hps/conditions/database/ConverterRegistryTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/database/ConverterRegistryTest.java	(added)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/database/ConverterRegistryTest.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,12 @@
+package org.hps.conditions.database;
+
+import junit.framework.TestCase;
+
+public class ConverterRegistryTest extends TestCase {
+    
+    public void testConverterRegistry() {
+        ConverterRegistry converterRegistry = ConverterRegistry.create();
+        System.out.println(converterRegistry.toString());
+    }
+
+}

Added: java/trunk/conditions/src/test/java/org/hps/conditions/database/TableRegistryTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/database/TableRegistryTest.java	(added)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/database/TableRegistryTest.java	Tue Dec 30 16:44:44 2014
@@ -0,0 +1,11 @@
+package org.hps.conditions.database;
+
+import junit.framework.TestCase;
+
+public class TableRegistryTest extends TestCase {
+
+    public void testTableRegistry() {
+        TableRegistry registry = TableRegistry.create();
+        System.out.println(registry.toString());
+    }
+}

Copied: java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalDetectorSetupTest.java (from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/EcalDetectorSetupTest.java)
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/EcalDetectorSetupTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalDetectorSetupTest.java	Tue Dec 30 16:44:44 2014
@@ -1,4 +1,4 @@
-package org.hps.conditions;
+package org.hps.conditions.ecal;
 
 import java.util.List;
 

Modified: java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalLedTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalLedTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/ecal/EcalLedTest.java	Tue Dec 30 16:44:44 2014
@@ -17,31 +17,20 @@
           
 
     DatabaseConditionsManager conditionsManager;
-	  public void setUp() {
-	        conditionsManager = DatabaseConditionsManager.getInstance();
-	        try {
-	            conditionsManager.setDetector("HPS-Proposal2014-v7-2pt2", 2000);
-	        } catch (ConditionsNotFoundException e) {
-	            throw new RuntimeException(e);
-	        }
-	    }
+    public void setUp() {
+        conditionsManager = DatabaseConditionsManager.getInstance();
+        try {
+            conditionsManager.setDetector("HPS-Proposal2014-v7-2pt2", 2000);
+        } catch (ConditionsNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
 	
-    
-    
     public void testEcalLed() {
         DatabaseConditionsManager manager = DatabaseConditionsManager.getInstance();
         EcalLedCollection collection = manager.getConditionsData(EcalLedCollection.class, TableConstants.ECAL_LEDS);
-        for (EcalLed led : collection) {
-        	
+        for (EcalLed led : collection) {    	
         	System.out.println(led);
-            //System.out.println("ECAL LED info ...");
-            //System.out.println("ecal_channel_id: " + led.getEcalChannelId());
-            //System.out.println("crate: " + led.getCrateNumber());
-            //System.out.println("number: " + led.getLedNumber());
-            //System.out.println("time_delay: " + led.getTimeDelay());
-            //System.out.println("amplitude_low: " + led.getAmplitudeLow());
-            //System.out.println("amplitude_high: " + led.getAmplitudeHigh());
-            //System.out.println();
         }
     }
 }

Modified: java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDaqMappingTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDaqMappingTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDaqMappingTest.java	Tue Dec 30 16:44:44 2014
@@ -14,7 +14,7 @@
  */
 public class SvtDaqMappingTest extends TestCase {
 
-    // --- Constants ---//
+    // --- Constants ---// 
     // -----------------//
 
     // Total number of SVT sensors
@@ -30,7 +30,7 @@
         DatabaseConditionsManager conditionsManager = new DatabaseConditionsManager();
         conditionsManager.setDetector("HPS-Proposal2014-v7-2pt2", 0);
 
-        TableMetaData metaData = conditionsManager.findTableMetaData(SvtDaqMappingCollection.class).get(0);
+        TableMetaData metaData = conditionsManager.findTableMetaData(SvtDaqMappingCollection.class);
         SvtDaqMappingCollection daqMappingCollection = conditionsManager.getConditionsData(SvtDaqMappingCollection.class, metaData.getTableName());
 
         int totalSensors = 0;

Copied: java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java (from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/SvtDetectorSetupTest.java)
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/SvtDetectorSetupTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java	Tue Dec 30 16:44:44 2014
@@ -1,4 +1,4 @@
-package org.hps.conditions;
+package org.hps.conditions.svt;
 
 import java.util.List;
 

Modified: java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDaqMappingTest.java
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDaqMappingTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDaqMappingTest.java	Tue Dec 30 16:44:44 2014
@@ -37,7 +37,7 @@
         conditionsManager.setXmlConfig("/org/hps/conditions/config/conditions_database_testrun_2012.xml");
         conditionsManager.setDetector("HPS-TestRun-v5", 1351);
 
-        metaData = conditionsManager.findTableMetaData(TestRunSvtDaqMappingCollection.class).get(0);
+        metaData = conditionsManager.findTableMetaData(TestRunSvtDaqMappingCollection.class);
         TestRunSvtDaqMappingCollection daqMappingCollection = conditionsManager.getConditionsData(TestRunSvtDaqMappingCollection.class, metaData.getTableName());
 
         int totalSensors = 0;

Copied: java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java (from r1808, java/trunk/conditions/src/test/java/org/hps/conditions/TestRunSvtDetectorSetupTest.java)
 =============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/TestRunSvtDetectorSetupTest.java	(original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java	Tue Dec 30 16:44:44 2014
@@ -1,4 +1,4 @@
-package org.hps.conditions;
+package org.hps.conditions.svt;
 
 import java.util.List;