提交 8e0cf5eb 编写于 作者: E Eduardo Ramos

More fixes for correct dynamic index updates due to attribute events.

上级 d818ed3c
...@@ -41,6 +41,8 @@ Portions Copyrighted 2011 Gephi Consortium. ...@@ -41,6 +41,8 @@ Portions Copyrighted 2011 Gephi Consortium.
*/ */
package org.gephi.data.attributes.api; package org.gephi.data.attributes.api;
import org.gephi.project.api.Workspace;
/** /**
* Represents the data model, like a standard database would do. As a database, * Represents the data model, like a standard database would do. As a database,
* contains a list of tables, where columns are defined. By default, a model * contains a list of tables, where columns are defined. By default, a model
...@@ -147,4 +149,10 @@ public interface AttributeModel { ...@@ -147,4 +149,10 @@ public interface AttributeModel {
* @param model the model that is to be merged in this model * @param model the model that is to be merged in this model
*/ */
public void mergeModel(AttributeModel model); public void mergeModel(AttributeModel model);
/**
* Returns the workspace this Attribute model belongs to.
* @return the workspace that owns this Attribute model or null if it is independent from a Workspace
*/
public Workspace getWorkspace();
} }
...@@ -66,6 +66,8 @@ public abstract class AttributeUtils { ...@@ -66,6 +66,8 @@ public abstract class AttributeUtils {
public abstract boolean isEdgeColumn(AttributeColumn column); public abstract boolean isEdgeColumn(AttributeColumn column);
public abstract boolean isGraphColumn(AttributeColumn column);
public abstract boolean isColumnOfType(AttributeColumn column, AttributeType type); public abstract boolean isColumnOfType(AttributeColumn column, AttributeType type);
public abstract boolean areAllColumnsOfType(AttributeColumn[] columns, AttributeType type); public abstract boolean areAllColumnsOfType(AttributeColumn[] columns, AttributeType type);
......
...@@ -52,6 +52,7 @@ import org.gephi.data.attributes.api.AttributeValueFactory; ...@@ -52,6 +52,7 @@ import org.gephi.data.attributes.api.AttributeValueFactory;
import org.gephi.data.attributes.event.AbstractEvent; import org.gephi.data.attributes.event.AbstractEvent;
import org.gephi.data.attributes.event.AttributeEventManager; import org.gephi.data.attributes.event.AttributeEventManager;
import org.gephi.data.properties.PropertiesColumn; import org.gephi.data.properties.PropertiesColumn;
import org.gephi.project.api.Workspace;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
/** /**
...@@ -61,6 +62,7 @@ import org.openide.util.NbBundle; ...@@ -61,6 +62,7 @@ import org.openide.util.NbBundle;
*/ */
public abstract class AbstractAttributeModel implements AttributeModel { public abstract class AbstractAttributeModel implements AttributeModel {
private final Workspace workspace;
//Classes //Classes
private final ConcurrentMap<String, AttributeTableImpl> tableMap; private final ConcurrentMap<String, AttributeTableImpl> tableMap;
private final AttributeTableImpl nodeTable; private final AttributeTableImpl nodeTable;
...@@ -72,7 +74,8 @@ public abstract class AbstractAttributeModel implements AttributeModel { ...@@ -72,7 +74,8 @@ public abstract class AbstractAttributeModel implements AttributeModel {
protected AttributeEventManager eventManager; protected AttributeEventManager eventManager;
//Data API //Data API
public AbstractAttributeModel() { public AbstractAttributeModel(Workspace workspace) {
this.workspace = workspace;
tableMap = new ConcurrentHashMap<String, AttributeTableImpl>(); tableMap = new ConcurrentHashMap<String, AttributeTableImpl>();
nodeTable = new AttributeTableImpl(this, NbBundle.getMessage(AttributeTableImpl.class, "NodeAttributeTable.name")); nodeTable = new AttributeTableImpl(this, NbBundle.getMessage(AttributeTableImpl.class, "NodeAttributeTable.name"));
edgeTable = new AttributeTableImpl(this, NbBundle.getMessage(AttributeTableImpl.class, "EdgeAttributeTable.name")); edgeTable = new AttributeTableImpl(this, NbBundle.getMessage(AttributeTableImpl.class, "EdgeAttributeTable.name"));
...@@ -185,4 +188,8 @@ public abstract class AbstractAttributeModel implements AttributeModel { ...@@ -185,4 +188,8 @@ public abstract class AbstractAttributeModel implements AttributeModel {
} }
} }
} }
public Workspace getWorkspace(){
return this.workspace;
}
} }
...@@ -46,9 +46,9 @@ import org.gephi.data.attributes.api.AttributeModel; ...@@ -46,9 +46,9 @@ import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.data.attributes.model.IndexedAttributeModel; import org.gephi.data.attributes.model.IndexedAttributeModel;
import org.gephi.data.attributes.model.TemporaryAttributeModel; import org.gephi.data.attributes.model.TemporaryAttributeModel;
import org.gephi.project.api.ProjectController; import org.gephi.project.api.ProjectController;
import org.gephi.project.api.WorkspaceProvider;
import org.gephi.project.api.Workspace; import org.gephi.project.api.Workspace;
import org.gephi.project.api.WorkspaceListener; import org.gephi.project.api.WorkspaceListener;
import org.gephi.project.api.WorkspaceProvider;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
...@@ -68,7 +68,7 @@ public class AttributeControllerImpl implements AttributeController { ...@@ -68,7 +68,7 @@ public class AttributeControllerImpl implements AttributeController {
public void initialize(Workspace workspace) { public void initialize(Workspace workspace) {
AttributeModel m = workspace.getLookup().lookup(AttributeModel.class); AttributeModel m = workspace.getLookup().lookup(AttributeModel.class);
if (m == null) { if (m == null) {
workspace.add(new IndexedAttributeModel()); workspace.add(new IndexedAttributeModel(workspace));
} }
} }
...@@ -88,7 +88,7 @@ public class AttributeControllerImpl implements AttributeController { ...@@ -88,7 +88,7 @@ public class AttributeControllerImpl implements AttributeController {
for (Workspace workspace : projectController.getCurrentProject().getLookup().lookup(WorkspaceProvider.class).getWorkspaces()) { for (Workspace workspace : projectController.getCurrentProject().getLookup().lookup(WorkspaceProvider.class).getWorkspaces()) {
AttributeModel m = workspace.getLookup().lookup(AttributeModel.class); AttributeModel m = workspace.getLookup().lookup(AttributeModel.class);
if (m == null) { if (m == null) {
workspace.add(new IndexedAttributeModel()); workspace.add(new IndexedAttributeModel(workspace));
} }
} }
} }
...@@ -101,7 +101,7 @@ public class AttributeControllerImpl implements AttributeController { ...@@ -101,7 +101,7 @@ public class AttributeControllerImpl implements AttributeController {
if (model != null) { if (model != null) {
return model; return model;
} }
model = new IndexedAttributeModel(); model = new IndexedAttributeModel(workspace);
workspace.add(model); workspace.add(model);
return model; return model;
} }
...@@ -113,13 +113,13 @@ public class AttributeControllerImpl implements AttributeController { ...@@ -113,13 +113,13 @@ public class AttributeControllerImpl implements AttributeController {
if (model != null) { if (model != null) {
return model; return model;
} }
model = new IndexedAttributeModel(); model = new IndexedAttributeModel(workspace);
workspace.add(model); workspace.add(model);
return model; return model;
} }
public AttributeModel newModel() { public AttributeModel newModel() {
TemporaryAttributeModel model = new TemporaryAttributeModel(); TemporaryAttributeModel model = new TemporaryAttributeModel(null);
return model; return model;
} }
} }
...@@ -70,11 +70,16 @@ public class AttributeRowImpl implements AttributeRow { ...@@ -70,11 +70,16 @@ public class AttributeRowImpl implements AttributeRow {
public void reset() { public void reset() {
rowVersion = attributeTable.getVersion(); rowVersion = attributeTable.getVersion();
int attSize = attributeTable.countColumns(); int attSize = attributeTable.countColumns();
AttributeValueImpl[] newValues = new AttributeValueImpl[attSize];
if (values == null) {
values = new AttributeValueImpl[attSize];
} else {
updateColumns();
}
for (int i = 0; i < attSize; i++) { for (int i = 0; i < attSize; i++) {
newValues[i] = attributeTable.getColumn(i).defaultValue; setValue(i, attributeTable.getColumn(i).defaultValue, false);
} }
this.values = newValues;
} }
public void setValues(AttributeRow attributeRow) { public void setValues(AttributeRow attributeRow) {
...@@ -133,17 +138,19 @@ public class AttributeRowImpl implements AttributeRow { ...@@ -133,17 +138,19 @@ public class AttributeRowImpl implements AttributeRow {
value = attributeTable.getFactory().newValue(column, value.getValue()); value = attributeTable.getFactory().newValue(column, value.getValue());
} }
setValue(column.getIndex(), (AttributeValueImpl) value); setValue(column.getIndex(), (AttributeValueImpl) value, true);
} }
private void setValue(int index, AttributeValueImpl value) { private void setValue(int index, AttributeValueImpl value, boolean doUpdateColumns) {
if (doUpdateColumns) {
updateColumns(); updateColumns();
}
AttributeValueImpl oldValue = this.values[index]; AttributeValueImpl oldValue = this.values[index];
this.values[index] = value; this.values[index] = value;
if (!((oldValue == null && value == null) || (oldValue != null && oldValue.equals(value))) if (!(oldValue != null && oldValue.equals(value))
&& index > 0 && !value.getColumn().getOrigin().equals(AttributeOrigin.COMPUTED)) { //0 is the index of node id and edge id cols, not useful to send these events && index > 0 && !value.getColumn().getOrigin().equals(AttributeOrigin.COMPUTED)) { //0 is the index of node id and edge id cols, not useful to send these events
if (oldValue != null) { if (oldValue != null) {
attributeTable.model.fireAttributeEvent(new ValueEvent(EventType.UNSET_VALUE, attributeTable, object, oldValue)); attributeTable.model.fireAttributeEvent(new ValueEvent(EventType.UNSET_VALUE, attributeTable, object, oldValue));
...@@ -211,27 +218,32 @@ public class AttributeRowImpl implements AttributeRow { ...@@ -211,27 +218,32 @@ public class AttributeRowImpl implements AttributeRow {
} }
private void updateColumns() { private void updateColumns() {
int tableVersion = attributeTable.getVersion(); int tableVersion = attributeTable.getVersion();
if (rowVersion < tableVersion) { if (rowVersion < tableVersion) {
//Need to update //Need to update
AttributeColumnImpl[] columns = attributeTable.getColumns(); AttributeColumnImpl[] columns = attributeTable.getColumns();
AttributeValueImpl[] newValues = new AttributeValueImpl[columns.length]; AttributeValueImpl[] oldValues = values;
values = new AttributeValueImpl[columns.length];
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
AttributeColumnImpl tableCol = columns[i]; AttributeColumnImpl tableCol = columns[i];
newValues[i] = tableCol.defaultValue; boolean found = false;
int j = 0; int j = 0;
while (j < values.length) { while (j < oldValues.length) {
AttributeValueImpl val = values[j++]; AttributeValueImpl val = oldValues[j++];
if (val.getColumn() == tableCol) { if (val.getColumn() == tableCol) {
newValues[i] = val; values[i] = val;
found = true;
break; break;
} }
} }
if (!found) {
setValue(i, tableCol.defaultValue, false);
}
} }
values = newValues;
//Upd version //Upd version
rowVersion = tableVersion; rowVersion = tableVersion;
......
...@@ -52,10 +52,17 @@ import org.gephi.data.attributes.api.AttributeEvent; ...@@ -52,10 +52,17 @@ import org.gephi.data.attributes.api.AttributeEvent;
import org.gephi.data.attributes.api.AttributeOrigin; import org.gephi.data.attributes.api.AttributeOrigin;
import org.gephi.data.attributes.api.AttributeTable; import org.gephi.data.attributes.api.AttributeTable;
import org.gephi.data.attributes.api.AttributeType; import org.gephi.data.attributes.api.AttributeType;
import org.gephi.data.attributes.api.AttributeUtils;
import org.gephi.data.attributes.event.ColumnEvent; import org.gephi.data.attributes.event.ColumnEvent;
import org.gephi.data.attributes.spi.AttributeValueDelegateProvider; import org.gephi.data.attributes.spi.AttributeValueDelegateProvider;
import org.gephi.data.attributes.type.TypeConvertor; import org.gephi.data.attributes.type.TypeConvertor;
import org.gephi.data.properties.PropertiesColumn; import org.gephi.data.properties.PropertiesColumn;
import org.gephi.graph.api.Attributes;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Node;
import org.openide.util.Lookup;
/** /**
* *
...@@ -116,7 +123,7 @@ public class AttributeTableImpl implements AttributeTable { ...@@ -116,7 +123,7 @@ public class AttributeTableImpl implements AttributeTable {
throw new IllegalArgumentException("The column id can't be null, empty or already existing in the table"); throw new IllegalArgumentException("The column id can't be null, empty or already existing in the table");
} }
if(title == null || title.isEmpty() || hasColumn(title)){ if (title == null || title.isEmpty() || hasColumn(title)) {
//The id is correct, but the title may be invalid or repeated even when the id is valid //The id is correct, but the title may be invalid or repeated even when the id is valid
//Use id as title as a compromise so the column can still be added: //Use id as title as a compromise so the column can still be added:
...@@ -151,12 +158,58 @@ public class AttributeTableImpl implements AttributeTable { ...@@ -151,12 +158,58 @@ public class AttributeTableImpl implements AttributeTable {
return column; return column;
} }
/**
* Sends unset events for all attribute rows of a column that is going to be removed. (This is basically necessary to correctly update Dynamic index of Dynamic API.)
*
* Events are only sent for node, edge and graph table columns.
*
* @param column Column that is being removed
*/
private boolean sendUnsetValueEventsForRemovedColumn(AttributeColumn column) {
if (this.model.getWorkspace() == null) {
return false;
}
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel(this.model.getWorkspace());
Attributes[] rows;
if (AttributeUtils.getDefault().isNodeColumn(column)) {
Node[] nodes = graphModel.getGraph().getNodes().toArray();
rows = new Attributes[nodes.length];
for (int i = 0; i < nodes.length; i++) {
rows[i] = nodes[i].getAttributes();
}
} else if (AttributeUtils.getDefault().isEdgeColumn(column)) {
Edge[] edges = graphModel.getGraph().getEdges().toArray();
rows = new Attributes[edges.length];
for (int i = 0; i < edges.length; i++) {
rows[i] = edges[i].getAttributes();
}
} else if (AttributeUtils.getDefault().isGraphColumn(column)) {
rows = new Attributes[]{graphModel.getGraph().getAttributes()};
} else {
return false;
}
int columnIndex = column.getIndex();
for (Attributes row : rows) {
row.setValue(columnIndex, null);
}
return true;
}
public synchronized void removeColumn(AttributeColumn column) { public synchronized void removeColumn(AttributeColumn column) {
int index = columns.indexOf(column); int index = columns.indexOf(column);
if (index == -1) { if (index == -1) {
return; return;
} }
sendUnsetValueEventsForRemovedColumn(column);
//update indexes of the next columns of the one to delete: //update indexes of the next columns of the one to delete:
AttributeColumnImpl c; AttributeColumnImpl c;
for (index = index + 1; index < columns.size(); index++) { for (index = index + 1; index < columns.size(); index++) {
...@@ -183,6 +236,9 @@ public class AttributeTableImpl implements AttributeTable { ...@@ -183,6 +236,9 @@ public class AttributeTableImpl implements AttributeTable {
if (index == -1) { if (index == -1) {
return null; return null;
} }
sendUnsetValueEventsForRemovedColumn(source);
//Remove from collections //Remove from collections
columnsMap.remove(source.getId().toLowerCase()); columnsMap.remove(source.getId().toLowerCase());
if (source.getTitle() != null && !source.getTitle().equals(source.getId())) { if (source.getTitle() != null && !source.getTitle().equals(source.getId())) {
......
...@@ -250,6 +250,19 @@ public class AttributeUtilsImpl extends AttributeUtils { ...@@ -250,6 +250,19 @@ public class AttributeUtilsImpl extends AttributeUtils {
return false; return false;
} }
@Override
public boolean isGraphColumn(AttributeColumn column) {
if (column == null) {
throw new NullPointerException();
}
AttributeColumnImpl columnImpl = (AttributeColumnImpl) column;
AttributeTableImpl table = columnImpl.getTable();
if (table == table.getModel().getGraphTable()) {
return true;
}
return false;
}
@Override @Override
public AttributeColumn[] getNumberColumns(AttributeTable table) { public AttributeColumn[] getNumberColumns(AttributeTable table) {
List<AttributeColumn> res = new ArrayList<AttributeColumn>(); List<AttributeColumn> res = new ArrayList<AttributeColumn>();
......
...@@ -44,6 +44,7 @@ package org.gephi.data.attributes.model; ...@@ -44,6 +44,7 @@ package org.gephi.data.attributes.model;
import org.gephi.data.attributes.AbstractAttributeModel; import org.gephi.data.attributes.AbstractAttributeModel;
import org.gephi.data.attributes.api.AttributeType; import org.gephi.data.attributes.api.AttributeType;
import org.gephi.data.attributes.event.AttributeEventManager; import org.gephi.data.attributes.event.AttributeEventManager;
import org.gephi.project.api.Workspace;
/** /**
* *
...@@ -54,7 +55,8 @@ public class IndexedAttributeModel extends AbstractAttributeModel { ...@@ -54,7 +55,8 @@ public class IndexedAttributeModel extends AbstractAttributeModel {
protected DataIndex dataIndex; protected DataIndex dataIndex;
public IndexedAttributeModel() { public IndexedAttributeModel(Workspace workspace) {
super(workspace);
dataIndex = new DataIndex(); dataIndex = new DataIndex();
eventManager = new AttributeEventManager(this); eventManager = new AttributeEventManager(this);
createPropertiesColumn(); createPropertiesColumn();
......
...@@ -45,6 +45,7 @@ import org.gephi.data.attributes.AbstractAttributeModel; ...@@ -45,6 +45,7 @@ import org.gephi.data.attributes.AbstractAttributeModel;
import org.gephi.data.attributes.api.AttributeListener; import org.gephi.data.attributes.api.AttributeListener;
import org.gephi.data.attributes.api.AttributeType; import org.gephi.data.attributes.api.AttributeType;
import org.gephi.data.attributes.event.AbstractEvent; import org.gephi.data.attributes.event.AbstractEvent;
import org.gephi.project.api.Workspace;
/** /**
* Specific manager for temporary storing of attributes. This is typically used when new attributes are * Specific manager for temporary storing of attributes. This is typically used when new attributes are
...@@ -56,7 +57,8 @@ import org.gephi.data.attributes.event.AbstractEvent; ...@@ -56,7 +57,8 @@ import org.gephi.data.attributes.event.AbstractEvent;
*/ */
public class TemporaryAttributeModel extends AbstractAttributeModel { public class TemporaryAttributeModel extends AbstractAttributeModel {
public TemporaryAttributeModel() { public TemporaryAttributeModel(Workspace workspace) {
super(workspace);
createPropertiesColumn(); createPropertiesColumn();
} }
......
...@@ -73,7 +73,7 @@ public class AttributeModelPersistenceProvider implements WorkspacePersistencePr ...@@ -73,7 +73,7 @@ public class AttributeModelPersistenceProvider implements WorkspacePersistencePr
public void readXML(XMLStreamReader reader, Workspace workspace) { public void readXML(XMLStreamReader reader, Workspace workspace) {
IndexedAttributeModel model = workspace.getLookup().lookup(IndexedAttributeModel.class); IndexedAttributeModel model = workspace.getLookup().lookup(IndexedAttributeModel.class);
if (model == null) { if (model == null) {
model = new IndexedAttributeModel(); model = new IndexedAttributeModel(workspace);
workspace.add(model); workspace.add(model);
} }
AttributeModelSerializer serializer = new AttributeModelSerializer(); AttributeModelSerializer serializer = new AttributeModelSerializer();
......
...@@ -153,6 +153,9 @@ public class DynamicIndex { ...@@ -153,6 +153,9 @@ public class DynamicIndex {
public synchronized void clear() { public synchronized void clear() {
lowMap.clear(); lowMap.clear();
highMap.clear(); highMap.clear();
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MIN_CHANGED, model, getMin()));
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MAX_CHANGED, model, getMax()));
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.IS_DYNAMIC_GRAPH, model, Boolean.FALSE));
} }
public synchronized double getMin() { public synchronized double getMin() {
......
...@@ -270,15 +270,7 @@ public final class DynamicModelImpl implements DynamicModel { ...@@ -270,15 +270,7 @@ public final class DynamicModelImpl implements DynamicModel {
graphModel.addGraphListener(graphListener); graphModel.addGraphListener(graphListener);
} }
private void refresh() { private void indexNodeColumnsValues(AttributeColumn[] dynamicCols) {
timeIntervalIndex.clear();
for (AttributeColumn col : attributeModel.getNodeTable().getColumns()) {
if (col.getType().isDynamicType()) {
nodeDynamicColumns.add(col);
}
}
AttributeColumn[] dynamicCols = nodeDynamicColumns.toArray(new AttributeColumn[0]);
if (dynamicCols.length > 0) {
Graph graph = graphModel.getGraph(); Graph graph = graphModel.getGraph();
for (Node n : graph.getNodes()) { for (Node n : graph.getNodes()) {
Attributes attributeRow = n.getNodeData().getAttributes(); Attributes attributeRow = n.getNodeData().getAttributes();
...@@ -292,13 +284,8 @@ public final class DynamicModelImpl implements DynamicModel { ...@@ -292,13 +284,8 @@ public final class DynamicModelImpl implements DynamicModel {
} }
} }
} }
for (AttributeColumn col : attributeModel.getNodeTable().getColumns()) {
if (col.getType().isDynamicType()) { private void indexEdgeColumnsValues(AttributeColumn[] dynamicCols) {
edgeDynamicColumns.add(col);
}
}
dynamicCols = edgeDynamicColumns.toArray(new AttributeColumn[0]);
if (dynamicCols.length > 0) {
Graph graph = graphModel.getGraph(); Graph graph = graphModel.getGraph();
for (Edge e : graph.getEdges()) { for (Edge e : graph.getEdges()) {
Attributes attributeRow = e.getEdgeData().getAttributes(); Attributes attributeRow = e.getEdgeData().getAttributes();
...@@ -312,6 +299,25 @@ public final class DynamicModelImpl implements DynamicModel { ...@@ -312,6 +299,25 @@ public final class DynamicModelImpl implements DynamicModel {
} }
} }
} }
private void refresh() {
timeIntervalIndex.clear();
nodeDynamicColumns.clear();
edgeDynamicColumns.clear();
for (AttributeColumn col : attributeModel.getNodeTable().getColumns()) {
if (col.getType().isDynamicType()) {
nodeDynamicColumns.add(col);
}
}
indexNodeColumnsValues(nodeDynamicColumns.toArray(new AttributeColumn[0]));
for (AttributeColumn col : attributeModel.getNodeTable().getColumns()) {
if (col.getType().isDynamicType()) {
edgeDynamicColumns.add(col);
}
}
indexEdgeColumnsValues(edgeDynamicColumns.toArray(new AttributeColumn[0]));
} }
@Override @Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册