Author: [log in to unmask]
Date: Mon Apr 20 15:47:54 2015
New Revision: 2756
Log:
implement conditions object conversion
Added:
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/AbstractConditionsObjectConverter.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectUtilities.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/TableRegistry.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObject.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObjectConverter.java
java/branches/conditions-HPSJAVA-488/src/main/resources/org/hps/conditions/config/jeremym_dev_connection.prop
java/branches/conditions-HPSJAVA-488/src/test/java/org/hps/conditions/apinew/DummyConditionsObjectConverterTest.java
Modified:
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObject.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObjectCollection.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObject.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectCollection.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValues.java
java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValuesMap.java
Added: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/AbstractConditionsObjectConverter.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/AbstractConditionsObjectConverter.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/AbstractConditionsObjectConverter.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,178 @@
+package org.hps.conditions.apinew;
+
+import java.sql.SQLException;
+
+import org.hps.conditions.api.ConditionsObjectException;
+import org.hps.conditions.api.ConditionsRecord;
+import org.hps.conditions.api.ConditionsRecord.ConditionsRecordCollection;
+import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.database.MultipleCollectionsAction;
+import org.lcsim.conditions.ConditionsConverter;
+import org.lcsim.conditions.ConditionsManager;
+
+/**
+ * <p>
+ * Implementation of default conversion from database tables to a {@link ConditionsObject} class.
+ * <p>
+ * This class actually returns collections and not individual objects.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ * @param <T> The type of the returned data which should be a class extending {@link BaseConditionsObjectCollection}.
+ */
+public abstract class AbstractConditionsObjectConverter<T> implements ConditionsConverter<T> {
+
+ /**
+ * 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 BaseConditionsObjectCollection<?> createCollection(final DatabaseConditionsManager manager,
+ final ConditionsRecord conditionsRecord, final TableMetaData tableMetaData)
+ throws ConditionsObjectException {
+ BaseConditionsObjectCollection<?> collection;
+ try {
+ collection = tableMetaData.getCollectionClass().newInstance();
+ if (conditionsRecord != null) {
+ collection.setConnection(manager.getConnection());
+ collection.setTableMetaData(tableMetaData);
+ collection.setCollectionId(conditionsRecord.getCollectionId());
+ }
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new ConditionsObjectException("Error creating conditions object collection.", e);
+ }
+ return collection;
+ }
+
+ /**
+ * The action to take if multiple overlapping conditions sets are found. The default is using the most recently
+ * updated one.
+ */
+ private MultipleCollectionsAction multipleCollections = MultipleCollectionsAction.LAST_UPDATED;
+
+ /**
+ * Class constructor.
+ */
+ public AbstractConditionsObjectConverter() {
+ }
+
+ /**
+ * Get the conditions data based on the name, e.g. "ecal_channels". The table information is found using the type
+ * handled by the Converter.
+ *
+ * @param conditionsManager the current conditions manager
+ * @param name the name of the conditions set (maps to table name)
+ * @return the conditions data
+ */
+ @Override
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public T getData(final ConditionsManager conditionsManager, final String name) {
+
+ // Get the DatabaseConditionsManager which is required for using this converter.
+ final DatabaseConditionsManager databaseConditionsManager = (DatabaseConditionsManager) conditionsManager;
+
+ // Setup connection if necessary.
+ final boolean openedConnection = databaseConditionsManager.openConnection();
+
+ // Get the TableMetaData from the table name.
+ final TableMetaData tableMetaData = TableRegistry.getTableRegistry().findByTableName(name);
+
+ // Throw an exception if the table name does not map to a known type.
+ if (tableMetaData == null) {
+ throw new RuntimeException(new ConditionsObjectException("No table information found for name: " + name));
+ }
+
+ // Get the ConditionsRecordCollection with the run number assignments.
+ final ConditionsRecordCollection conditionsRecords = databaseConditionsManager.findConditionsRecords(name);
+
+ // The record with the collection information.
+ ConditionsRecord conditionsRecord = null;
+
+ // Now we need to determine which ConditionsRecord object to use.
+ if (conditionsRecords.size() == 0) {
+ // No conditions records were found for the key.
+ throw new RuntimeException("No conditions were found with key: " + name);
+ } else if (conditionsRecords.size() == 1) {
+ // Use the single conditions set that was found.
+ conditionsRecord = conditionsRecords.get(0);
+ } else if (conditionsRecords.size() > 1) {
+ if (this.multipleCollections.equals(MultipleCollectionsAction.LAST_UPDATED)) {
+ // Use the conditions set with the latest updated date.
+ conditionsRecord = conditionsRecords.sortedByUpdated().get(conditionsRecords.size() - 1);
+ } else if (this.multipleCollections.equals(MultipleCollectionsAction.LAST_CREATED)) {
+ // Use the conditions set with the latest created date.
+ conditionsRecord = conditionsRecords.sortedByCreated().get(conditionsRecords.size() - 1);
+ } else if (this.multipleCollections.equals(MultipleCollectionsAction.LATEST_RUN_START)) {
+ // Use the conditions set with the greatest run start value.
+ conditionsRecord = conditionsRecords.sortedByRunStart().get(conditionsRecords.size() - 1);
+ } else if (this.multipleCollections.equals(MultipleCollectionsAction.ERROR)) {
+ // The converter has been configured to throw an error.
+ throw new RuntimeException("Multiple ConditionsRecord object found for conditions key " + name);
+ }
+ }
+
+ // Create a collection of objects to return.
+ ConditionsObjectCollection collection = null;
+ try {
+ collection = createCollection(databaseConditionsManager, conditionsRecord, tableMetaData);
+ } catch (final ConditionsObjectException e) {
+ throw new RuntimeException(e);
+ }
+
+ DatabaseConditionsManager.getLogger().info("loading conditions set..." + '\n' + conditionsRecord);
+
+ // Select the objects into the collection by the collection ID.
+ try {
+ collection.select(conditionsRecord.getCollectionId());
+ } catch (ConditionsObjectException | SQLException e) {
+ throw new RuntimeException("Error creating conditions collection from table " + name
+ + " with collection ID " + conditionsRecord.getCollectionId(), e);
+ }
+
+ if (openedConnection) {
+ // Close connection if one was opened.
+ databaseConditionsManager.closeConnection();
+ }
+
+ return (T) collection;
+ }
+
+ /**
+ * Get the multiple collections action.
+ *
+ * @return the multiple collections action
+ */
+ public final MultipleCollectionsAction getMultipleCollectionsAction() {
+ return this.multipleCollections;
+ }
+
+ /**
+ * Get the specific type converted by this class.
+ *
+ * @return the class that this converter handles
+ */
+ @Override
+ public abstract Class<T> getType();
+
+ /**
+ * Set the action that the converter will use to disambiguate when multiple conditions sets are found.
+ *
+ * @param multipleCollections the multiple collections action
+ */
+ final void setMultipleCollectionsAction(final MultipleCollectionsAction multipleCollections) {
+ this.multipleCollections = multipleCollections;
+ }
+
+ /**
+ * Convert object to string.
+ *
+ * @return the object converted to string
+ */
+ @Override
+ public String toString() {
+ return "ConditionsObjectConverter: type = " + this.getType() + ", multipleCollectionsAction = "
+ + this.getMultipleCollectionsAction().toString();
+ }
+}
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObject.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObject.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObject.java Mon Apr 20 15:47:54 2015
@@ -8,6 +8,7 @@
import java.util.Date;
import org.hps.conditions.api.ConditionsObjectException;
+import org.hps.conditions.database.Field;
/**
* This is a basic ORM class for performing CRUD (create, read, update, delete) operations on objects in the conditions
@@ -50,7 +51,7 @@
/**
* The field values.
*/
- private final FieldValues fields;
+ private FieldValues fieldValues;
/**
* The row ID of the object in its table. This will be -1 for new objects that are not in the database.
@@ -68,7 +69,7 @@
private TableMetaData tableMetaData;
protected BaseConditionsObject() {
- this.fields = new FieldValuesMap();
+ this.fieldValues = new FieldValuesMap();
}
/**
@@ -83,7 +84,7 @@
public BaseConditionsObject(final Connection connection, final TableMetaData tableMetaData) {
this.connection = connection;
this.tableMetaData = tableMetaData;
- this.fields = new FieldValuesMap(tableMetaData);
+ this.fieldValues = new FieldValuesMap(tableMetaData);
}
/**
@@ -98,7 +99,7 @@
public BaseConditionsObject(final Connection connection, final TableMetaData tableMetaData, final FieldValues fields) {
this.connection = connection;
this.tableMetaData = tableMetaData;
- this.fields = fields;
+ this.fieldValues = fields;
}
/**
@@ -117,7 +118,7 @@
throws ConditionsObjectException, SQLException {
this.connection = connection;
this.tableMetaData = tableMetaData;
- this.fields = new FieldValuesMap(tableMetaData);
+ this.fieldValues = new FieldValuesMap(tableMetaData);
final boolean selected = select(rowId);
if (!selected) {
throw new ConditionsObjectException("Failed to select data into object using row ID " + rowId);
@@ -147,8 +148,9 @@
}
@Override
- public final int getCollectionId() {
- if (this.fields.isNonNull(COLLECTION_ID_FIELD)) {
+ @Field(names = {"collection_id"})
+ public final Integer getCollectionId() {
+ if (this.fieldValues.isNonNull(COLLECTION_ID_FIELD)) {
return getValue(Integer.class, COLLECTION_ID_FIELD);
} else {
return UNSET_COLLECTION_ID;
@@ -157,7 +159,7 @@
@Override
public FieldValues getFieldValues() {
- return this.fields;
+ return this.fieldValues;
}
@Override
@@ -172,7 +174,7 @@
@Override
public final <T> T getValue(final Class<T> type, final String name) {
- return type.cast(this.fields.getValue(type, name));
+ return type.cast(this.fieldValues.getValue(type, name));
}
@Override
@@ -182,12 +184,12 @@
}
final StringBuffer sb = new StringBuffer();
sb.append("INSERT INTO " + this.tableMetaData.getTableName() + " (");
- for (final String fieldName : this.fields.getFieldNames()) {
+ for (final String fieldName : this.fieldValues.getFieldNames()) {
sb.append(fieldName + ", ");
}
sb.setLength(sb.length() - 2);
sb.append(") VALUES (");
- for (final Object value : this.fields.getValues()) {
+ for (final Object value : this.fieldValues.getValues()) {
if (value instanceof Date) {
sb.append("STR_TO_DATE( '" + DATE_FORMAT.format((Date) value) + "', '%Y-%m-%d %H:%i:%S' ), ");
} else {
@@ -291,6 +293,11 @@
}
@Override
+ public void setFieldValues(final FieldValues fieldValues) {
+ this.fieldValues = fieldValues;
+ }
+
+ @Override
public void setId(final int id) {
this.id = id;
}
@@ -302,7 +309,7 @@
@Override
public final void setValue(final String name, final Object value) {
- this.fields.setValue(name, value);
+ this.fieldValues.setValue(name, value);
this.isDirty = true;
}
@@ -319,9 +326,9 @@
}
final StringBuffer sb = new StringBuffer();
sb.append("UPDATE " + this.tableMetaData.getTableName() + " SET ");
- for (final String fieldName : this.fields.getFieldNames()) {
+ for (final String fieldName : this.fieldValues.getFieldNames()) {
sb.append(fieldName + "=");
- final Object value = this.fields.getValue(fieldName);
+ final Object value = this.fieldValues.getValue(fieldName);
if (value instanceof Date) {
// FIXME: Is there a more generic way to handle this?
sb.append("STR_TO_DATE( '" + DATE_FORMAT.format((Date) value) + "', '%Y-%m-%d %H:%i:%S' ), ");
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObjectCollection.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObjectCollection.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/BaseConditionsObjectCollection.java Mon Apr 20 15:47:54 2015
@@ -6,6 +6,7 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -18,7 +19,7 @@
public class BaseConditionsObjectCollection<ObjectType extends ConditionsObject> implements
ConditionsObjectCollection<ObjectType> {
- private int collectionId;
+ private int collectionId = BaseConditionsObject.UNSET_COLLECTION_ID;
private Connection connection;
private final Set<ObjectType> objects = new LinkedHashSet<ObjectType>();
private TableMetaData tableMetaData;
@@ -98,7 +99,7 @@
@Override
public Collection<ObjectType> getObjects() {
- return this.objects;
+ return Collections.unmodifiableCollection(this.objects);
}
@Override
@@ -137,16 +138,13 @@
this.connection.setAutoCommit(false);
insertObjects = this.connection.prepareStatement(updateStatement, Statement.RETURN_GENERATED_KEYS);
for (final ObjectType object : this.getObjects()) {
+ object.setCollectionId(this.collectionId);
for (int fieldIndex = 0; fieldIndex < this.getTableMetaData().getFieldNames().length; fieldIndex++) {
final String fieldName = this.getTableMetaData().getFieldNames()[fieldIndex];
- object.getValue(getTableMetaData().getFieldType(fieldName), fieldName);
- // System.out.println(fieldName + "=" + value);
- if (fieldName.equals(BaseConditionsObject.COLLECTION_ID_FIELD)) {
- insertObjects.setObject(fieldIndex + 1, getCollectionId());
- } else {
- insertObjects.setObject(fieldIndex + 1,
- object.getValue(getTableMetaData().getFieldType(fieldName), fieldName));
- }
+ final Object value = object.getValue(getTableMetaData().getFieldType(fieldName), fieldName);
+ System.out.println(fieldName + "=" + value);
+ insertObjects.setObject(fieldIndex + 1,
+ object.getValue(getTableMetaData().getFieldType(fieldName), fieldName));
}
insertObjects.executeUpdate();
this.connection.commit();
@@ -225,6 +223,20 @@
}
@Override
+ public void setCollectionId(final int collectionId) {
+ this.collectionId = collectionId;
+ }
+
+ public void setConnection(final Connection connection) {
+ this.connection = connection;
+ }
+
+ @Override
+ public void setTableMetaData(final TableMetaData tableMetaData) {
+ this.tableMetaData = tableMetaData;
+ }
+
+ @Override
public int size() {
return this.objects.size();
}
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObject.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObject.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObject.java Mon Apr 20 15:47:54 2015
@@ -17,7 +17,7 @@
/**
* @return
*/
- int getCollectionId();
+ Integer getCollectionId();
FieldValues getFieldValues();
@@ -68,6 +68,8 @@
*/
void setConnection(Connection connection);
+ void setFieldValues(FieldValues fieldValues);
+
void setId(int id);
void setTableMetaData(TableMetaData tableMetaData);
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectCollection.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectCollection.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectCollection.java Mon Apr 20 15:47:54 2015
@@ -25,6 +25,10 @@
void select(final int collectionId) throws ConditionsObjectException, SQLException;
+ void setCollectionId(int collectionId);
+
+ void setTableMetaData(TableMetaData tableMetaData);
+
int size();
void updateAll() throws ConditionsObjectException, SQLException;
Added: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectUtilities.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectUtilities.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/ConditionsObjectUtilities.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,115 @@
+package org.hps.conditions.apinew;
+
+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 <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ */
+public final class ConditionsObjectUtilities {
+
+ /**
+ * Find all available classes that extend ConditionsObject.
+ *
+ * @return The set of all available classes that extend ConditionsObject.
+ */
+ public static Set<Class<? extends ConditionsObject>> findConditionsObjectTypes() {
+ final Reflections reflections = new Reflections("org.hps.conditions");
+ final Set<Class<? extends ConditionsObject>> objectTypes = new HashSet<Class<? extends ConditionsObject>>();
+ for (final 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;
+ }
+
+ /**
+ * 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 BaseConditionsObjectCollection<? extends ConditionsObject>> getCollectionType(
+ final Class<? extends ConditionsObject> type) {
+ final String collectionClassName = type.getCanonicalName() + "$" + type.getSimpleName() + "Collection";
+ Class<?> rawCollectionClass;
+ try {
+ rawCollectionClass = Class.forName(collectionClassName);
+ } catch (final ClassNotFoundException e) {
+ throw new RuntimeException("The type does not define a nested collection class.", e);
+ }
+ if (!BaseConditionsObjectCollection.class.isAssignableFrom(rawCollectionClass)) {
+ throw new RuntimeException("The class " + rawCollectionClass.getSimpleName()
+ + " does not extend ConditionsObjectCollection.");
+ }
+ return (Class<? extends BaseConditionsObjectCollection<? extends ConditionsObject>>) rawCollectionClass;
+ }
+
+ /**
+ * 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(final Class<? extends ConditionsObject> type) {
+ final Set<String> fieldNames = new HashSet<String>();
+ for (final Method method : type.getMethods()) {
+ System.out.println(method.getName());
+ if (!method.getReturnType().equals(Void.TYPE)) {
+ for (final 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.");
+ }
+ final Field field = (Field) annotation;
+ for (final String fieldName : field.names()) {
+ if (fieldName != null && !"".equals(fieldName)) {
+ System.out.println(" " + fieldName);
+ fieldNames.add(fieldName);
+ }
+ }
+ }
+ }
+ }
+ }
+ return fieldNames;
+ }
+
+ /**
+ * Get the list of table names for the class.
+ *
+ * @param type the class
+ * @return the list of table names
+ */
+ public static String[] getTableNames(final Class<? extends ConditionsObject> type) {
+ final Table tableAnnotation = type.getAnnotation(Table.class);
+ if (tableAnnotation != null) {
+ return tableAnnotation.names();
+ } else {
+ return new String[] {};
+ }
+ }
+
+ /**
+ * Do not allow class to be instantiated.
+ */
+ private ConditionsObjectUtilities() {
+ }
+}
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValues.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValues.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValues.java Mon Apr 20 15:47:54 2015
@@ -20,6 +20,8 @@
boolean isNonNull(String name);
+ boolean isNull(String name);
+
void setValue(String name, Object value);
int size();
Modified: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValuesMap.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValuesMap.java (original)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/FieldValuesMap.java Mon Apr 20 15:47:54 2015
@@ -52,6 +52,11 @@
}
@Override
+ public boolean isNull(final String name) {
+ return this.data.get(name) == null;
+ }
+
+ @Override
public void setValue(final String name, final Object value) {
this.data.put(name, value);
}
Added: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/TableRegistry.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/TableRegistry.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/apinew/TableRegistry.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,172 @@
+package org.hps.conditions.apinew;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.hps.conditions.database.Field;
+
+/**
+ * This is a registry providing a map between tables and their meta-data.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ */
+@SuppressWarnings("serial")
+public final class TableRegistry extends HashMap<String, TableMetaData> {
+
+ /**
+ * Maps collection types to table meta data.
+ */
+ static class CollectionTypeMap extends
+ HashMap<Class<? extends BaseConditionsObjectCollection<?>>, List<TableMetaData>> {
+
+ /**
+ * Add a mapping between a collection type and table meta data.
+ *
+ * @param type the collection type
+ * @param metaData the table meta data
+ */
+ void add(final Class<? extends BaseConditionsObjectCollection<?>> type, final TableMetaData metaData) {
+ if (this.get(type) == null) {
+ this.put(type, new ArrayList<TableMetaData>());
+ }
+ this.get(type).add(metaData);
+ }
+ }
+
+ /**
+ * Maps types to table meta data.
+ */
+ static class ObjectTypeMap extends HashMap<Class<? extends ConditionsObject>, List<TableMetaData>> {
+ /**
+ * Add a connection between an object type and table meta data.
+ *
+ * @param type the object type
+ * @param metaData the table meta data
+ */
+ void add(final Class<? extends ConditionsObject> type, final TableMetaData metaData) {
+ if (this.get(type) == null) {
+ this.put(type, new ArrayList<TableMetaData>());
+ }
+ this.get(type).add(metaData);
+ }
+ }
+
+ static TableRegistry instance = null;
+
+ /**
+ * Create a new table meta data registry.
+ *
+ * @return the meta data registry
+ */
+ static TableRegistry create() {
+ final TableRegistry registry = new TableRegistry();
+ for (final Class<? extends ConditionsObject> objectType : ConditionsObjectUtilities.findConditionsObjectTypes()) {
+
+ // Get the collection type.
+ final Class<? extends BaseConditionsObjectCollection<?>> collectionType = ConditionsObjectUtilities
+ .getCollectionType(objectType);
+
+ // Get the list of field names.
+ final Set<String> fieldNames = ConditionsObjectUtilities.getFieldNames(objectType);
+
+ // Create map of fields to their types.
+ final Map<String, Class<?>> fieldTypes = new HashMap<String, Class<?>>();
+ for (final Method method : objectType.getMethods()) {
+ if (!method.getReturnType().equals(Void.TYPE)) {
+ for (final Annotation annotation : method.getAnnotations()) {
+ if (annotation.annotationType().equals(Field.class)) {
+ final Field field = (Field) annotation;
+ for (final String fieldName : field.names()) {
+ fieldTypes.put(fieldName, method.getReturnType());
+ }
+ }
+ }
+ }
+ }
+
+ for (final String name : ConditionsObjectUtilities.getTableNames(objectType)) {
+ // Create a meta data mapping for each table name in the class description.
+ final TableMetaData data = new TableMetaData(name, name, objectType, collectionType, fieldNames,
+ fieldTypes);
+ registry.put(name, data);
+ registry.objectTypeMap.add(objectType, data);
+ registry.collectionTypeMap.add(collectionType, data);
+ }
+ }
+ return registry;
+ }
+
+ public synchronized static TableRegistry getTableRegistry() {
+ if (instance == null) {
+ instance = TableRegistry.create();
+ }
+ return instance;
+ }
+
+ /**
+ * Map between collection types and meta data.
+ */
+ private final CollectionTypeMap collectionTypeMap = new CollectionTypeMap();
+
+ /**
+ * Map between object types and meta data.
+ */
+ private final ObjectTypeMap objectTypeMap = new ObjectTypeMap();
+
+ /**
+ * Class should not be directly instantiated.
+ * <p>
+ * Use the {@link #create()} method instead.
+ */
+ private TableRegistry() {
+ }
+
+ /**
+ * Find meta data by collection type.
+ *
+ * @param collectionType the collection type
+ * @return the meta data or <code>null</code> if none exists.
+ */
+ List<TableMetaData> findByCollectionType(final Class<?> collectionType) {
+ return this.collectionTypeMap.get(collectionType);
+ }
+
+ /**
+ * Find meta data by object type.
+ *
+ * @param objectType the object type
+ * @return the meta data or <code>null</code> if none exists.
+ */
+ List<TableMetaData> findByObjectType(final Class<? extends ConditionsObject> objectType) {
+ return this.objectTypeMap.get(objectType);
+ }
+
+ /**
+ * Find meta data by table name.
+ *
+ * @param name the table name
+ * @return the meta data or <code>null</code> if none exists
+ */
+ TableMetaData findByTableName(final String name) {
+ return this.get(name);
+ }
+
+ /**
+ * Convert this object to a string.
+ *
+ * @return this object converted to a string
+ */
+ @Override
+ public String toString() {
+ final StringBuffer buff = new StringBuffer();
+ for (final TableMetaData tableMetaData : this.values()) {
+ buff.append(tableMetaData.toString());
+ }
+ return buff.toString();
+ }
+}
Added: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObject.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObject.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObject.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,40 @@
+package org.hps.conditions.dummy;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.hps.conditions.api.ConditionsObjectException;
+import org.hps.conditions.apinew.BaseConditionsObject;
+import org.hps.conditions.apinew.BaseConditionsObjectCollection;
+import org.hps.conditions.apinew.TableMetaData;
+import org.hps.conditions.database.Field;
+import org.hps.conditions.database.Table;
+
+/**
+ * A dummy conditions object type.
+ */
+@Table(names = {"dummy"})
+public final class DummyConditionsObject extends BaseConditionsObject {
+
+ public static class DummyConditionsObjectCollection extends BaseConditionsObjectCollection<DummyConditionsObject> {
+ public DummyConditionsObjectCollection() {
+ }
+
+ DummyConditionsObjectCollection(final Connection connection, final TableMetaData tableMetaData)
+ throws SQLException, ConditionsObjectException {
+ super(connection, tableMetaData, -1);
+ }
+ }
+
+ public DummyConditionsObject() {
+ }
+
+ public DummyConditionsObject(final Connection connection, final TableMetaData tableMetaData) {
+ super(connection, tableMetaData);
+ }
+
+ @Field(names = {"dummy"})
+ public Double getDummy() {
+ return this.getValue(Double.class, "dummy");
+ }
+}
Added: java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObjectConverter.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObjectConverter.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/java/org/hps/conditions/dummy/DummyConditionsObjectConverter.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,12 @@
+package org.hps.conditions.dummy;
+
+import org.hps.conditions.apinew.AbstractConditionsObjectConverter;
+import org.hps.conditions.dummy.DummyConditionsObject.DummyConditionsObjectCollection;
+
+public final class DummyConditionsObjectConverter extends
+ AbstractConditionsObjectConverter<DummyConditionsObjectCollection> {
+ @Override
+ public Class<DummyConditionsObjectCollection> getType() {
+ return DummyConditionsObjectCollection.class;
+ }
+}
Added: java/branches/conditions-HPSJAVA-488/src/main/resources/org/hps/conditions/config/jeremym_dev_connection.prop
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/main/resources/org/hps/conditions/config/jeremym_dev_connection.prop (added)
+++ java/branches/conditions-HPSJAVA-488/src/main/resources/org/hps/conditions/config/jeremym_dev_connection.prop Mon Apr 20 15:47:54 2015
@@ -0,0 +1,4 @@
+hostname = localhost
+user = root
+password = derp
+database = hps_conditions_dev
Added: java/branches/conditions-HPSJAVA-488/src/test/java/org/hps/conditions/apinew/DummyConditionsObjectConverterTest.java
=============================================================================
--- java/branches/conditions-HPSJAVA-488/src/test/java/org/hps/conditions/apinew/DummyConditionsObjectConverterTest.java (added)
+++ java/branches/conditions-HPSJAVA-488/src/test/java/org/hps/conditions/apinew/DummyConditionsObjectConverterTest.java Mon Apr 20 15:47:54 2015
@@ -0,0 +1,47 @@
+package org.hps.conditions.apinew;
+
+import junit.framework.TestCase;
+
+import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.dummy.DummyConditionsObject;
+import org.hps.conditions.dummy.DummyConditionsObject.DummyConditionsObjectCollection;
+import org.hps.conditions.dummy.DummyConditionsObjectConverter;
+
+/**
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ */
+public class DummyConditionsObjectConverterTest extends TestCase {
+
+ public void testConditionsObjectConverter() throws Exception {
+
+ final DatabaseConditionsManager manager = DatabaseConditionsManager.getInstance();
+ manager.setConnectionResource("/org/hps/conditions/config/jeremym_dev_connection.prop");
+ manager.setXmlConfig("/org/hps/conditions/config/conditions_database_no_svt.xml");
+ manager.registerConditionsConverter(new DummyConditionsObjectConverter());
+ manager.setDetector("HPS-dummy-detector", 1);
+ manager.openConnection();
+
+ final TableMetaData tableMetaData = TableRegistry.getTableRegistry().findByTableName("dummy");
+
+ final DummyConditionsObjectCollection newCollection = new DummyConditionsObjectCollection();
+ newCollection.setTableMetaData(tableMetaData);
+ newCollection.setConnection(manager.getConnection());
+
+ final DummyConditionsObject object = new DummyConditionsObject(manager.getConnection(), tableMetaData);
+ object.setValue("dummy", 1.2345);
+ newCollection.add(object);
+
+ try {
+ newCollection.insertAll(1002);
+
+ final DummyConditionsObjectCollection readCollection = manager.getCachedConditions(
+ DummyConditionsObjectCollection.class, "dummy").getCachedData();
+
+ System.out.println("got dummy collection " + readCollection.getCollectionId() + " with "
+ + readCollection.size() + " objects");
+ } finally {
+ System.out.println("deleting collection " + newCollection.getCollectionId());
+ newCollection.deleteAll();
+ }
+ }
+}
|