Author: jm
Date: 2012-09-18 12:05:12 -0700 (Tue, 18 Sep 2012)
New Revision: 30377
Added:
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyListImpl.java
Modified:
core3/api/trunk/model-api/src/test/java/org/cytoscape/model/AbstractCyTableTest.java
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/handler/ReadDataManager.java
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyTableImpl.java
core3/impl/trunk/model-impl/impl/src/test/java/org/cytoscape/model/CyTableTest.java
Log:
Fixes #1426: Added wrapper for lists so it's cheap to get and update them while
removing side effects
Modified:
core3/api/trunk/model-api/src/test/java/org/cytoscape/model/AbstractCyTableTest.java
===================================================================
---
core3/api/trunk/model-api/src/test/java/org/cytoscape/model/AbstractCyTableTest.java
2012-09-18 17:56:27 UTC (rev 30376)
+++
core3/api/trunk/model-api/src/test/java/org/cytoscape/model/AbstractCyTableTest.java
2012-09-18 19:05:12 UTC (rev 30377)
@@ -58,6 +58,13 @@
protected boolean rowCreatedMicroListenerWasCalled;
protected boolean rowAboutToBeDeletedMicroListenerWasCalled;
+ protected void assertListEquals(List<?> expected, List<?> actual) {
+ assertEquals(expected.size(), actual.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), actual.get(i));
+ }
+ }
+
@Test
public void testAddStringAttr() {
table.createColumn("someString", String.class, false);
@@ -435,7 +442,7 @@
final List<String> strings = new ArrayList<String>();
strings.add("joe");
attrs.set("l", strings);
- assertEquals(attrs.getList("l", String.class), strings);
+ assertListEquals(attrs.getList("l", String.class), strings);
}
@Test(expected=NullPointerException.class)
Modified:
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/handler/ReadDataManager.java
===================================================================
---
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/handler/ReadDataManager.java
2012-09-18 17:56:27 UTC (rev 30376)
+++
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/handler/ReadDataManager.java
2012-09-18 19:05:12 UTC (rev 30377)
@@ -517,8 +517,8 @@
extEdgeIds =
nphRow.getList(EXTERNAL_EDGE_ATTRIBUTE, Long.class);
if (extEdgeIds == null) {
- extEdgeIds = new
ArrayList<Long>();
-
nphRow.set(EXTERNAL_EDGE_ATTRIBUTE, extEdgeIds);
+
nphRow.set(EXTERNAL_EDGE_ATTRIBUTE, new ArrayList<Long>());
+ extEdgeIds =
nphRow.getList(EXTERNAL_EDGE_ATTRIBUTE, Long.class);
}
}
}
Added:
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyListImpl.java
===================================================================
---
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyListImpl.java
(rev 0)
+++
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyListImpl.java
2012-09-18 19:05:12 UTC (rev 30377)
@@ -0,0 +1,263 @@
+package org.cytoscape.model.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.cytoscape.event.CyEventHelper;
+import org.cytoscape.model.CyColumn;
+import org.cytoscape.model.CyRow;
+import org.cytoscape.model.events.RowSetRecord;
+import org.cytoscape.model.events.RowsSetEvent;
+
+public class CyListImpl<T> implements List<T> {
+ private Class<T> elementType;
+ private List<T> delegate;
+ private CyEventHelper eventHelper;
+ private CyRow row;
+ private CyColumn column;
+
+ public CyListImpl(Class<T> elementType, List<T> delegate, CyEventHelper
eventHelper, CyRow row, CyColumn column) {
+ this.elementType = elementType;
+ this.delegate = delegate;
+ this.eventHelper = eventHelper;
+ this.row = row;
+ this.column = column;
+ }
+
+ public Class<T> getListElementType() {
+ return elementType;
+ }
+
+ @Override
+ public boolean add(T item) {
+ checkType(item);
+ if (delegate.add(item)) {
+ fireEvent();
+ return true;
+ }
+ return false;
+ }
+
+ private void checkType(T item) {
+ if (item == null ||
!elementType.isAssignableFrom(item.getClass())) {
+ throw new IllegalArgumentException("This list only
allows objects of type " + elementType.getName());
+ }
+ }
+
+ private void fireEvent() {
+ // TODO: If this is a virtual column, we need to ensure all
dependents
+ // fire events.
+ eventHelper.addEventPayload(row.getTable(), new
RowSetRecord(row, column.getName(), this, this), RowsSetEvent.class);
+ }
+
+ @Override
+ public void add(int index, T item) {
+ checkType(item);
+ fireEvent();
+ delegate.add(index, item);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends T> items) {
+ for (T item : items) {
+ checkType(item);
+ }
+ if (delegate.addAll(items)) {
+ fireEvent();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends T> items) {
+ for (T item : items) {
+ checkType(item);
+ }
+ if (delegate.addAll(index, items)) {
+ fireEvent();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void clear() {
+ if (delegate.size() == 0) {
+ return;
+ }
+ delegate.clear();
+ fireEvent();
+ }
+
+ @Override
+ public boolean contains(Object item) {
+ return delegate.contains(item);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> items) {
+ return delegate.containsAll(items);
+ }
+
+ @Override
+ public T get(int index) {
+ return delegate.get(index);
+ }
+
+ @Override
+ public int indexOf(Object item) {
+ return delegate.indexOf(item);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return listIterator();
+ }
+
+ @Override
+ public int lastIndexOf(Object item) {
+ return delegate.lastIndexOf(item);
+ }
+
+ @Override
+ public ListIterator<T> listIterator() {
+ final ListIterator<T> iterator = delegate.listIterator();
+ return createListIterator(iterator);
+ }
+
+ private ListIterator<T> createListIterator(final ListIterator<T>
iterator) {
+ return new ListIterator<T>() {
+ @Override
+ public void add(T item) {
+ checkType(item);
+ iterator.add(item);
+ fireEvent();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return iterator.hasPrevious();
+ }
+
+ @Override
+ public T next() {
+ return iterator.next();
+ }
+
+ @Override
+ public int nextIndex() {
+ return iterator.nextIndex();
+ }
+
+ @Override
+ public T previous() {
+ return iterator.previous();
+ }
+
+ @Override
+ public int previousIndex() {
+ return iterator.previousIndex();
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ fireEvent();
+ }
+
+ @Override
+ public void set(T item) {
+ checkType(item);
+ iterator.set(item);
+ fireEvent();
+ }
+ };
+ }
+
+ @Override
+ public ListIterator<T> listIterator(int index) {
+ return delegate.listIterator(index);
+ }
+
+ @Override
+ public boolean remove(Object item) {
+ if (delegate.remove(item)) {
+ fireEvent();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public T remove(int index) {
+ T value = delegate.remove(index);
+ if (value == null) {
+ return null;
+ }
+ fireEvent();
+ return value;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> items) {
+ if (delegate.removeAll(items)) {
+ fireEvent();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> items) {
+ if (delegate.retainAll(items)) {
+ fireEvent();
+ return true;
+ }
+ return true;
+ }
+
+ @Override
+ public T set(int index, T item) {
+ T value = delegate.set(index, item);
+ fireEvent();
+ return value;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
+ return new CyListImpl<T>(elementType,
delegate.subList(fromIndex, toIndex), eventHelper, row, column);
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public <S> S[] toArray(S[] container) {
+ return (S[]) delegate.toArray(container);
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+}
Modified:
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyTableImpl.java
===================================================================
---
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyTableImpl.java
2012-09-18 17:56:27 UTC (rev 30376)
+++
core3/impl/trunk/model-impl/impl/src/main/java/org/cytoscape/model/internal/CyTableImpl.java
2012-09-18 19:05:12 UTC (rev 30377)
@@ -55,14 +55,13 @@
import org.cytoscape.model.events.TableAddedListener;
import org.cytoscape.model.events.TablePrivacyChangedEvent;
import org.cytoscape.model.events.TableTitleChangedEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
-import com.google.common.collect.HashMultimap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public final class CyTableImpl implements CyTable, TableAddedListener {
private static final Logger logger =
LoggerFactory.getLogger(CyTableImpl.class);
@@ -671,54 +670,63 @@
private void setListX(final Object key, final String columnName, final
Object value) {
Object newValue;
-
+ final Object rawValue;
+
+
synchronized(this) {
final String normalizedColName =
normalizeColumnName(columnName);
+ final CyColumn column = types.get(normalizedColName);
+ CyRow row = rows.get(key);
+ final Class<?> type = column.getListElementType();
- if (value instanceof List) {
+ if (value instanceof CyListImpl) {
+ rawValue = value;
+ } else if (value instanceof List) {
final List list = (List)value;
if (!list.isEmpty())
checkType(list.get(0));
+ rawValue = new CyListImpl(type, new
ArrayList(list), eventHelper, row, column);
} else if (!(value instanceof Equation)) {
throw new IllegalArgumentException("value is a
" + value.getClass().getName()
+ " and not
a List for column '"
+ columnName
+ "'.");
- } else if
(!EqnSupport.listEquationIsCompatible((Equation)value,
-
types.get(normalizedColName).getListElementType())) {
+ } else if
(!EqnSupport.listEquationIsCompatible((Equation)value, type)) {
throw new IllegalArgumentException(
"value is
not a List equation of a compatible type for column '"
+ columnName
+ "'.");
+ } else {
+ rawValue = value;
}
final VirtualColumn virtColumn =
virtualColumnMap.get(normalizedColName);
if (virtColumn != null) {
- virtColumn.setValue(key, value);
+ virtColumn.setValue(key, rawValue);
}
- if (virtColumn != null && !(value instanceof Equation))
{
+ if (virtColumn != null && !(rawValue instanceof
Equation)) {
newValue = virtColumn.getListValue(key);
} else {
Map<Object, Object> keyToValueMap =
attributes.get(normalizedColName);
// TODO this is an implicit addRow - not sure
if we want to refactor this or not
final Object oldValue = keyToValueMap.get(key);
- keyToValueMap.put(key, value);
- if (value instanceof Equation) {
+ keyToValueMap.put(key, rawValue);
+ if (rawValue instanceof Equation) {
final StringBuilder errorMsg = new
StringBuilder();
- newValue =
EqnSupport.evalEquation((Equation)value, suid, interpreter,
+ newValue =
EqnSupport.evalEquation((Equation)rawValue, suid, interpreter,
currentlyActiveAttributes, columnName,
errorMsg, this);
lastInternalError = errorMsg.toString();
} else {
- newValue = value;
- addToReverseMap(columnName, key,
oldValue, value);
+ newValue = rawValue;
+ addToReverseMap(columnName, key,
oldValue, rawValue);
}
}
}
if (fireEvents)
eventHelper.addEventPayload((CyTable)this,
- new
RowSetRecord(getRow(key),columnName,newValue, value),
+ new
RowSetRecord(getRow(key),columnName,newValue, rawValue),
RowsSetEvent.class);
}
Modified:
core3/impl/trunk/model-impl/impl/src/test/java/org/cytoscape/model/CyTableTest.java
===================================================================
---
core3/impl/trunk/model-impl/impl/src/test/java/org/cytoscape/model/CyTableTest.java
2012-09-18 17:56:27 UTC (rev 30376)
+++
core3/impl/trunk/model-impl/impl/src/test/java/org/cytoscape/model/CyTableTest.java
2012-09-18 19:05:12 UTC (rev 30377)
@@ -125,7 +125,7 @@
attrs.set("booleanList", new BooleanList());
final BooleanList nonEmptyList = new BooleanList(true, false);
attrs.set("booleanList", nonEmptyList);
- assertEquals(attrs.getList("booleanList", Boolean.class),
nonEmptyList);
+ assertListEquals(attrs.getList("booleanList", Boolean.class),
nonEmptyList);
}
//@Test : TODO: We removed support for strongly typed lists so this
test is
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.