Print

Print


Author: [log in to unmask]
Date: Thu Nov 13 19:50:23 2014
New Revision: 1514

Log:
Patch from Sho to fix slow conditions loading.  Replaces internal ArrayList with LinkedHashSet.

Modified:
    java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java

Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java
 =============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java	(original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ConditionsObjectCollection.java	Thu Nov 13 19:50:23 2014
@@ -1,170 +1,167 @@
-package org.hps.conditions;
-
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-public class ConditionsObjectCollection<ObjectType extends ConditionsObject> implements Iterable<ObjectType> {
-
-    protected List<ObjectType> objects = new ArrayList<ObjectType>();
-    protected TableMetaData tableMetaData;
-    protected int collectionId = -1;
-    protected boolean isReadOnly;
-    protected boolean isDirty;
-    protected boolean isNew;
-    protected ConditionsRecord conditionsRecord;
-
-    protected ConditionsObjectCollection() {
-    }
-
-    public ConditionsObjectCollection(TableMetaData tableMetaData, int collectionId, boolean isReadOnly) {
-        this.tableMetaData = tableMetaData;
-        this.collectionId = collectionId;
-        this.isReadOnly = isReadOnly;
-        if (collectionId == -1) {
-            this.isNew = true;
-        }
-    }
-
-    public ConditionsRecord getConditionsRecord() {
-        return conditionsRecord;
-    }
-
-    public ObjectType get(int index) {
-        return objects.get(index);
-    }
-
-    public List<ObjectType> getObjects() {
-        return Collections.unmodifiableList(objects);
-    }
-
-    public boolean contains(Object object) {
-        return getObjects().contains(object);
-    }
-
-    // TODO: Should check here if object has an existing collection ID that is
-    // different
-    // from this collection's, in which case this collection becomes "mixed" and
-    // it should
-    // be
-    // flagged as read only.
-    public void add(ObjectType object) throws ConditionsObjectException {
-        if (objects.contains(object)) {
-            throw new IllegalArgumentException("Collection already contains this object.");
-        }
-        try {
-            // Only assign a collection ID to the object if this collection has
-            // a valid ID
-            // and the object does not have one already.
-            if (getCollectionId() != -1)
-                object.setCollectionId(getCollectionId());
-        } catch (ConditionsObjectException x) {
-            throw new IllegalArgumentException("Error assigning collection ID to object.", x);
-        }
-        // Set the table meta data on the object if it does not have any.
-        if (object.getTableMetaData() == null && tableMetaData != null)
-            object.setTableMetaData(tableMetaData);
-        objects.add(object);
-        if (!isNew())
-            setIsDirty(true);
-    }
-
-    public TableMetaData getTableMetaData() {
-        return tableMetaData;
-    }
-
-    public int getCollectionId() {
-        return collectionId;
-    }
-
-    // TODO: Should this also insert new records that do not exist?
-    // TODO: This operation should lock the table.
-    public void update() throws ConditionsObjectException {
-        for (ConditionsObject object : objects) {
-            object.update();
-        }
-        setIsDirty(false);
-    }
-
-    // TODO: This does not need to loop. It should just call delete on the
-    // collection ID
-    // value.
-    public void delete() throws ConditionsObjectException {
-        if (isReadOnly()) {
-            throw new ConditionsObjectException("Collection is read only.");
-        }
-        for (ConditionsObject object : objects) {
-            object.delete();
-        }
-    }
-
-    // TODO: This should not loop. It should select all the objects with a
-    // matching
-    // collection ID
-    // from the database.
-    public void select() throws ConditionsObjectException, SQLException {
-        for (ConditionsObject object : objects) {
-            object.select();
-        }
-    }
-
-    // TODO: This method needs to get the next collection ID from the conditions
-    // manager.
-    // TODO: This operation should lock the table.
-    public void insert() throws ConditionsObjectException, SQLException {
-        if (!isNew()) {
-            throw new ConditionsObjectException("Collection already exists in the database.");
-        }
-        for (ConditionsObject object : objects) {
-            // if (object.isNew()) {
-            object.insert();
-            // }
-        }
-        isNew = false;
-    }
-
-    public boolean isDirty() {
-        return isDirty;
-    }
-
-    public boolean isReadOnly() {
-        return isReadOnly;
-    }
-
-    void setIsDirty(boolean isDirty) {
-        this.isDirty = isDirty;
-    }
-
-    // TODO: This can probably just check if collection ID is not valid e.g.
-    // equals -1.
-    public boolean isNew() {
-        return isNew;
-    }
-
-    public void setCollectionId(int collectionId) throws ConditionsObjectException {
-        if (this.collectionId != -1)
-            throw new ConditionsObjectException("The collection ID is already set.");
-        this.collectionId = collectionId;
-    }
-
-    public void setTableMetaData(TableMetaData tableMetaData) {
-        this.tableMetaData = tableMetaData;
-    }
-
-    public void setIsReadOnly(boolean isReadOnly) {
-        this.isReadOnly = isReadOnly;
-    }
-
-    public void setConditionsRecord(ConditionsRecord conditionsRecord) throws ConditionsObjectException {
-        if (this.conditionsRecord != null)
-            throw new ConditionsObjectException("The ConditionsRecord is already set on this collection.");
-        this.conditionsRecord = conditionsRecord;
-    }
-
-    @Override
-    public Iterator<ObjectType> iterator() {
-        return objects.iterator();
-    }
-}
+package org.hps.conditions;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class ConditionsObjectCollection<ObjectType extends ConditionsObject> implements Iterable<ObjectType> {
+
+    protected Set<ObjectType> objects = new LinkedHashSet<ObjectType>();
+    protected TableMetaData tableMetaData;
+    protected int collectionId = -1;
+    protected boolean isReadOnly;
+    protected boolean isDirty;
+    protected boolean isNew;
+    protected ConditionsRecord conditionsRecord;
+
+    protected ConditionsObjectCollection() {
+    }
+
+    public ConditionsObjectCollection(TableMetaData tableMetaData, int collectionId, boolean isReadOnly) {
+        this.tableMetaData = tableMetaData;
+        this.collectionId = collectionId;
+        this.isReadOnly = isReadOnly;
+        if (collectionId == -1) {
+            this.isNew = true;
+        }
+    }
+
+    public ConditionsRecord getConditionsRecord() {
+        return conditionsRecord;
+    }
+
+    public ObjectType get(int index) {
+        Iterator<ObjectType> iterator = objects.iterator();
+        ObjectType current = iterator.next();
+        for (int i = 0; i < index; i++) {
+            current = iterator.next();
+        }
+        return current;
+    }
+
+    public Set<ObjectType> getObjects() {
+        return Collections.unmodifiableSet(objects);
+    }
+
+    public boolean contains(Object object) {
+        return getObjects().contains(object);
+    }
+
+    // TODO: Should check here if object has an existing collection ID that is
+    // different from this collection's, in which case this collection becomes "mixed" and
+    // it should be flagged as read only.
+    public void add(ObjectType object) throws ConditionsObjectException {
+        if (objects.contains(object)) {
+            throw new IllegalArgumentException("Collection already contains this object.");
+        }
+        try {
+            // Only assign a collection ID to the object if this collection has a valid ID
+            // and the object does not have one already.
+            if (getCollectionId() != -1)
+                object.setCollectionId(getCollectionId());
+        } catch (ConditionsObjectException x) {
+            throw new IllegalArgumentException("Error assigning collection ID to object.", x);
+        }
+        // Set the table meta data on the object if it does not have any.
+        if (object.getTableMetaData() == null && tableMetaData != null)
+            object.setTableMetaData(tableMetaData);
+        objects.add(object);
+        if (!isNew())
+            setIsDirty(true);
+    }
+
+    public TableMetaData getTableMetaData() {
+        return tableMetaData;
+    }
+
+    public int getCollectionId() {
+        return collectionId;
+    }
+
+    // TODO: Should this also insert new records that do not exist?
+    // TODO: This operation should lock the table.
+    public void update() throws ConditionsObjectException {
+        for (ConditionsObject object : objects) {
+            object.update();
+        }
+        setIsDirty(false);
+    }
+
+    // TODO: This does not need to loop. It should just call delete on the
+    // collection ID value.
+    public void delete() throws ConditionsObjectException {
+        if (isReadOnly()) {
+            throw new ConditionsObjectException("Collection is read only.");
+        }
+        for (ConditionsObject object : objects) {
+            object.delete();
+        }
+    }
+
+    // TODO: This should not loop. It should select all the objects with a
+    // matching collection ID from the database.
+    public void select() throws ConditionsObjectException, SQLException {
+        for (ConditionsObject object : objects) {
+            object.select();
+        }
+    }
+
+    // TODO: This method needs to get the next collection ID from the conditions
+    // manager.
+    // TODO: This operation should lock the table.
+    public void insert() throws ConditionsObjectException, SQLException {
+        if (!isNew()) {
+            throw new ConditionsObjectException("Collection already exists in the database.");
+        }
+        for (ConditionsObject object : objects) {
+            // if (object.isNew()) {
+            object.insert();
+            // }
+        }
+        isNew = false;
+    }
+
+    public boolean isDirty() {
+        return isDirty;
+    }
+
+    public boolean isReadOnly() {
+        return isReadOnly;
+    }
+
+    void setIsDirty(boolean isDirty) {
+        this.isDirty = isDirty;
+    }
+
+    // TODO: This can probably just check if collection ID is not valid e.g. equals -1.
+    public boolean isNew() {
+        return isNew;
+    }
+
+    public void setCollectionId(int collectionId) throws ConditionsObjectException {
+        if (this.collectionId != -1)
+            throw new ConditionsObjectException("The collection ID is already set.");
+        this.collectionId = collectionId;
+    }
+
+    public void setTableMetaData(TableMetaData tableMetaData) {
+        this.tableMetaData = tableMetaData;
+    }
+
+    public void setIsReadOnly(boolean isReadOnly) {
+        this.isReadOnly = isReadOnly;
+    }
+
+    public void setConditionsRecord(ConditionsRecord conditionsRecord) throws ConditionsObjectException {
+        if (this.conditionsRecord != null)
+            throw new ConditionsObjectException("The ConditionsRecord is already set on this collection.");
+        this.conditionsRecord = conditionsRecord;
+    }
+
+    @Override
+    public Iterator<ObjectType> iterator() {
+        return objects.iterator();
+    }
+}