From 2a37041c6da8864656e7217dbcc3d6dae8cd65be Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Thu, 23 Feb 2017 12:21:37 +0200 Subject: [PATCH] Generinc UpdateEditor refs #7045 Change-Id: Idad586011de488d6d188949b3817e10ac2633632 --- .../META-INF/MANIFEST.MF | 7 +- .../update/editor/ModelUpdateEditor.java | 770 ++++++++++++++++++ .../update/editor/UpdateEditorInput.java | 33 + .../interop/update/model/UpdateNode.java | 6 +- .../update/model/UpdateOperations.java | 2 +- .../interop/update/model/UpdateTree.java | 15 +- 6 files changed, 824 insertions(+), 9 deletions(-) create mode 100644 org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java create mode 100644 org.simantics.interop.update/src/org/simantics/interop/update/editor/UpdateEditorInput.java diff --git a/org.simantics.interop.update/META-INF/MANIFEST.MF b/org.simantics.interop.update/META-INF/MANIFEST.MF index 83657de..d0a0ca7 100644 --- a/org.simantics.interop.update/META-INF/MANIFEST.MF +++ b/org.simantics.interop.update/META-INF/MANIFEST.MF @@ -12,7 +12,10 @@ Require-Bundle: org.eclipse.ui, org.simantics.db.common;bundle-version="1.1.0", org.simantics.layer0;bundle-version="1.1.0", org.simantics.issues;bundle-version="1.1.0", - org.simantics.issues.common;bundle-version="1.1.0" + org.simantics.issues.common;bundle-version="1.1.0", + org.simantics.db.layer0;bundle-version="1.1.0", + org.simantics.ui;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy -Export-Package: org.simantics.interop.update.model +Export-Package: org.simantics.interop.update.editor, + org.simantics.interop.update.model diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java b/org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java new file mode 100644 index 0000000..a3b6033 --- /dev/null +++ b/org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java @@ -0,0 +1,770 @@ +package org.simantics.interop.update.editor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Stack; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxCellEditor; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.viewers.TreeViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorInput; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.DoesNotContainValueException; +import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; +import org.simantics.db.exception.NoSingleResultException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.request.Read; +import org.simantics.interop.test.GraphChanges; +import org.simantics.interop.test.GraphComparator; +import org.simantics.interop.test.NameComparator; +import org.simantics.interop.update.Activator; +import org.simantics.interop.update.model.UpdateNode; +import org.simantics.interop.update.model.UpdateNode.Status; +import org.simantics.interop.update.model.UpdateTree; +import org.simantics.interop.utils.TableUtils; +import org.simantics.layer0.Layer0; +import org.simantics.ui.workbench.ResourceEditorPart2; +import org.simantics.utils.datastructures.BijectionMap; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.ui.ExceptionUtils; + + +/** + * Editor for updating models. + * + * @author Marko Luukkainen + * + */ +public abstract class ModelUpdateEditor extends ResourceEditorPart2 { + + + private Composite composite; + private Composite errorComposite; + + private CheckboxTreeViewer changeBrowser; + private TableViewer changeViewer; + + private GraphChanges changes; + private UpdateTree updateTree; + + private Button updateAllButton; + private Button updateSelectedButton; + + private LocalResourceManager manager = new LocalResourceManager(JFaceResources.getResources()); + + private Image checked; + private Image unchecked; + private Image warning; + + private Color containsColor; + private Color deletedColor; + private Color addedColor; + + private HashSet> selected = new HashSet>(); + + private HashSet selectedStructure = new HashSet(); + + private List filters = new ArrayList(); + + public ModelUpdateEditor() { + checked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/tick.png")); + unchecked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/cross.png")); + warning = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/error.png")); + } + + @Override + public void createPartControl(Composite parent) { + + containsColor = new Color(parent.getDisplay(), new RGB(255,255,220)); + deletedColor = new Color(parent.getDisplay(), new RGB(255,220,220)); + addedColor = new Color(parent.getDisplay(), new RGB(220,255,220)); + + composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(1,false)); + + errorComposite = new Composite(composite, SWT.BORDER); + GridData data = new GridData(); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = false; + data.horizontalAlignment = SWT.FILL; + data.verticalAlignment = SWT.TOP; + errorComposite.setLayoutData(data); + errorComposite.setLayout(new GridLayout(2, false)); + + errorComposite.setVisible(false); + + IEditorInput input = getEditorInput(); + if (!(input instanceof UpdateEditorInput)) { + Label label = new Label(composite, SWT.NONE); + label.setText("Unknown input."); + return; + } + + Composite fillComposite = new Composite(composite, SWT.NONE); + data = new GridData(); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + data.horizontalAlignment = SWT.FILL; + data.verticalAlignment = SWT.FILL; + fillComposite.setLayoutData(data); + fillComposite.setLayout(new FillLayout(SWT.VERTICAL)); + + { + changeBrowser = new CheckboxTreeViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION ); + + changeBrowser.setContentProvider(new UpdateTreeContentProvider()); + + changeBrowser.getTree().setHeaderVisible(true); + + ColumnViewerToolTipSupport.enableFor(changeBrowser); + + + TreeViewerColumn dataColumn = TableUtils.addColumn(changeBrowser, "Data", true, 600); + + dataColumn.setLabelProvider(new UpdateNodeLabelProvicer()); + + changeBrowser.addCheckStateListener(new ICheckStateListener() { + + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + UpdateNode node = (UpdateNode) event.getElement(); + if (node.getOp() != null) { + node.getOp().select(Boolean.TRUE.equals(event.getChecked())); + + } + updateSelection(); + + } + }); + changeBrowser.addTreeListener(new ITreeViewerListener() { + + @Override + public void treeExpanded(TreeExpansionEvent event) { + event.getTreeViewer().getControl().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + updateSelection(); + } + }); + + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + + } + }); + changeBrowser.setUseHashlookup(true); + + } + { + changeViewer = new TableViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION); + + changeViewer.getTable().setHeaderVisible(true); + changeViewer.getTable().setLinesVisible(true); + + changeViewer.setContentProvider(new ModificationListContentProvider()); + + changeViewer.setUseHashlookup(true); + + TableViewerColumn selection = TableUtils.addColumn(changeViewer, getColumntTitle(0), false, false, 20); + TableViewerColumn diagram = TableUtils.addColumn(changeViewer, getColumntTitle(1), true, true, 100); + TableViewerColumn symbol = TableUtils.addColumn(changeViewer, getColumntTitle(2), true, true, 100); + TableViewerColumn property = TableUtils.addColumn(changeViewer, getColumntTitle(3), true, true, 100); + TableViewerColumn oldValue = TableUtils.addColumn(changeViewer, getColumntTitle(4), true, true, 100); + TableViewerColumn newValue = TableUtils.addColumn(changeViewer, getColumntTitle(5), true, true, 100); + + diagram.setLabelProvider(getLabelProvider(1)); + symbol.setLabelProvider(getLabelProvider(2)); + property.setLabelProvider(getLabelProvider(3)); + oldValue.setLabelProvider(getLabelProvider(4)); + newValue.setLabelProvider(getLabelProvider(5)); + + selection.setLabelProvider(new SelectionLabelProvider(selected)); + selection.getColumn().addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (changes.getModifications().size() > 0) { + if (selected.contains(changes.getModifications().get(0))) { + for (Pair nr : changes.getModifications()) + selected.remove(nr); + } else { + for (Pair nr : changes.getModifications()) + selected.add(nr); + } + changeViewer.refresh(); + } + } + }); + selection.setEditingSupport(new SelectionEditingSupport(changeViewer, selected)); + + } + Composite buttonComposite = new Composite(composite, SWT.NONE); + + data = new GridData(); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = false; + data.horizontalAlignment = SWT.FILL; + data.verticalAlignment = SWT.BOTTOM; + + buttonComposite.setLayoutData(data); + + buttonComposite.setLayout(new GridLayout(3, false)); + + Label label = new Label(buttonComposite, SWT.NONE); + data = new GridData(); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = false; + data.horizontalAlignment = SWT.FILL; + data.verticalAlignment = SWT.CENTER; + label.setLayoutData(data); + + updateAllButton = new Button(buttonComposite, SWT.PUSH); + updateAllButton.setText("Update All"); + updateAllButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + updateAll(); + } + }); + updateSelectedButton = new Button(buttonComposite, SWT.PUSH); + updateSelectedButton.setText("Update Selected"); + updateSelectedButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + updateSelected(); + } + }); + + load(); + + } + + protected String getColumntTitle(int i) { + switch (i) { + case 0: + return "!"; + case 1: + return "Diagram"; + case 2: + return "Symbol"; + case 3: + return "Property"; + case 4: + return "Old Value"; + case 5: + return "New Value"; + default: + throw new RuntimeException("Unknown column index" + i); + + } + } + + protected abstract ColumnLabelProvider getLabelProvider(int i); + protected abstract Pair getChanges(Resource r1, Resource r2) throws DatabaseException; + protected abstract UpdateTree getUpdateTree(GraphChanges changes) throws DatabaseException; + + protected void addFilters(List filters) { + + } + + public GraphChanges getChanges() { + return changes; + } + + private void showWarning(String text) { + errorComposite.setVisible(true); + + Label label = new Label(errorComposite, SWT.NONE); + label.setImage(warning); + label = new Label(errorComposite, SWT.NONE); + label.setText(text); + //this.setStatusMessage("Update contains structural changes (new or deleted symbols), please create a new model."); + composite.layout(true); + + } + + private void updateSelection() { + Stack nodeStack = new Stack(); + nodeStack.push((UpdateNode)updateTree.getRootNode()); + while (!nodeStack.isEmpty()) { + UpdateNode n = nodeStack.pop(); + if (n.getOp() != null) { + boolean applied = n.getOp().applied(); + if (applied) { + changeBrowser.setChecked(n, true); + changeBrowser.setGrayed(n, true); + selectedStructure.remove(n); + } else { + boolean sel = n.getOp().selected(); + if (sel) { + selectedStructure.add(n); + + } else { + selectedStructure.remove(n); + } + changeBrowser.setChecked(n, sel); + changeBrowser.setGrayed(n, false); + } + } else { + changeBrowser.setGrayed(n, true); + changeBrowser.setChecked(n, true); + } + for (UpdateNode c : n.getChildren()) { + nodeStack.add((UpdateNode)c); + } + } + + changeBrowser.refresh(); + } + + + + private void load() { + + addFilters(filters); + + UpdateEditorInput uei = (UpdateEditorInput)getEditorInput(); + Resource r1 = uei.getR1(); + Resource r2 = uei.getR2(); + + + try { + + Pair result = getChanges(r1,r2); + GraphComparator comparator = result.first; + if (result.second) + showWarning("Structural symbols have been changed. Model update is not able to update these, please create a new model."); + comparator.test(getSession()); + changes = comparator.getChanges(); + changes = getSession().syncRequest(new FilterChangesRead(changes)); + updateTree = getUpdateTree(changes); + } catch (DatabaseException e) { + Text text = new Text(composite, SWT.MULTI); + text.setText(e.getMessage()); + e.printStackTrace(); + return; + } + + + + changeViewer.setInput(changes.getModifications()); + changeBrowser.setInput(updateTree); + updateSelection(); + } + + + + private void updateAll() { + updateAllButton.setEnabled(false); + updateSelectedButton.setEnabled(false); + getSession().asyncRequest(new WriteRequest(){ + @Override + public void perform(WriteGraph graph) throws DatabaseException { + for (Pair mod : changes.getModifications()) { + applyLiteralChange(graph, mod); + } + selected.clear(); + changes.getModifications().clear(); + + updateTree.getUpdateOps().applyAll(graph); + + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + + updateAllButton.setEnabled(true); + updateSelectedButton.setEnabled(true); + updateSelection(); + changeViewer.refresh(); + } + }); + } + + + }, new Callback() { + @Override + public void run(DatabaseException parameter) { + if (parameter != null) + ExceptionUtils.logAndShowError("Cannot update model", parameter); + } + }); + } + + private void applyLiteralChange(WriteGraph graph, Pair mod) throws DoesNotContainValueException, ServiceException, ManyObjectsForFunctionalRelationException { + + Resource s = changes.getComparable().getLeft(mod.second.getSubject()); + Resource pred = mod.first.getPredicate(); + if (graph.hasValue(mod.second.getObject())) { + Object value = graph.getValue(mod.second.getObject()); + graph.claimLiteral(s, pred, value); + } else { + graph.deny(s,pred); + } + + + } + + private void updateSelected() { + updateAllButton.setEnabled(false); + updateSelectedButton.setEnabled(false); + getSession().asyncRequest(new WriteRequest(){ + @Override + public void perform(WriteGraph graph) throws DatabaseException { + for (Pair mod : selected) { + changes.getModifications().remove(mod); + applyLiteralChange(graph, mod); + } + selected.clear(); + + updateTree.getUpdateOps().applySelected(graph); + + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + changeViewer.refresh(); + updateAllButton.setEnabled(true); + updateSelectedButton.setEnabled(true); + updateSelection(); + } + }); + } + }); + } + + @Override + public void setFocus() { + composite.setFocus(); + + } + + /** + * Filters changes: + * 1. Changes that are not essential for model update (changes that can be found when the models are axcatly the same) + * 2. Runs custom filters for value changes. + * + * @param g + * @param changes + * @return + * @throws DatabaseException + */ + protected GraphChanges filterChanges(ReadGraph g, GraphChanges changes) throws DatabaseException + { + + List> modifications = new ArrayList>(); + + for (Pair mod : changes.getModifications()) { + + boolean accept = true; + for (ChangeFilter filter : filters) { + if (!filter.accept(g, mod)) { + accept = false; + break; + } + } + if (accept) + modifications.add(mod); + } + GraphChanges newChanges = new GraphChanges(changes.getResource1(),changes.getResource2(),changes.getDeletions(), changes.getAdditions(), modifications, changes.getComparable()); + return newChanges; + } + + public interface ChangeFilter { + public boolean accept(ReadGraph g, Pair change) throws DatabaseException; + } + + + + + /** + * + * Filters floating point value changes (default filter is set filter when the change is less than 1%) + * + */ + protected class FPValueFilter implements ChangeFilter { + + private double percentage = 0.01; + + public FPValueFilter() { + + } + + public FPValueFilter(double percentage) { + if (percentage < 0.0 || percentage > 1.0) + throw new IllegalArgumentException("Percentage must be between 0.0 and 1.0."); + this.percentage = percentage; + } + + @Override + public boolean accept(ReadGraph g, Pair change) throws DatabaseException { + //filter floating point values that have less than 1% difference. + if (!g.hasValue(change.first.getObject()) || !g.hasValue(change.second.getObject())) + return true; + Object v1 = g.getValue(change.first.getObject()); + Object v2 = g.getValue(change.second.getObject()); + + if (v1 instanceof Double && v2 instanceof Double) { + double d1 = (Double)v1; + double d2 = (Double)v2; + if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage) + return false; + } else if (v1 instanceof Float && v2 instanceof Float) { + float d1 = (Float)v1; + float d2 = (Float)v2; + if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage) + return false; + } + + return true; + } + } + + + private class FilterChangesRead implements Read { + private GraphChanges changes; + public FilterChangesRead(GraphChanges changes) { + this.changes = changes; + } + + @Override + public GraphChanges perform(ReadGraph graph) throws DatabaseException { + return filterChanges(graph, changes); + } + } + + + private class ModificationListContentProvider implements IStructuredContentProvider { + + @SuppressWarnings("unchecked") + @Override + public Object[] getElements(Object inputElement) { + if (inputElement == null) + return null; + Collection> coll = (Collection>)inputElement; + return coll.toArray(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + @Override + public void dispose() { + + } + } + + private class UpdateTreeContentProvider implements ITreeContentProvider { + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof UpdateTree) + return new Object[]{((UpdateTree)inputElement).getRootNode()}; + if (inputElement instanceof UpdateNode) { + UpdateNode node = (UpdateNode)inputElement; + return node.getChildren().toArray(); + } + return new Object[0]; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public Object[] getChildren(Object parentElement) { + UpdateNode node = (UpdateNode)parentElement; + return node.getChildren().toArray(); + } + + @Override + public boolean hasChildren(Object element) { + UpdateNode node = (UpdateNode)element; + return node.getChildren().size() > 0; + } + + @Override + public void dispose() { + + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + } + + private class SelectionLabelProvider extends ColumnLabelProvider { + + Collection selected; + public SelectionLabelProvider(Collection selected) { + this.selected = selected; + } + @Override + public String getText(Object element) { + return ""; + } + + @Override + public Image getImage(Object element) { + if (selected.contains(element)) + return checked; + else + return unchecked; + } + } + + private class UpdateNodeLabelProvicer extends ColumnLabelProvider { + + @Override + public String getText(Object element) { + final UpdateNode node = (UpdateNode)element; + try { + return getSession().syncRequest(new Read() { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + return node.getLabel(graph); + } + }); + } catch (Exception e) { + return e.getMessage(); + } + } + + @Override + public Image getImage(Object element) { + final UpdateNode node = (UpdateNode)element; + try { + ImageDescriptor id = getSession().syncRequest(new Read() { + @Override + public ImageDescriptor perform(ReadGraph graph) throws DatabaseException { + return node.getImage(graph); + } + }); + return manager.createImage(id); + } catch (Exception e) { + return null; + } + } + + @Override + public String getToolTipText(Object element) { + final UpdateNode node = (UpdateNode)element; + if (node.getOp() != null) { + return node.getOp().toString(); + } else { + return null; + } + } + + @Override + public int getToolTipDisplayDelayTime(Object object) { + return 1000; + } + + @Override + public int getToolTipTimeDisplayed(Object object) { + return 10000; + } + + @Override + public Color getBackground(Object element) { + final UpdateNode node = (UpdateNode)element; + Status status = node.getStatus(); + if (status == Status.CONTAINS) + return containsColor; + if (status == Status.DELETED) + return deletedColor; + if (status == Status.NEW) + return addedColor; + return null; + } + } + + private class SelectionEditingSupport extends EditingSupport { + + @SuppressWarnings("rawtypes") + Collection selected; + + + @SuppressWarnings("rawtypes") + public SelectionEditingSupport(ColumnViewer viewer, Collection selected) { + super(viewer); + this.selected = selected; + + } + + @Override + protected boolean canEdit(Object element) { + return true; + } + + @Override + protected CellEditor getCellEditor(Object element) { + return new CheckboxCellEditor(null, SWT.CHECK); + } + + @Override + protected Object getValue(Object element) { + return selected.contains(element); + } + + @SuppressWarnings("unchecked") + @Override + protected void setValue(Object element, Object value) { + if (Boolean.TRUE.equals(value)) + selected.add(element); + else + selected.remove(element); + + getViewer().refresh(element); + } + + + } + + +} diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/editor/UpdateEditorInput.java b/org.simantics.interop.update/src/org/simantics/interop/update/editor/UpdateEditorInput.java new file mode 100644 index 0000000..f91f659 --- /dev/null +++ b/org.simantics.interop.update/src/org/simantics/interop/update/editor/UpdateEditorInput.java @@ -0,0 +1,33 @@ +package org.simantics.interop.update.editor; + +import org.simantics.db.Resource; +import org.simantics.db.layer0.variable.RVI; +import org.simantics.ui.workbench.ResourceEditorInput2; + +/** + * Editor input for ModelUpdateEditor + * + * @author Marko Luukkainen + * + */ +public class UpdateEditorInput extends ResourceEditorInput2{ + + private Resource r1; + private Resource r2; + + public UpdateEditorInput(String editorID, Resource r1, Resource r2, Resource model, RVI rvi) { + super(editorID, r1, model, rvi); + this.r1 = r1; + this.r2 = r2; + } + + public Resource getR1() { + return r1; + } + + public Resource getR2() { + return r2; + } + + +} diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java index e1312bf..da78b90 100644 --- a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java +++ b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java @@ -13,7 +13,7 @@ import org.simantics.db.exception.ServiceException; import org.simantics.db.exception.ValidationException; import org.simantics.layer0.Layer0; -public abstract class UpdateNode { +public class UpdateNode { public enum Status {EXIST,DELETED,NEW,CONTAINS}; @@ -69,7 +69,9 @@ public abstract class UpdateNode { children.add(node); } - public abstract ImageDescriptor getImage(ReadGraph graph) throws DatabaseException; + public ImageDescriptor getImage(ReadGraph graph) throws DatabaseException { + return null; + } public String getLabel(ReadGraph graph) throws DatabaseException { return getLabel(graph,r); diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java index 74acf18..9c929c5 100644 --- a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java +++ b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java @@ -92,7 +92,7 @@ public abstract class UpdateOperations { protected void replaceOp(Resource r, UpdateOp op) { UpdateOp oldOp = opMap.remove(r); if (oldOp != null) { - operations.remove(op); + operations.remove(oldOp); } opMap.put(r, op); operations.add(op); diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java index b7a2c4b..d06d706 100644 --- a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java +++ b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java @@ -10,7 +10,7 @@ import org.simantics.interop.test.GraphChanges; import org.simantics.interop.update.model.UpdateNode.Status; -public abstract class UpdateTree { +public class UpdateTree { private UpdateNode rootNode; private Map nodes; @@ -37,8 +37,13 @@ public abstract class UpdateTree { return rootNode; } - protected abstract UpdateNode createNode(Status status, Resource r); - protected abstract UpdateNode createNode(Status status, UpdateOp op); + protected UpdateNode createNode(Status status, Resource r) { + return new UpdateNode(status, r); + } + + protected UpdateNode createNode(Status status, UpdateOp op) { + return new UpdateNode(status, op); + } private UpdateNode createNode(Resource r1, Resource r2) { UpdateNode node = null; @@ -95,7 +100,9 @@ public abstract class UpdateTree { } } - protected abstract boolean handleCustom(ReadGraph g, UpdateOp op) throws DatabaseException; + protected boolean handleCustom(ReadGraph g, UpdateOp op) throws DatabaseException { + return false; + } private void populate(ReadGraph g) throws DatabaseException{ -- 2.47.1