Author: [log in to unmask] Date: Fri Jun 19 14:10:26 2015 New Revision: 3169 Log: Add missing documentation. Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractConditionsObjectConverter.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractIdentifier.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObject.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObjectCollection.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObject.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectCollection.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsSeries.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObject.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObjectException.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValues.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValuesMap.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableMetaData.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableRegistry.java java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/package-info.java java/branches/HPSJAVA-488/conditions/src/test/java/org/hps/conditions/dummy/DummyConditionsObjectTest.java Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/ConditionsDriver.java Fri Jun 19 14:10:26 2015 @@ -13,7 +13,7 @@ * be included in a steering file. * <p> * This is an example of using the Driver in an XML steering file: - * + * * <pre> * {@code * <driver name="ConditionsDriver" type="org.hps.conditions.ConditionsDriver"> @@ -40,19 +40,19 @@ /** The name of the detector model. */ private String detectorName; + /** + * True to freeze the conditions system after activation (requires valid detector name and run number). + */ + private boolean freeze; + + /** The user run number. */ + private int runNumber = 0; + /** The conditions system tag. */ private String tag; /** The XML config resource. */ private String xmlConfigResource; - - /** The user run number. */ - private int runNumber = 0; - - /** - * True to freeze the conditions system after activation (requires valid detector name and run number). - */ - private boolean freeze; /** * Default constructor. @@ -61,8 +61,41 @@ } /** + * Setup the conditions system based on the Driver parameters. + * + * @throws RuntimeException if there is a problem setting up the conditions system + */ + public final void initialize() { + + final DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance(); + + if (this.xmlConfigResource != null) { + // Set a custom XML configuration resource. + conditionsManager.setXmlConfig(this.xmlConfigResource); + } + + if (this.tag != null) { + // Set a tag for filtering ConditionsRecord objects. + conditionsManager.setTag(this.tag); + } + if (this.detectorName != null) { + // The manager can only be initialized here if there is a user supplied detector name. + try { + // Initialize the conditions manager. + conditionsManager.setDetector(this.detectorName, this.runNumber); + if (this.freeze) { + // User configured to freeze conditions for the job. + conditionsManager.freeze(); + } + } catch (final ConditionsNotFoundException e) { + throw new RuntimeException("Error initializing conditions from ConditionsDriver.", e); + } + } + } + + /** * Set the name of the detector to use. - * + * * @param detectorName the name of the detector */ public final void setDetectorName(final String detectorName) { @@ -74,7 +107,7 @@ * 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 <code>true</code> to freeze the conditions system after it is setup */ public final void setFreeze(final boolean freeze) { @@ -86,7 +119,7 @@ * that differ from this one, most likely the Driver should be configured to be frozen after setup using * {@link #setFreeze(boolean)}. 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 final void setRunNumber(final int runNumber) { @@ -95,7 +128,7 @@ /** * Set a tag used to filter ConditionsRecords. - * + * * @param tag the tag value e.g. "pass0" */ public final void setTag(final String tag) { @@ -104,43 +137,10 @@ /** * Set an XML configuration resource. - * + * * @param xmlConfigResource the XML configuration resource */ public final void setXmlConfigResource(final 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 final void initialize() { - - final DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance(); - - if (xmlConfigResource != null) { - // Set a custom XML configuration resource. - conditionsManager.setXmlConfig(xmlConfigResource); - } - - if (tag != null) { - // Set a tag for filtering ConditionsRecord objects. - conditionsManager.setTag(tag); - } - if (detectorName != null) { - // The manager can only be initialized here if there is a user supplied detector name. - try { - // Initialize the conditions manager. - conditionsManager.setDetector(detectorName, runNumber); - if (this.freeze) { - // User configured to freeze conditions for the job. - conditionsManager.freeze(); - } - } catch (ConditionsNotFoundException e) { - throw new RuntimeException("Error initializing conditions from ConditionsDriver.", e); - } - } - } } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractConditionsObjectConverter.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractConditionsObjectConverter.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractConditionsObjectConverter.java Fri Jun 19 14:10:26 2015 @@ -21,12 +21,13 @@ /** * Create a conditions object collection. * + * @param manager the conditions manager * @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 */ - private static final ConditionsObjectCollection<?> createCollection(final DatabaseConditionsManager manager, + private static ConditionsObjectCollection<?> createCollection(final DatabaseConditionsManager manager, final ConditionsRecord conditionsRecord, final TableMetaData tableMetaData) throws ConditionsObjectException { ConditionsObjectCollection<?> collection; Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractIdentifier.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractIdentifier.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/AbstractIdentifier.java Fri Jun 19 14:10:26 2015 @@ -3,7 +3,7 @@ /** * This class is a simplistic representation of a packaged identifier for use in the conditions system. * - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC */ public abstract class AbstractIdentifier { Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObject.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObject.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObject.java Fri Jun 19 14:10:26 2015 @@ -14,7 +14,7 @@ * This is a basic ORM class for performing CRUD (create, read, update, delete) operations on objects in the conditions * system. Each object is mapped to a single row in a database table. * - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC */ public class BaseConditionsObject implements ConditionsObject { @@ -26,7 +26,7 @@ /** * Date formatting for insert statement. */ - static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss"); + static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss"); /** * Value that indicates collection ID is not set (no collection assigned). @@ -40,7 +40,7 @@ /** * Perform the default to string operation on a conditions object. - * + * * @param object the conditions object * @return the object converted to a string */ @@ -67,14 +67,14 @@ private FieldValues fieldValues; /** + * Flag to indicate that the object is locally changed and a database update has not been executed. + */ + private boolean isDirty; + + /** * The row ID of the object in its table. This will be -1 for new objects that are not in the database. */ private int rowId = UNSET_ROW_ID; - - /** - * Flag to indicate that the object is locally changed and a database update has not been executed. - */ - private boolean isDirty; /** * The information about the associated table such as the table and column names. @@ -91,8 +91,8 @@ /** * Public class constructor. * <p> - * This should be used when creating new objects without a list of field values. A new <code>FieldValues</code> - * object will be automatically created from the table information. + * This should be used when creating new objects without a list of field values. A new {@link FieldValues} object + * will be automatically created from the table information. * * @param connection the database connection * @param tableMetaData the table meta data @@ -104,7 +104,7 @@ } /** - * Full qualified class constructor. + * Fully qualified class constructor. * <p> * This should be used when creating new objects from a list of field values. * @@ -123,22 +123,21 @@ /** * Delete the object from the database using its row ID. - * + * * @throws DatabaseObjectException if object is not in the database * @throws SQLException if there is an error performing the delete operation */ @Override public final void delete() throws DatabaseObjectException, SQLException { - if (isNew()) { + if (this.isNew()) { throw new DatabaseObjectException("Object is not in the database.", this); } - if (connection.getAutoCommit() == false) { - connection.setAutoCommit(true); - } + this.connection.setAutoCommit(true); PreparedStatement statement = null; try { - statement = this.connection.prepareStatement("DELETE FROM " + this.tableMetaData.getTableName() + " WHERE id = ?"); - statement.setInt(1, + this.getRowId()); + statement = this.connection.prepareStatement("DELETE FROM " + this.tableMetaData.getTableName() + + " WHERE id = ?"); + statement.setInt(1, +this.getRowId()); statement.executeUpdate(); this.rowId = UNSET_ROW_ID; } finally { @@ -150,22 +149,45 @@ /** * Get the collection ID of the object. - * + * * @return the collection ID of the object */ @Override @Field(names = {"collection_id"}) public final Integer getCollectionId() { if (this.fieldValues.isNonNull(COLLECTION_ID_FIELD)) { - return getFieldValue(Integer.class, COLLECTION_ID_FIELD); + return this.getFieldValue(Integer.class, COLLECTION_ID_FIELD); } else { return UNSET_COLLECTION_ID; } } /** + * Get a field value by name. + * + * @param type the return type + * @param name the name of the field + */ + @Override + public final <T> T getFieldValue(final Class<T> type, final String name) { + return type.cast(this.fieldValues.getValue(type, name)); + } + + /** + * Get a field value. + * + * @param name the field name + * @param T the field value + * @param <T> the implicit return return + */ + @Override + public <T> T getFieldValue(final String name) { + return (T) this.fieldValues.getValue(name); + } + + /** * Get the field values. - * + * * @return the field values */ @Override @@ -175,7 +197,7 @@ /** * Get the row ID. - * + * * @return the row ID */ @Override @@ -185,7 +207,7 @@ /** * Get the table meta data for the object. - * + * * @return the table meta data or <code>null</code> if not set */ @Override @@ -194,26 +216,24 @@ } /** - * Get a field value by name. - * - * @param type the return type - * @param name the name of the field - */ - @Override - public final <T> T getFieldValue(final Class<T> type, final String name) { - return type.cast(this.fieldValues.getValue(type, name)); - } - - /** - * - */ - @Override - // FIXME: Rewrite to use a PreparedStatement. + * Return <code>true</code> if collection ID is valid. + * + * @param <code>true</code> if collection ID is valid + */ + @Override + public boolean hasValidCollectionId() { + return this.getCollectionId() != UNSET_COLLECTION_ID; + } + + /** + * Insert the object into the conditions database. + */ + @Override public final void insert() throws DatabaseObjectException, SQLException { if (!this.isNew()) { throw new DatabaseObjectException("Cannot insert existing record with row ID: " + this.getRowId(), this); } - if (!this.hasValidCollection()) { + if (!this.hasValidCollectionId()) { throw new DatabaseObjectException("Cannot insert object without a valid collection ID.", this); } final StringBuffer sb = new StringBuffer(); @@ -225,7 +245,7 @@ sb.append(") VALUES ("); 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' ), "); + sb.append("STR_TO_DATE( '" + DEFAULT_DATE_FORMAT.format((Date) value) + "', '%Y-%m-%d %H:%i:%S' ), "); } else { sb.append("'" + value + "', "); } @@ -256,7 +276,9 @@ } /** - * + * Return <code>true</code> if object is dirty and needs a database update. + * + * @return <code>true</code> if object is dirty */ @Override public final boolean isDirty() { @@ -264,15 +286,22 @@ } /** - * + * Return <code>true</code> if object is not in the database. + * <p> + * This returns <code>true</code> if the object has a valid row ID. + * + * @return <code>true</code> if object is not in the database */ @Override public final boolean isNew() { - return getRowId() == UNSET_ROW_ID; - } - - /** - * + return this.getRowId() == UNSET_ROW_ID; + } + + /** + * Select a conditions object by its row ID. + * + * @param id the row ID + * @return <code>true</code> is selection was performed */ @Override public final boolean select(final int id) throws DatabaseObjectException, SQLException { @@ -314,20 +343,18 @@ } /** - * + * Set the collection ID of the object. + * + * @param collectionId the collection ID of the object */ void setCollectionId(final int collectionId) throws ConditionsObjectException { - //if (this.getCollectionId() != UNSET_COLLECTION_ID) { - // throw new ConditionsObjectException("The collection ID is already set on this object."); - //} - //if (collectionId <= UNSET_COLLECTION_ID) { - // throw new ConditionsObjectException("Invalid collection ID value: " + collectionId); - //} this.setFieldValue(COLLECTION_ID_FIELD, collectionId); } /** - * + * Set the JDBC database connection of the object. + * + * @param connection the database connection of the object */ @Override public final void setConnection(final Connection connection) { @@ -335,7 +362,23 @@ } /** - * + * Set a field value. + * <p> + * Calling this method will flag the object as "dirty" meaning it needs to be updated in the database. + * + * @param name the name of the field + * @param value the new value of the field + */ + @Override + public final void setFieldValue(final String name, final Object value) { + this.fieldValues.setValue(name, value); + this.isDirty = true; + } + + /** + * Set the field values of the object. + * + * @param fieldValues the field values of the object */ @Override public void setFieldValues(final FieldValues fieldValues) { @@ -344,7 +387,20 @@ } /** - * + * Set the row ID of the object. + * + * @param rowId the new row ID + */ + void setRowId(final int rowId) { + this.rowId = rowId; + } + + /** + * Set the table meta data of the object. + * <p> + * This sets which table is associated with the object for database operations. + * + * @param tableMetaData the table meta data */ @Override public final void setTableMetaData(final TableMetaData tableMetaData) { @@ -352,16 +408,9 @@ } /** - * - */ - @Override - public final void setFieldValue(final String name, final Object value) { - this.fieldValues.setValue(name, value); - this.isDirty = true; - } - - /** - * + * Convert this object to a string. + * + * @return this object converted to a string */ @Override public String toString() { @@ -369,13 +418,15 @@ } /** - * + * Perform an update operation to insert this object's data in the database. + * + * @return <code>true</code> if an update occurred */ @Override public final boolean update() throws DatabaseObjectException, SQLException { int rowsUpdated = 0; - if (isDirty()) { - if (isNew()) { + if (this.isDirty()) { + if (this.isNew()) { throw new DatabaseObjectException("Cannot update a new object.", this); } final StringBuffer sb = new StringBuffer(); @@ -384,8 +435,8 @@ sb.append(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' ), "); + sb.append("STR_TO_DATE( '" + DEFAULT_DATE_FORMAT.format((Date) value) + + "', '%Y-%m-%d %H:%i:%S' ), "); } else { sb.append("'" + value + "', "); } @@ -408,24 +459,4 @@ } return rowsUpdated != 0; } - - /** - * - */ - @Override - public <T> T getFieldValue(final String name) { - return (T) this.fieldValues.getValue(name); - } - - /** - * - */ - @Override - public boolean hasValidCollection() { - return getCollectionId() != UNSET_COLLECTION_ID; - } - - void setRowId(final int rowId) { - this.rowId = rowId; - } } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObjectCollection.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObjectCollection.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/BaseConditionsObjectCollection.java Fri Jun 19 14:10:26 2015 @@ -14,46 +14,89 @@ import java.util.Set; /** + * Implementation of the {@link ConditionsObjectCollection} interface. * + * @param <ObjectType> the type of the object contained in this collection + * @author Jeremy McCormick, SLAC */ public class BaseConditionsObjectCollection<ObjectType extends ConditionsObject> implements ConditionsObjectCollection<ObjectType> { + /** + * The collection ID. + */ private int collectionId = BaseConditionsObject.UNSET_COLLECTION_ID; + + /** + * The database connection. + */ private Connection connection; + + /** + * Flag to indicate collection needs to be updated in the database. + */ + private boolean isDirty; + + /** + * The set of objects contained in the collection (no duplicate references allowed to the same object). + */ private final Set<ObjectType> objects = new LinkedHashSet<ObjectType>(); + + /** + * The collection's table meta data mapping it to the database. + */ private TableMetaData tableMetaData; - private boolean isDirty; - private Class<ObjectType> type; - + + /** + * No argument constructor; usable by sub-classes. + */ protected BaseConditionsObjectCollection() { } - public BaseConditionsObjectCollection(final Connection connection, final TableMetaData tableMetaData) - throws SQLException, DatabaseObjectException { + /** + * Constructor with connection and meta data without field values. + * + * @param connection the database connection + * @param tableMetaData the table meta data + * @throws SQLException if there + * @throws DatabaseObjectException + */ + public BaseConditionsObjectCollection(final Connection connection, final TableMetaData tableMetaData) { this.connection = connection; this.tableMetaData = tableMetaData; - this.type = (Class<ObjectType>) tableMetaData.getObjectClass(); - } - + } + + /** + * Constructor which selects data into the collection using a collection ID. + * + * @param connection the database connection + * @param tableMetaData the table meta data + * @param collectionId the collection ID + * @throws SQLException if there is an error executing SQL query + * @throws DatabaseObjectException if there is an error relating to the conditions object API + */ public BaseConditionsObjectCollection(final Connection connection, final TableMetaData tableMetaData, final int collectionId) throws SQLException, DatabaseObjectException { this.connection = connection; this.tableMetaData = tableMetaData; this.collectionId = collectionId; if (collectionId != -1) { - select(collectionId); - } - this.type = (Class<ObjectType>) tableMetaData.getObjectClass(); - } - + this.select(collectionId); + } + } + + /** + * Add an object to the collection. + * + * @param object the object to add to the collection + */ @Override public boolean add(final ObjectType object) throws ConditionsObjectException { if (object == null) { throw new IllegalArgumentException("The object argument is null."); } // Does this collection have a valid ID yet? - if (getCollectionId() != BaseConditionsObject.UNSET_COLLECTION_ID) { + if (this.getCollectionId() != BaseConditionsObject.UNSET_COLLECTION_ID) { // Does the object that is being added have a collection ID? if (object.getCollectionId() != BaseConditionsObject.UNSET_COLLECTION_ID) { // Does the object's collection ID not match? @@ -81,15 +124,39 @@ } /** - * @throws ConditionsObjectException - * @throws SQLException + * Add all objects from a collection. + * + * @param collection the collection with objects to add + */ + @Override + public void addAll(final ConditionsObjectCollection<ObjectType> collection) { + for (final ObjectType object : collection) { + this.objects.add(object); + } + } + + /** + * Return <code>true</code> if object is contained in this collection. + * + * @return <code>true</code> if object is contained in this collection + */ + @Override + public final boolean contains(final Object object) { + return this.objects.contains(object); + } + + /** + * Delete the objects in the collection from database. + * + * @throws ConditionsObjectException if there is an error deleting the object + * @throws SQLException if there was an error executing the query */ @Override public final void delete() throws DatabaseObjectException, SQLException { Statement statement = null; try { final String sql = "DELETE FROM `" + this.tableMetaData.getTableName() + "` WHERE collection_id = '" - + getCollectionId() + "'"; + + this.getCollectionId() + "'"; statement = this.connection.createStatement(); statement.executeUpdate(sql); } catch (final SQLException e) { @@ -101,6 +168,40 @@ } } + /** + * Return <code>true</code> if collection exists in the database. + * + * @return <code>true</code> if collection exists in the database + * @throws SQLException if there is a query error + */ + private boolean exists() throws SQLException { + PreparedStatement statement = null; + ResultSet resultSet = null; + boolean exists = false; + try { + statement = this.connection.prepareStatement("SELECT id FROM " + this.tableMetaData.getTableName() + + " where collection_id = ?"); + statement.setInt(1, this.collectionId); + resultSet = statement.executeQuery(); + exists = resultSet.next(); + } finally { + if (statement != null) { + statement.close(); + } + if (resultSet != null) { + resultSet.close(); + } + } + return exists; + } + + /** + * Get the object at the index. + * + * @param index the object index + * @return the object at the index + * @throws IndexOutOfBoundsException if the index is invalid + */ @Override public final ObjectType get(final int index) { if (index + 1 > this.size() || index < 0) { @@ -116,93 +217,14 @@ return object; } + /** + * Get the collection ID. + * + * @return the collection ID + */ @Override public final int getCollectionId() { return this.collectionId; - } - - @Override - public final TableMetaData getTableMetaData() { - return this.tableMetaData; - } - - /** - * @param collectionId - * @throws ConditionsObjectException - * @throws SQLException - */ - @Override - public final void insert() throws DatabaseObjectException, SQLException { - - // Turn off auto-commit to perform a transaction. - this.connection.setAutoCommit(false); - - if (this.collectionId == BaseConditionsObject.UNSET_COLLECTION_ID) { - // Automatically get the next global collection ID from the conditions database. - this.collectionId = this.getNextCollectionId(); - } else { - // If the collection already exists in the database with this ID then it cannot be inserted. - if (checkExists()) { - throw new DatabaseObjectException("The collection " + this.collectionId - + " cannot be inserted because it already exists in the " + this.tableMetaData.getTableName() - + " table.", this); - } - } - - // Set collection ID on objects. - try { - setConditionsObjectCollectionIds(); - } catch (final ConditionsObjectException e) { - throw new DatabaseObjectException("Error setting collection IDs on objects.", e, this); - } - - PreparedStatement insertObjects = null; - final StringBuffer sb = new StringBuffer(); - sb.append("INSERT INTO " + this.getTableMetaData().getTableName() + " ("); - for (final String field : this.getTableMetaData().getFieldNames()) { - sb.append(field + ", "); - } - sb.setLength(sb.length() - 2); - sb.append(") VALUES ("); - for (int fieldIndex = 0; fieldIndex < this.getTableMetaData().getFieldNames().length; fieldIndex++) { - sb.append("?, "); - } - sb.setLength(sb.length() - 2); - sb.append(")"); - final String updateStatement = sb.toString(); - try { - insertObjects = this.connection.prepareStatement(updateStatement, Statement.RETURN_GENERATED_KEYS); - for (final ObjectType object : this) { - for (int fieldIndex = 0; fieldIndex < this.getTableMetaData().getFieldNames().length; fieldIndex++) { - final String fieldName = this.getTableMetaData().getFieldNames()[fieldIndex]; - insertObjects.setObject(fieldIndex + 1, - object.getFieldValue(getTableMetaData().getFieldType(fieldName), fieldName)); - } - insertObjects.executeUpdate(); - final ResultSet resultSet = insertObjects.getGeneratedKeys(); - resultSet.next(); - ((BaseConditionsObject) object).setRowId(resultSet.getInt(1)); - resultSet.close(); - } - // Commit the object insert statements together. - this.connection.commit(); - - } catch (final SQLException e1) { - e1.printStackTrace(); - if (this.connection != null) { - try { - System.err.println("Transaction is being rolled back ..."); - this.connection.rollback(); - } catch (final SQLException e2) { - e2.printStackTrace(); - } - } - } finally { - if (insertObjects != null) { - insertObjects.close(); - } - this.connection.setAutoCommit(true); - } } /** @@ -218,7 +240,7 @@ final String description = "inserted " + this.size() + " records into " + this.tableMetaData.getTableName(); PreparedStatement statement = null; ResultSet resultSet = null; - int collectionId = -1; + int nextCollectionId = -1; try { statement = this.connection.prepareStatement( "INSERT INTO collections (table_name, log, description, created) VALUES (?, ?, ?, NOW())", @@ -231,7 +253,7 @@ if (!resultSet.next()) { throw new DatabaseObjectException("Failed to create new collection record.", this); } - collectionId = resultSet.getInt(1); + nextCollectionId = resultSet.getInt(1); } finally { if (resultSet != null) { resultSet.close(); @@ -240,9 +262,155 @@ statement.close(); } } - return collectionId; - } - + return nextCollectionId; + } + + /** + * Get the set of objects in this collection. + * + * @return the set of objects in this collection + */ + protected Set<ObjectType> getObjects() { + return this.objects; + } + + /** + * Get the table meta data. + * + * @return the table meta data + * @see TableMetaData + */ + @Override + public final TableMetaData getTableMetaData() { + return this.tableMetaData; + } + + /** + * Insert the objects from this collection into the database. + * <p> + * The collection ID will be determined automatically if it is not already set. + * + * @throws ConditionsObjectException if there is an error inserting the objects + * @throws SQLException if there is a query error + */ + @Override + public final void insert() throws DatabaseObjectException, SQLException { + + // Turn off auto-commit to perform a transaction. + this.connection.setAutoCommit(false); + + if (this.collectionId == BaseConditionsObject.UNSET_COLLECTION_ID) { + // Automatically get the next global collection ID from the conditions database. + this.collectionId = this.getNextCollectionId(); + } else { + // If the collection already exists in the database with this ID then it cannot be inserted. + if (this.exists()) { + throw new DatabaseObjectException("The collection " + this.collectionId + + " cannot be inserted because it already exists in the " + this.tableMetaData.getTableName() + + " table.", this); + } + } + + // Set collection ID on objects. + try { + this.setConditionsObjectCollectionIds(); + } catch (final ConditionsObjectException e) { + throw new DatabaseObjectException("Error setting collection IDs on objects.", e, this); + } + + PreparedStatement insertObjects = null; + final StringBuffer sb = new StringBuffer(); + sb.append("INSERT INTO " + this.getTableMetaData().getTableName() + " ("); + for (final String field : this.getTableMetaData().getFieldNames()) { + sb.append(field + ", "); + } + sb.setLength(sb.length() - 2); + sb.append(") VALUES ("); + for (int fieldIndex = 0; fieldIndex < this.getTableMetaData().getFieldNames().length; fieldIndex++) { + sb.append("?, "); + } + sb.setLength(sb.length() - 2); + sb.append(")"); + final String updateStatement = sb.toString(); + try { + insertObjects = this.connection.prepareStatement(updateStatement, Statement.RETURN_GENERATED_KEYS); + for (final ObjectType object : this) { + for (int fieldIndex = 0; fieldIndex < this.getTableMetaData().getFieldNames().length; fieldIndex++) { + final String fieldName = this.getTableMetaData().getFieldNames()[fieldIndex]; + insertObjects.setObject(fieldIndex + 1, + object.getFieldValue(this.getTableMetaData().getFieldType(fieldName), fieldName)); + } + insertObjects.executeUpdate(); + final ResultSet resultSet = insertObjects.getGeneratedKeys(); + resultSet.next(); + ((BaseConditionsObject) object).setRowId(resultSet.getInt(1)); + resultSet.close(); + } + // Commit the object insert statements together. + this.connection.commit(); + + } catch (final SQLException e1) { + e1.printStackTrace(); + if (this.connection != null) { + try { + System.err.println("Transaction is being rolled back ..."); + this.connection.rollback(); + } catch (final SQLException e2) { + e2.printStackTrace(); + } + } + } finally { + if (insertObjects != null) { + insertObjects.close(); + } + this.connection.setAutoCommit(true); + } + } + + /** + * Return <code>true</code> if the collection has objects that need to be inserted into the database. + * + * @return <code>true</code> if the collection is dirty + */ + @Override + public final boolean isDirty() { + return this.isDirty; + } + + /** + * Return <code>true</code> if the collection is new, e.g. it is not in the database. + * + * @return <code>true</code> if the collection is new + */ + @Override + public final boolean isNew() { + if (this.collectionId == BaseConditionsObject.UNSET_COLLECTION_ID) { + return true; + } + try { + // Valid collection ID exists but need to check if inserted into database yet. + return this.exists() == false; + } catch (final SQLException e) { + throw new RuntimeException(e); + } + } + + /** + * Get an iterator for the collection. + * + * @return an iterator for the collection + */ + @Override + public final Iterator<ObjectType> iterator() { + return this.objects.iterator(); + } + + /** + * Select objects into this collection by their collection ID in the database. + * + * @return <code>true</code> if at least one object was selected + */ + // FIXME: Rewrite to use a PreparedStatement. @Override public final boolean select(final int collectionId) throws SQLException, DatabaseObjectException { this.collectionId = collectionId; @@ -271,7 +439,7 @@ newObject.setFieldValue(fieldName, resultSet.getObject(fieldIndex + 2)); } try { - add(newObject); + this.add(newObject); } catch (final ConditionsObjectException e) { throw new DatabaseObjectException("Error adding object to collection.", e, newObject); } @@ -288,17 +456,27 @@ return selected; } + /** + * Set the collection ID of this collection. + * + * @param collectionId the collection ID + */ @Override public final void setCollectionId(final int collectionId) { this.collectionId = collectionId; try { // Set collection ID on all objects. - setConditionsObjectCollectionIds(); + this.setConditionsObjectCollectionIds(); } catch (final ConditionsObjectException e) { throw new RuntimeException("Error setting collection ID on object.", e); } } + /** + * Iterate over the objects in the collection and set their collection IDs. + * + * @throws ConditionsObjectException if there is an error setting one of the collection IDs + */ private final void setConditionsObjectCollectionIds() throws ConditionsObjectException { if (this.collectionId != BaseConditionsObject.UNSET_COLLECTION_ID) { for (final ConditionsObject object : this) { @@ -307,32 +485,95 @@ } } + /** + * Iterate over the objects in the collection and set their database connection reference. + */ private final void setConditionsObjectConnections() { for (final ConditionsObject object : this) { object.setConnection(this.connection); } } - @Override - public void setConnection(final Connection connection) { + /** + * Set the database connection of the collection. + * + * @param connection the database connection of the collection + */ + @Override + public final void setConnection(final Connection connection) { this.connection = connection; // Set connection on all objects. - setConditionsObjectConnections(); - } - + this.setConditionsObjectConnections(); + } + + /** + * Set the table meta data of the collection. + * + * @param the table meta data of the collection + * @see TableMetaData + */ @Override public void setTableMetaData(final TableMetaData tableMetaData) { this.tableMetaData = tableMetaData; } + /** + * Get the size of the collection. + * + * @return the size of the collection + */ @Override public int size() { return this.objects.size(); } - @Override - // FIXME: This method should execute a prepared statement in a transaction instead of performing individual updates. + /** + * Sort the collection in place. + * + * @param comparator the comparison operator to use for sorting + */ + @Override + public final void sort(final Comparator<ObjectType> comparator) { + final List<ObjectType> list = new ArrayList<ObjectType>(this.objects); + Collections.sort(list, comparator); + this.objects.clear(); + this.objects.addAll(list); + } + + /** + * Return a sorted copy of this collection, leaving the original unchanged. + * + * @param comparator the comparison class to use for sorting + * @return a sorted copy of this collection + */ + @Override + public ConditionsObjectCollection<ObjectType> sorted(final Comparator<ObjectType> comparator) { + final List<ObjectType> list = new ArrayList<ObjectType>(this.objects); + Collections.sort(list, comparator); + BaseConditionsObjectCollection<ObjectType> collection; + try { + collection = this.getClass().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Error creating new collection instance.", e); + } + for (final ObjectType object : list) { + try { + collection.add(object); + } catch (final ConditionsObjectException e) { + throw new RuntimeException("Error adding to new collection in sorted method.", e); + } + } + return collection; + } + + /** + * Perform database updates on the objects in the collection. + * + * @return <code>true</code> if at least one object was updated + */ + @Override + // FIXME: This method should execute a prepared statement in a transaction. public boolean update() throws DatabaseObjectException, SQLException { boolean updated = false; for (final ObjectType object : this.objects) { @@ -344,102 +585,4 @@ } return updated; } - - /** - * Sort the collection in place. - * - * @param comparator the comparison to use for sorting - */ - @Override - public final void sort(final Comparator<ObjectType> comparator) { - final List<ObjectType> list = new ArrayList<ObjectType>(this.objects); - Collections.sort(list, comparator); - this.objects.clear(); - this.objects.addAll(list); - } - - @Override - public ConditionsObjectCollection<ObjectType> sorted(final Comparator<ObjectType> comparator) { - final List<ObjectType> list = new ArrayList<ObjectType>(this.objects); - Collections.sort(list, comparator); - BaseConditionsObjectCollection<ObjectType> collection; - try { - collection = this.getClass().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Error creating new collection instance.", e); - } - for (final ObjectType object : list) { - try { - collection.add(object); - } catch (final ConditionsObjectException e) { - throw new RuntimeException("Error adding to new collection in sorted method.", e); - } - } - return collection; - } - - @Override - public boolean contains(final Object object) { - return this.objects.contains(object); - } - - @Override - public void addAll(final ConditionsObjectCollection<ObjectType> collection) { - for (final ObjectType object : collection) { - this.objects.add(object); - } - } - - @Override - public Iterator<ObjectType> iterator() { - return this.objects.iterator(); - } - - @Override - public boolean isDirty() { - return this.isDirty; - } - - @Override - public boolean isNew() { - if (this.collectionId == BaseConditionsObject.UNSET_COLLECTION_ID) { - return true; - } - try { - // Valid collection ID exists but need to check if inserted into database yet. - return checkExists() == false; - } catch (final SQLException e) { - throw new RuntimeException(e); - } - } - - // FIXME: Use PreparedStatement instead of Statement. - private boolean checkExists() throws SQLException { - PreparedStatement statement = null; - ResultSet resultSet = null; - boolean exists = false; - try { - statement = this.connection.prepareStatement("SELECT id FROM " + this.tableMetaData.getTableName() - + " where collection_id = ?"); - statement.setInt(1, this.collectionId); - resultSet = statement.executeQuery(); - exists = resultSet.next(); - } finally { - if (statement != null) { - statement.close(); - } - if (resultSet != null) { - resultSet.close(); - } - } - return exists; - } - - protected Set<ObjectType> getObjects() { - return this.objects; - } - - protected void setIsDirty(boolean isDirty) { - this.isDirty = isDirty; - } } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObject.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObject.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObject.java Fri Jun 19 14:10:26 2015 @@ -1,39 +1,71 @@ package org.hps.conditions.api; +/** + * This is an interface for connecting conditions information to a database. + * <p> + * Most of the functionality is derived from the {@link DatabaseObject} interface. + * + * @author Jeremy McCormick, SLAC + */ public interface ConditionsObject extends DatabaseObject { /** - * @return + * Return the collection ID of the object. + * + * @return the collection ID of the object */ Integer getCollectionId(); - boolean hasValidCollection(); + /** + * Get the value of a field by casting to an explicit type. + * + * @param type the return type + * @param name the name of the field + * @return the field value + */ + <T> T getFieldValue(final Class<T> type, final String name); + /** + * Get the value of a field by casting to an implicit type. + * + * @param name the name of the field + * @return the field value + */ + <T> T getFieldValue(final String name); + + /** + * Get the field values for the object. + * + * @return the field values for the object + */ FieldValues getFieldValues(); /** - * @return + * Get the row ID of the object in the database. + * + * @return the row ID of the object in the database */ int getRowId(); /** - * @param type - * @param name - * @return + * Return <code>true</code> if object has a valid collection ID. + * + * @return <code>true</code> if object has a valid collection ID */ - <T> T getFieldValue(final Class<T> type, final String name); - - <T> T getFieldValue(final String name); - - void setFieldValues(FieldValues fieldValues); + boolean hasValidCollectionId(); /** - * @param name - * @param value + * Set the value of a field. + * + * @param name the name of the field + * @param value the new value of the field */ void setFieldValue(String name, Object value); - - // void setCollectionId(Integer id); - - // void setRowId(Integer id); + + /** + * Set all of the field values. + * + * @param fieldValues the new field values + */ + void setFieldValues(FieldValues fieldValues); } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectCollection.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectCollection.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectCollection.java Fri Jun 19 14:10:26 2015 @@ -2,24 +2,80 @@ import java.util.Comparator; +/** + * Interface representing a collection of conditions objects. + * + * @author Jeremy McCormick, SLAC + * @param <ObjectType> the type of the objects + */ public interface ConditionsObjectCollection<ObjectType extends ConditionsObject> extends Iterable<ObjectType>, DatabaseObject { + /** + * Add an object to the collection. + * + * @param object the object to add to the collection + * @return <code>true</code> if object was added successfully + * @throws ConditionsObjectException if there was an error adding the object + */ boolean add(final ObjectType object) throws ConditionsObjectException; + /** + * Add all objects to the collection. + * + * @param collection the source collection with objects to add + */ + void addAll(ConditionsObjectCollection<ObjectType> collection); + + /** + * Return <code>true</code> if collection contains this object. + * + * @param object the object to check + * @return <code>true</code> if the collection contains the object + */ + boolean contains(Object object); + + /** + * Get an object by index. + * + * @param index the index of the object + * @return the object + */ ObjectType get(final int index); + /** + * Get the collection ID. + * + * @return the collection ID + */ int getCollectionId(); - void setCollectionId(int id); + /** + * Set the collection ID. + * + * @param collectionId the new collection ID + */ + void setCollectionId(int collectionId); + /** + * Get the size of the collection. + * + * @return the size of the collection + */ int size(); + /** + * Sort the collection in place. + * + * @param comparator the comparison operator to use for sorting + */ void sort(final Comparator<ObjectType> comparator); + /** + * Get a sorted copy of the collection, leaving the original in place. + * + * @param comparator the comparison operator to use + * @return the sorted copy of the collection + */ ConditionsObjectCollection<ObjectType> sorted(final Comparator<ObjectType> comparator); - - boolean contains(Object object); - - void addAll(ConditionsObjectCollection<ObjectType> collection); -} +} Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java Fri Jun 19 14:10:26 2015 @@ -2,6 +2,8 @@ /** * Thrown by methods of {@link ConditionsObject} or other associated classes such as converters and collections. + * + * @author Jeremy McCormick */ @SuppressWarnings("serial") public final class ConditionsObjectException extends Exception { @@ -21,16 +23,6 @@ } /** - * Error with an associated throwable. - * - * @param message the error message - * @param cause the error's cause - */ - public ConditionsObjectException(final String message, final Throwable cause) { - super(message, cause); - } - - /** * Error with a message and object. * * @param message the error message @@ -42,11 +34,21 @@ } /** + * Error with an associated throwable. + * + * @param message the error message + * @param cause the error's cause + */ + public ConditionsObjectException(final String message, final Throwable cause) { + super(message, cause); + } + + /** * Get the associated conditions object to the error. - * + * * @return the object associated with the error */ public ConditionsObject getConditionsObject() { - return object; + return this.object; } } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectUtilities.java Fri Jun 19 14:10:26 2015 @@ -14,7 +14,7 @@ /** * This is a collection of utility methods for {@link ConditionsObject}. * - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC */ public final class ConditionsObjectUtilities { Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsRecord.java Fri Jun 19 14:10:26 2015 @@ -14,7 +14,7 @@ * This class represents a single record from the primary conditions data table, which defines the validity range for a * specific collection of conditions objects. * - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC */ @Table(names = {"conditions"}) @Converter(converter = ConditionsRecordConverter.class) @@ -23,13 +23,13 @@ /** * The concrete collection implementation, including sorting utilities. */ - @SuppressWarnings("serial") public static class ConditionsRecordCollection extends BaseConditionsObjectCollection<ConditionsRecord> { /** * Compare conditions records by creation date. */ private static class CreatedComparator implements Comparator<ConditionsRecord> { + /** * Compare the creation dates of two conditions records. * @@ -54,6 +54,7 @@ * Compare conditions records by their key (table name). */ private static class KeyComparator implements Comparator<ConditionsRecord> { + /** * Compare the keys (names) of two conditions records. * @@ -72,6 +73,7 @@ * Compare conditions records by run start. */ private static class RunStartComparator implements Comparator<ConditionsRecord> { + /** * Compare the run start numbers of two conditions records. * @@ -94,6 +96,7 @@ * Compare conditions records by updated date. */ private static class UpdatedComparator implements Comparator<ConditionsRecord> { + /** * Compare the updated dates of two conditions records. * @@ -114,7 +117,14 @@ } } + /** + * Add a <code>ConditionsRecord</code> to the collection. + * + * @param object the <code>ConditionsRecord</code> to add to the collection + * @return <code>true</code> if object was added + */ @Override + // FIXME: Not sure this method needs to exist. public boolean add(final ConditionsRecord object) throws ConditionsObjectException { if (object == null) { throw new IllegalArgumentException("The object argument is null."); @@ -127,7 +137,11 @@ } /** - * Find a sub-set of the records with matching key name. + * Find a sub-set of the records matching the key name. + * <p> + * These will generally map to names of tables. + * + * @param key the key to find */ public ConditionsRecordCollection findByKey(final String key) { final ConditionsRecordCollection collection = new ConditionsRecordCollection(); @@ -157,35 +171,35 @@ } /** - * Sort in place by creation date. + * Sort the collection in place by creation date. */ public final void sortByCreated() { this.sort(new CreatedComparator()); } /** - * Sort in place by key. + * Sort the collection in place by key. */ public final void sortByKey() { this.sort(new KeyComparator()); } /** - * Sort in place by run start. + * Sort the collection in place by run start. */ public final void sortByRunStart() { this.sort(new RunStartComparator()); } /** - * Sort in place by updated date. + * Sort the collection in place by updated date. */ public final void sortByUpdated() { this.sort(new UpdatedComparator()); } /** - * Sort and return collection by creation date. + * Sort and return the collection by creation date. * * @return the sorted collection */ @@ -194,7 +208,7 @@ } /** - * Sort and return by key (table name). + * Sort and return the collection by key (table name). * * @return the sorted collection */ @@ -203,7 +217,7 @@ } /** - * Sort and return by run start number. + * Sort and return the collection by run start number. * * @return the sorted collection */ @@ -212,7 +226,7 @@ } /** - * Sort and return collection by updated date. + * Sort and return the collection by updated date. * * @return the sorted collection */ @@ -222,7 +236,9 @@ } /** - * Create a "blank" conditions record. + * Class constructor. + * <p> + * Creates an empty conditions record. */ public ConditionsRecord() { } @@ -245,12 +261,12 @@ } /** - * Create a conditions record with fully qualified constructor. + * Fully qualified class constructor. * * @param collectionId the ID of the associated conditions collection * @param runStart the starting run number * @param runEnd the ending run number - * @param name the name of the conditions set (usually same as table name) + * @param name the name of the conditions set (usually the same as table name but can be different) * @param tableName the name of the conditions data table * @param notes text notes about this record * @param tag the conditions tag for grouping this record with others Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsSeries.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsSeries.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/ConditionsSeries.java Fri Jun 19 14:10:26 2015 @@ -8,9 +8,10 @@ * * @param <ObjectType> the type of the conditions object * @param <CollectionType> the type of the conditions collection - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC */ @SuppressWarnings({"serial"}) +// FIXME: This class should possibly be removed. It doesn't provide much functionality. public class ConditionsSeries<ObjectType extends ConditionsObject, CollectionType extends ConditionsObjectCollection<ObjectType>> extends ArrayList<ConditionsObjectCollection<ObjectType>> { } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObject.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObject.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObject.java Fri Jun 19 14:10:26 2015 @@ -4,9 +4,19 @@ import java.sql.SQLException; /** + * This is a simple ORM interface for mapping Java objects to a database. + * * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public interface DatabaseObject { + + /** + * Delete the object from the database, using its table name from the meta data and row ID. + * + * @throws ConditionsObjectException if there was an error deleting the object + * @throws SQLException if there was a SQL query error + */ + void delete() throws DatabaseObjectException, SQLException; /** * Get the {@link TableMetaData} for this object. @@ -14,11 +24,6 @@ * @return the {@link TableMetaData} for this object. */ TableMetaData getTableMetaData(); - - /** - * @param tableMetaData - */ - void setTableMetaData(TableMetaData tableMetaData); /** * Insert the data of this object into the database. @@ -31,13 +36,6 @@ public void insert() throws DatabaseObjectException, SQLException; /** - * Set the database <code>Connection</code> for the object. - * - * @param connection the database <code>Connection</code> for the object - */ - void setConnection(Connection connection); - - /** * Return <code>true</code> if there are local data modifications that have not been persisted to the database. * * @return <code>true</code> if there un-persisted local data modifications @@ -47,28 +45,41 @@ /** * Return <code>true</code> if the record * - * @return + * @return <code>true</code> if the object is new */ boolean isNew(); /** + * Select information from the database into this object using the row ID. + * + * @param id the row ID + * @return <code>true</code> if the select operation worked + * @throws DatabaseObjectException if there was an error selecting information into this object + * @throws SQLException if there was a query error + */ + boolean select(final int id) throws DatabaseObjectException, SQLException; + + /** + * Set the database <code>Connection</code> for the object. + * + * @param connection the database <code>Connection</code> for the object + */ + void setConnection(Connection connection); + + /** + * Set the table meta data of the object. + * + * @param tableMetaData the table meta data of the object + * @see TableMetaData + */ + void setTableMetaData(TableMetaData tableMetaData); + + /** + * Update the information in the database from this object. + * * @return <code>true</code> if an update occurred - * @throws ConditionsObjectException + * @throws ConditionsObjectException if there is an error performing the update from the object + * @throws SQLException if there is a SQL query error */ boolean update() throws DatabaseObjectException, SQLException; - - /** - * @return - * @throws ConditionsObjectException - * @throws SQLException - */ - void delete() throws DatabaseObjectException, SQLException; - - /** - * @param id - * @return - * @throws DatabaseObjectException - * @throws SQLException - */ - boolean select(final int id) throws DatabaseObjectException, SQLException; } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObjectException.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObjectException.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/DatabaseObjectException.java Fri Jun 19 14:10:26 2015 @@ -1,18 +1,22 @@ package org.hps.conditions.api; /** - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * Exception for errors that occur when performing operations on {@link DatabaseObject}s. + * + * @author Jeremy McCormick, SLAC */ public final class DatabaseObjectException extends Exception { /** - * + * The object on which the error occurred. */ private final DatabaseObject object; /** - * @param message - * @param object + * Class constructor. + * + * @param message the message describing the error + * @param object the object with the error */ public DatabaseObjectException(final String message, final DatabaseObject object) { super(message); @@ -20,9 +24,11 @@ } /** - * @param message - * @param cause - * @param object + * Class constructor. + * + * @param message the message describing the error + * @param cause the cause of the error (another <code>Exception</code> that was caught) + * @param object the object with the error */ public DatabaseObjectException(final String message, final Throwable cause, final DatabaseObject object) { super(message, cause); @@ -30,7 +36,9 @@ } /** - * @return + * Get the object with the error. + * + * @return the object that had the error */ public DatabaseObject getDatabaseObject() { return this.object; Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValues.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValues.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValues.java Fri Jun 19 14:10:26 2015 @@ -4,25 +4,81 @@ import java.util.Set; /** - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * Representation of fields and values of individual conditions objects. + * + * @author Jeremy McCormick, SLAC */ public interface FieldValues { + /** + * Get the field names. + * + * @return the field names + */ Set<String> getFieldNames(); + /** + * Get a field value. + * + * @param <T> the object type (inferred from the explicit type argument) + * @param type the class of the object to return + * @param name the name of the field + * @return the field value + */ + // FIXME: This could be simplified by using type inference on the return object and removing the type param. <T> T getValue(Class<T> type, String name); + /** + * Get a field value as an object. + * + * @param name the name of the field + * @return the field value as an object + */ Object getValue(String name); + /** + * Get the collection of values. + * + * @return the collection of values + */ Collection<Object> getValues(); + /** + * Return <code>true</code> if this field exists. + * + * @param name the name of the field + * @return <code>true</code> if the field exists + */ boolean hasField(String name); + /** + * Return <code>true</code> if the field's value is not null. + * + * @param name the name of the field + * @return <code>true</code> if the field's value is not null + */ boolean isNonNull(String name); + /** + * Return <code>true</code> if the field's value is null. + * + * @param name the name of the field + * @return <code>true</code> if the field's value is null + */ boolean isNull(String name); + /** + * Set the value of a field. + * + * @param name the name of the field + * @param value the new value of the field + */ void setValue(String name, Object value); + /** + * Get the size which is the field count. + * + * @return the size + */ int size(); } Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValuesMap.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValuesMap.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/FieldValuesMap.java Fri Jun 19 14:10:26 2015 @@ -6,61 +6,121 @@ import java.util.Set; /** - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * Implementation of {@link FieldValues} for storing field-value pairs. + * + * @author Jeremy McCormick, SLAC */ -public class FieldValuesMap implements FieldValues { +public final class FieldValuesMap implements FieldValues { - Map<String, Object> data = new HashMap<String, Object>(); + /** + * Map of field names to values. + */ + private final Map<String, Object> data = new HashMap<String, Object>(); + /** + * Class constructor. + */ public FieldValuesMap() { } + /** + * Class constructor with table meta data; all fields in the table will have values set to null in the map. + * + * @param tableMetaData the table meta data + */ FieldValuesMap(final TableMetaData tableMetaData) { for (final String fieldName : tableMetaData.getFieldNames()) { this.data.put(fieldName, null); } } + /** + * Get the set of field names. + * + * @return the set of field names + */ @Override public Set<String> getFieldNames() { return this.data.keySet(); } + /** + * Get a value and cast to a type. + * + * @param type the return type + * @param name the name of the field + */ @Override public <T> T getValue(final Class<T> type, final String name) { return type.cast(this.data.get(name)); } + /** + * Get a value as an object. + * + * @return the name of the field + */ @Override public Object getValue(final String name) { return this.data.get(name); } + /** + * Get the values as a collection of objects. + * + * @return the values as a collection of objects + */ @Override public Collection<Object> getValues() { return this.data.values(); } + /** + * Return <code>true</code> if field exists with any value. + * + * @return <code>true</code> if field exists + */ @Override public boolean hasField(final String name) { return this.data.containsKey(name); } + /** + * Return <code>true</code> if the field has a non-null value. + * + * @return <code>true</code> if the field has a non-null value + */ @Override public boolean isNonNull(final String name) { return this.data.get(name) != null; } + /** + * Return <code>true</code> if the field has a null value. + * + * @return <code>true</code> if field is null + */ @Override public boolean isNull(final String name) { return this.data.get(name) == null; } + /** + * Set the value of a field. + * + * @param name the name of the field + * @param value the value of the field + */ @Override public void setValue(final String name, final Object value) { this.data.put(name, value); } + /** + * Return the size of the values. + * + * @return the size of the values + */ @Override public int size() { return this.data.size(); Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableMetaData.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableMetaData.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableMetaData.java Fri Jun 19 14:10:26 2015 @@ -9,16 +9,15 @@ import java.util.Set; /** + * This class provides meta data about a conditions table, including a list of fields. A row ID field called <i>id</i> + * is assumed to exist and be a primary key for the table. (Problems will occur if this is not the case!) * <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> - * It also has references to the implementation classes which are used for the ORM onto {@link ConditionsObject} and - * {@link ConditionsObjectCollection}. + * The class also has references to the implementation classes which are used for mapping database operations to the + * {@link ConditionsObject} and {@link ConditionsObjectCollection} API. * + * @author Jeremy McCormick, SLAC * @see org.hps.conditions.api.ConditionsObject * @see org.hps.conditions.api.BaseConditionsObjectCollection - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class TableMetaData { @@ -71,6 +70,11 @@ */ private String tableName; + /** + * Class constructor. + * <p> + * Creates an empty object. + */ public TableMetaData() { } @@ -167,6 +171,11 @@ return this.tableName; } + /** + * Set all the field names from an array of strings. + * + * @param fieldNames the names of the fields + */ void setFieldNames(final String[] fieldNames) { this.fieldNames = new HashSet<String>(); for (final String fieldName : fieldNames) { @@ -174,14 +183,30 @@ } } + /** + * Set the type of a field. + * + * @param fieldName the field name + * @param fieldType the field's type (class) + */ void setFieldType(final String fieldName, final Class<?> fieldType) { this.fieldTypes.put(fieldName, fieldType); } + /** + * Set the class that maps to the database. + * + * @param objectClass the class that maps to the database + */ void setObjectClass(final Class<? extends ConditionsObject> objectClass) { this.objectClass = objectClass; } + /** + * Set the table name. + * + * @param tableName the table name + */ void setTableName(final String tableName) { this.tableName = tableName; } @@ -205,4 +230,4 @@ buff.append('\n'); return buff.toString(); } -} +} Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableRegistry.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableRegistry.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/TableRegistry.java Fri Jun 19 14:10:26 2015 @@ -19,7 +19,7 @@ public final class TableRegistry extends HashMap<String, TableMetaData> { /** - * Maps collection types to table meta data. + * Class which maps collection types to their table meta data. */ static class CollectionTypeMap extends HashMap<Class<? extends BaseConditionsObjectCollection<?>>, List<TableMetaData>> { @@ -39,7 +39,7 @@ } /** - * Maps types to table meta data. + * Class that maps object types to their table meta data. */ static class ObjectTypeMap extends HashMap<Class<? extends ConditionsObject>, List<TableMetaData>> { /** @@ -56,7 +56,10 @@ } } - static TableRegistry instance = null; + /** + * The global, static instance of the registry. + */ + private static TableRegistry instance = null; /** * Create a new table meta data registry. @@ -101,8 +104,14 @@ return registry; } + /** + * Get the global static instance of the registry. + * + * @return the global static instance of the registry + */ public synchronized static TableRegistry getTableRegistry() { if (instance == null) { + // Create registry if it does not exist. instance = TableRegistry.create(); } return instance; @@ -119,7 +128,7 @@ private final ObjectTypeMap objectTypeMap = new ObjectTypeMap(); /** - * Class should not be directly instantiated. + * Prevent direct class instantiation by users. * <p> * Use the {@link #create()} method instead. */ Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/package-info.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/package-info.java (original) +++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/api/package-info.java Fri Jun 19 14:10:26 2015 @@ -1,8 +1,7 @@ /** - * This package contains interfaces and abstract classes, along with some implementations, of the database conditions - * API for HPS. These classes include simple ORM between conditions objects and the database. + * Interfaces, abstract classes and implementations of the conditions system API for HPS. * - * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @author Jeremy McCormick, SLAC * @see ConditionsObject * @see ConditionsObjectCollection * @see ConditionsSeries Modified: java/branches/HPSJAVA-488/conditions/src/test/java/org/hps/conditions/dummy/DummyConditionsObjectTest.java ============================================================================= --- java/branches/HPSJAVA-488/conditions/src/test/java/org/hps/conditions/dummy/DummyConditionsObjectTest.java (original) +++ java/branches/HPSJAVA-488/conditions/src/test/java/org/hps/conditions/dummy/DummyConditionsObjectTest.java Fri Jun 19 14:10:26 2015 @@ -87,7 +87,7 @@ + newObject.getTableMetaData().getTableName() + " table."); assertEquals("The isNew method returned the wrong value.", false, newObject.isNew()); assertEquals("The isDirty method returned the wrong value.", false, newObject.isDirty()); - assertEquals("Object does not have a valid collection after insert.", true, newObject.hasValidCollection()); + assertEquals("Object does not have a valid collection after insert.", true, newObject.hasValidCollectionId()); // Select into another object by ID. final DummyConditionsObject anotherObject = new DummyConditionsObject(connection, tableMetaData); @@ -97,7 +97,7 @@ // Check that the selection into another object worked. assertEquals("Selected object has wrong row id.", newObject.getRowId(), anotherObject.getRowId()); - assertTrue("Select object does not have valid collection.", anotherObject.hasValidCollection()); + assertTrue("Select object does not have valid collection.", anotherObject.hasValidCollectionId()); assertEquals("Selected object has wrong collection id.", newObject.getCollectionId(), anotherObject.getCollectionId()); assertEquals("Selected object has wrong value.", newObject.getDummy(), anotherObject.getDummy());