]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.common/src/org/simantics/db/common/UndoContextEx.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / UndoContextEx.java
index 516426dff1f280dd0f2c0076204147649fef839b..52fc94861cf1919237b2a5fc2f8956cd5d6dcb59 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.common;\r
-\r
-import gnu.trove.map.TLongObjectMap;\r
-import gnu.trove.map.hash.TLongObjectHashMap;\r
-\r
-import java.lang.ref.WeakReference;\r
-import java.util.ArrayDeque;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Deque;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.concurrent.CopyOnWriteArrayList;\r
-\r
-import org.simantics.db.Operation;\r
-import org.simantics.db.UndoContext;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.NoHistoryException;\r
-import org.simantics.db.service.ExternalOperation;\r
-import org.simantics.db.service.UndoRedoSupport;\r
-import org.simantics.db.service.UndoRedoSupport.ChangeListener;\r
-import org.simantics.utils.threads.ThreadUtils;\r
-\r
-public class UndoContextEx implements UndoContext {\r
-    private static class Weak {\r
-        private final WeakReference<UndoContext> reference;\r
-        Weak(UndoContext context) {\r
-            reference = new WeakReference<UndoContext>(context);\r
-        }\r
-        UndoContext get() {\r
-            return reference.get();\r
-        }\r
-    }\r
-    private static class Operations {\r
-        private final Deque<Operation> operationsQue = new ArrayDeque<Operation>();\r
-        private final TLongObjectMap<Operation> operationsMap = new TLongObjectHashMap<Operation>();\r
-        void addLast(Operation op) {\r
-            long id = op.getId();\r
-            Operation old = operationsMap.put(id, op);\r
-            if (old != null) {\r
-                operationsQue.remove(old);\r
-                op.combine(old);\r
-            }\r
-            operationsQue.addLast(op);\r
-            fireChangeEvent();\r
-        }\r
-        Operation getLast() {\r
-            if (operationsQue.size() < 1)\r
-                return null;\r
-            Operation op = operationsQue.getLast();\r
-            if (DEBUG)\r
-                System.out.println("DEBUG: Get last id=" + op.getId() + ".");\r
-            return op;\r
-        }\r
-        Collection<Operation> getAll() {\r
-            return operationsQue;\r
-        }\r
-        Operation getCombined(long id) {\r
-            return operationsMap.get(id);\r
-        }\r
-        Operation removeLast() {\r
-            Operation op = operationsQue.pollLast();\r
-            if (null != op)\r
-                operationsMap.remove(op.getId());\r
-            fireChangeEvent();\r
-            return op;\r
-        }\r
-        Operation remove(long id) {\r
-            Operation op = operationsMap.remove(id);\r
-            if (null != op)\r
-                operationsQue.remove(op);\r
-            fireChangeEvent();\r
-            return op;\r
-        }\r
-        void clear() {\r
-            operationsQue.clear();\r
-            operationsMap.clear();\r
-            fireChangeEvent();\r
-        }\r
-        private final CopyOnWriteArrayList<ChangeListener> changeListeners = new CopyOnWriteArrayList<ChangeListener>(); \r
-        private void fireChangeEvent() {\r
-            final Iterator<ChangeListener> it = changeListeners.iterator();\r
-            ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() {\r
-                @Override\r
-                public void run() {\r
-                    while (it.hasNext()) {\r
-                        ChangeListener l = it.next();\r
-                        try {\r
-                            l.onChanged();\r
-                        } catch (Throwable t) {\r
-                            Logger.defaultLogError(t);\r
-                        }\r
-                    }\r
-                }\r
-            });\r
-        }\r
-        void addChangeListener(ChangeListener cl) {\r
-            changeListeners.add(cl);\r
-        }\r
-        void removeChangeListener(ChangeListener cl) {\r
-            changeListeners.remove(cl);\r
-        }\r
-    }\r
-    private static HashMap<String, Weak> contexts = new HashMap<String, Weak>(); \r
-    protected static final boolean DEBUG = false;\r
-    protected final boolean DISABLED = false;\r
-    private final Operations operations = new Operations();\r
-    private final Deque<Operation> redos = new ArrayDeque<Operation>();\r
-    private final ArrayList<ExternalOperation> pendingExternals = new ArrayList<ExternalOperation>();\r
-    private final String name;\r
-    private boolean undoRedoOn = false;\r
-    private final String id;\r
-    private boolean commitOkDisabled = false;\r
-\r
-    public UndoContextEx() {\r
-        this.id = getUniqueId(this.toString());\r
-        this.name = id;\r
-        init();\r
-    }\r
-    public UndoContextEx(String id) {\r
-        this.id = getUniqueId(id);\r
-        this.name = id;\r
-        init();\r
-    }\r
-    public UndoContextEx(String id, String name) {\r
-        this.id = getUniqueId(id);\r
-        this.name = name;\r
-        init();\r
-    }\r
-    private String getUniqueId(String id) {\r
-        String uniqueId = id;\r
-        int i=0;\r
-        while (contexts.containsKey(uniqueId)) {\r
-            uniqueId += "_" + ++i;\r
-        }\r
-        return uniqueId;\r
-    }\r
-    private void init() {\r
-        synchronized (this) {\r
-            Weak old = contexts.get(id);\r
-            assert(null == old);\r
-            contexts.put(id, new Weak(this));\r
-        }\r
-    }\r
-    public static synchronized UndoContext getUndoContext(String id) {\r
-        Weak w = contexts.get(id);\r
-        UndoContext c = null == w ? null : w.get();\r
-        return c; \r
-    }\r
-    public static synchronized Collection<UndoContext> getUndoContexts() {\r
-        Collection<UndoContext> ucs = new ArrayList<UndoContext>();\r
-        List<Weak> weaks = new ArrayList<Weak>();\r
-        List<String> stale = new ArrayList<String>();\r
-        for (Map.Entry<String, Weak> e : contexts.entrySet()) {\r
-            UndoContext c = e.getValue().get();\r
-            if (null != c) {\r
-                ucs.add(c);\r
-                weaks.add(new Weak(c));\r
-            } else\r
-                stale.add(e.getKey());\r
-        }\r
-        for (String id : stale)\r
-            contexts.remove(id);\r
-        return ucs;\r
-    }\r
-    @Override\r
-    public String toString() {\r
-        return name + "@" + Integer.toHexString(hashCode());\r
-    }\r
-    @Override\r
-    public void commitOk(Operation op) throws DatabaseException {\r
-       if (DISABLED)\r
-           return;\r
-       if (commitOkDisabled) {\r
-            if (DEBUG)\r
-                System.out.println("DEBUG: Commit ok disabled.");\r
-           return;\r
-       }\r
-        if (DEBUG)\r
-            System.out.println("DEBUG: Commit ok id=" + op.getId() + " cs=" + op.getCSId()\r
-                + " context=" + this + ".");\r
-        if (undoRedoOn) {\r
-            undoRedoOn = false;\r
-            redos.clear();\r
-        }\r
-        // Check if operation is new. \r
-        if (op.getId() < 1 || op.getId() == op.getCSId()) {\r
-            Operation last = getLast();\r
-            if (null != last && last.getCSId() == op.getCSId()) {\r
-                Logger.defaultLogError("Duplicate operation for new operation id=" + op.getId() + ".");\r
-                if (DEBUG)\r
-                    System.out.println("DEBUG: New operation already in undo list id=" + op.getId() + ".");\r
-                return;\r
-            }\r
-            if (DEBUG)\r
-                System.out.println("DEBUG: New operation added to undo list id=" + op.getId() + ".");\r
-        } else { // Operation is old i.e. part of combined operation.\r
-            Operation last = operations.getCombined(op.getId());\r
-            if (null == last) {\r
-                Logger.defaultLogError("Missing operation for combined operation id=" + op.getId() + " cs=" + op.getCSId() + ".");\r
-                if (DEBUG)\r
-                    System.out.println("DEBUG: Missing old combined operation id=" + op.getId() + ".");\r
-            }\r
-        }\r
-        operations.addLast(op);\r
-        pendingExternals.clear();\r
-    }\r
-    public void externalCommit(Operation op) {\r
-        operations.addLast(op);\r
-       pendingExternals.clear();\r
-    }\r
-    public void cancelCommit() {\r
-       pendingExternals.clear();\r
-    }\r
-    \r
-    @Override\r
-    public Operation getLast() throws DatabaseException {\r
-        return operations.getLast();\r
-    }\r
-    protected Operation getLastRedo() throws DatabaseException {\r
-        if (redos.size() < 1)\r
-            return null;\r
-        Operation op = redos.getLast();\r
-        if (DEBUG)\r
-            System.out.println("DEBUG: Get last redo id=" + op.getId() + ".");\r
-        return op;\r
-    }\r
-    @Override\r
-    public Collection<Operation> getAll() throws DatabaseException {\r
-        return operations.getAll();\r
-    }\r
-    @Override\r
-    public Collection<Operation> getRedoList() throws DatabaseException {\r
-        return redos;\r
-    }\r
-    @Override\r
-    public List<Operation> undo(UndoRedoSupport support, int count) throws DatabaseException {\r
-        List<Operation> ops = new ArrayList<Operation>(count);\r
-        for (int i=0; i<count; ++i) {\r
-            Operation op = operations.removeLast();\r
-            if (null == op)\r
-                break;\r
-            for (Operation o : op.getOperations())\r
-                ops.add(o);\r
-        }\r
-        if (ops.size()< 1)\r
-            throw new NoHistoryException("Illegal call, undo list is empty.");\r
-        commitOkDisabled = true;\r
-        Operation redo = null;\r
-        try {\r
-            redo = support.undo(ops);\r
-        } finally {\r
-            commitOkDisabled = false;\r
-        }\r
-        if (null == redo)\r
-            return Collections.emptyList();\r
-        redos.add(redo);\r
-        undoRedoOn = true;\r
-        return ops;\r
-    }\r
-    @Override\r
-    public List<Operation> redo(UndoRedoSupport support, int count) throws DatabaseException {\r
-        List<Operation> ops = new ArrayList<Operation>(count);\r
-        for (int i=0; i<count; ++i) {\r
-            Operation op = removeLastRedo();\r
-            if (null == op)\r
-                break;\r
-            for (Operation o : op.getOperations())\r
-                ops.add(o);\r
-        }\r
-        if (ops.size() < 1)\r
-            throw new NoHistoryException("Illegal call, redo list is empty.");\r
-        Operation undo = null;\r
-        try {\r
-            commitOkDisabled = true;\r
-            undo = support.undo(ops);\r
-        } finally {\r
-            commitOkDisabled = false;\r
-        }\r
-        if (null == undo)\r
-            return Collections.emptyList();\r
-        if (DEBUG)\r
-            System.out.println("New operation added to undo list id=" + undo.getId() + ".");\r
-        operations.addLast(undo);\r
-        undoRedoOn = true;\r
-        return ops;\r
-    }\r
-    @Override\r
-    public void clear() {\r
-        operations.clear();\r
-        redos.clear();\r
-        pendingExternals.clear();\r
-    }\r
-    Operation removeLastRedo() {\r
-        if (redos.size() < 1)\r
-            return null;\r
-        Operation op = redos.removeLast();\r
-        if (DEBUG)\r
-            System.out.println("Remove last redo id=" + op.getId() + ".");\r
-        return op;\r
-    }\r
-    void undoPair(Operation undo, Operation redo) {\r
-        operations.remove(undo.getId());\r
-        redos.addLast(redo);\r
-    }\r
-    void redoPair(Operation redo, Operation undo) {\r
-        redos.remove(redo);\r
-        operations.addLast(undo);\r
-    }\r
-    public void addChangeListener(ChangeListener cl) {\r
-        operations.addChangeListener(cl);\r
-    }\r
-    public void removeChangeListener(ChangeListener cl) {\r
-        operations.removeChangeListener(cl);\r
-    }\r
-    public void addExternalOperation(ExternalOperation op) {\r
-       pendingExternals.add(op);\r
-    }\r
-    public List<ExternalOperation> getPendingExternals() {\r
-       if(pendingExternals.isEmpty()) return Collections.emptyList();\r
-       if(!pendingExternals.isEmpty())\r
-               System.err.println("pending externals: " + pendingExternals);\r
-       return new ArrayList<ExternalOperation>(pendingExternals);\r
-    }\r
-    \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.common;
+
+import gnu.trove.map.TLongObjectMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.simantics.db.Operation;
+import org.simantics.db.UndoContext;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.NoHistoryException;
+import org.simantics.db.service.ExternalOperation;
+import org.simantics.db.service.UndoRedoSupport;
+import org.simantics.db.service.UndoRedoSupport.ChangeListener;
+import org.simantics.utils.threads.ThreadUtils;
+
+public class UndoContextEx implements UndoContext {
+    private static class Weak {
+        private final WeakReference<UndoContext> reference;
+        Weak(UndoContext context) {
+            reference = new WeakReference<UndoContext>(context);
+        }
+        UndoContext get() {
+            return reference.get();
+        }
+    }
+    private static class Operations {
+        private final Deque<Operation> operationsQue = new ArrayDeque<Operation>();
+        private final TLongObjectMap<Operation> operationsMap = new TLongObjectHashMap<Operation>();
+        void addLast(Operation op) {
+            long id = op.getId();
+            Operation old = operationsMap.put(id, op);
+            if (old != null) {
+                operationsQue.remove(old);
+                op.combine(old);
+            }
+            operationsQue.addLast(op);
+            fireChangeEvent();
+        }
+        Operation getLast() {
+            if (operationsQue.size() < 1)
+                return null;
+            Operation op = operationsQue.getLast();
+            if (DEBUG)
+                System.out.println("DEBUG: Get last id=" + op.getId() + ".");
+            return op;
+        }
+        Collection<Operation> getAll() {
+            return operationsQue;
+        }
+        Operation getCombined(long id) {
+            return operationsMap.get(id);
+        }
+        Operation removeLast() {
+            Operation op = operationsQue.pollLast();
+            if (null != op)
+                operationsMap.remove(op.getId());
+            fireChangeEvent();
+            return op;
+        }
+        Operation remove(long id) {
+            Operation op = operationsMap.remove(id);
+            if (null != op)
+                operationsQue.remove(op);
+            fireChangeEvent();
+            return op;
+        }
+        void clear() {
+            operationsQue.clear();
+            operationsMap.clear();
+            fireChangeEvent();
+        }
+        private final CopyOnWriteArrayList<ChangeListener> changeListeners = new CopyOnWriteArrayList<ChangeListener>(); 
+        private void fireChangeEvent() {
+            final Iterator<ChangeListener> it = changeListeners.iterator();
+            ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() {
+                @Override
+                public void run() {
+                    while (it.hasNext()) {
+                        ChangeListener l = it.next();
+                        try {
+                            l.onChanged();
+                        } catch (Throwable t) {
+                            Logger.defaultLogError(t);
+                        }
+                    }
+                }
+            });
+        }
+        void addChangeListener(ChangeListener cl) {
+            changeListeners.add(cl);
+        }
+        void removeChangeListener(ChangeListener cl) {
+            changeListeners.remove(cl);
+        }
+    }
+    private static HashMap<String, Weak> contexts = new HashMap<String, Weak>(); 
+    protected static final boolean DEBUG = false;
+    protected final boolean DISABLED = false;
+    private final Operations operations = new Operations();
+    private final Deque<Operation> redos = new ArrayDeque<Operation>();
+    private final ArrayList<ExternalOperation> pendingExternals = new ArrayList<ExternalOperation>();
+    private final String name;
+    private boolean undoRedoOn = false;
+    private final String id;
+    private boolean commitOkDisabled = false;
+
+    public UndoContextEx() {
+        this.id = getUniqueId(this.toString());
+        this.name = id;
+        init();
+    }
+    public UndoContextEx(String id) {
+        this.id = getUniqueId(id);
+        this.name = id;
+        init();
+    }
+    public UndoContextEx(String id, String name) {
+        this.id = getUniqueId(id);
+        this.name = name;
+        init();
+    }
+    private String getUniqueId(String id) {
+        String uniqueId = id;
+        int i=0;
+        while (contexts.containsKey(uniqueId)) {
+            uniqueId += "_" + ++i;
+        }
+        return uniqueId;
+    }
+    private void init() {
+        synchronized (this) {
+            Weak old = contexts.get(id);
+            assert(null == old);
+            contexts.put(id, new Weak(this));
+        }
+    }
+    public static synchronized UndoContext getUndoContext(String id) {
+        Weak w = contexts.get(id);
+        UndoContext c = null == w ? null : w.get();
+        return c; 
+    }
+    public static synchronized Collection<UndoContext> getUndoContexts() {
+        Collection<UndoContext> ucs = new ArrayList<UndoContext>();
+        List<Weak> weaks = new ArrayList<Weak>();
+        List<String> stale = new ArrayList<String>();
+        for (Map.Entry<String, Weak> e : contexts.entrySet()) {
+            UndoContext c = e.getValue().get();
+            if (null != c) {
+                ucs.add(c);
+                weaks.add(new Weak(c));
+            } else
+                stale.add(e.getKey());
+        }
+        for (String id : stale)
+            contexts.remove(id);
+        return ucs;
+    }
+    @Override
+    public String toString() {
+        return name + "@" + Integer.toHexString(hashCode());
+    }
+    @Override
+    public void commitOk(Operation op) throws DatabaseException {
+       if (DISABLED)
+           return;
+       if (commitOkDisabled) {
+            if (DEBUG)
+                System.out.println("DEBUG: Commit ok disabled.");
+           return;
+       }
+        if (DEBUG)
+            System.out.println("DEBUG: Commit ok id=" + op.getId() + " cs=" + op.getCSId()
+                + " context=" + this + ".");
+        if (undoRedoOn) {
+            undoRedoOn = false;
+            redos.clear();
+        }
+        // Check if operation is new. 
+        if (op.getId() < 1 || op.getId() == op.getCSId()) {
+            Operation last = getLast();
+            if (null != last && last.getCSId() == op.getCSId()) {
+                Logger.defaultLogError("Duplicate operation for new operation id=" + op.getId() + ".");
+                if (DEBUG)
+                    System.out.println("DEBUG: New operation already in undo list id=" + op.getId() + ".");
+                return;
+            }
+            if (DEBUG)
+                System.out.println("DEBUG: New operation added to undo list id=" + op.getId() + ".");
+        } else { // Operation is old i.e. part of combined operation.
+            Operation last = operations.getCombined(op.getId());
+            if (null == last) {
+                Logger.defaultLogError("Missing operation for combined operation id=" + op.getId() + " cs=" + op.getCSId() + ".");
+                if (DEBUG)
+                    System.out.println("DEBUG: Missing old combined operation id=" + op.getId() + ".");
+            }
+        }
+        operations.addLast(op);
+        pendingExternals.clear();
+    }
+    public void externalCommit(Operation op) {
+        operations.addLast(op);
+       pendingExternals.clear();
+    }
+    public void cancelCommit() {
+       pendingExternals.clear();
+    }
+    
+    @Override
+    public Operation getLast() throws DatabaseException {
+        return operations.getLast();
+    }
+    protected Operation getLastRedo() throws DatabaseException {
+        if (redos.size() < 1)
+            return null;
+        Operation op = redos.getLast();
+        if (DEBUG)
+            System.out.println("DEBUG: Get last redo id=" + op.getId() + ".");
+        return op;
+    }
+    @Override
+    public Collection<Operation> getAll() throws DatabaseException {
+        return operations.getAll();
+    }
+    @Override
+    public Collection<Operation> getRedoList() throws DatabaseException {
+        return redos;
+    }
+    @Override
+    public List<Operation> undo(UndoRedoSupport support, int count) throws DatabaseException {
+        List<Operation> ops = new ArrayList<Operation>(count);
+        for (int i=0; i<count; ++i) {
+            Operation op = operations.removeLast();
+            if (null == op)
+                break;
+            for (Operation o : op.getOperations())
+                ops.add(o);
+        }
+        if (ops.size()< 1)
+            throw new NoHistoryException("Illegal call, undo list is empty.");
+        commitOkDisabled = true;
+        Operation redo = null;
+        try {
+            redo = support.undo(ops);
+        } finally {
+            commitOkDisabled = false;
+        }
+        if (null == redo)
+            return Collections.emptyList();
+        redos.add(redo);
+        undoRedoOn = true;
+        return ops;
+    }
+    @Override
+    public List<Operation> redo(UndoRedoSupport support, int count) throws DatabaseException {
+        List<Operation> ops = new ArrayList<Operation>(count);
+        for (int i=0; i<count; ++i) {
+            Operation op = removeLastRedo();
+            if (null == op)
+                break;
+            for (Operation o : op.getOperations())
+                ops.add(o);
+        }
+        if (ops.size() < 1)
+            throw new NoHistoryException("Illegal call, redo list is empty.");
+        Operation undo = null;
+        try {
+            commitOkDisabled = true;
+            undo = support.undo(ops);
+        } finally {
+            commitOkDisabled = false;
+        }
+        if (null == undo)
+            return Collections.emptyList();
+        if (DEBUG)
+            System.out.println("New operation added to undo list id=" + undo.getId() + ".");
+        operations.addLast(undo);
+        undoRedoOn = true;
+        return ops;
+    }
+    @Override
+    public void clear() {
+        operations.clear();
+        redos.clear();
+        pendingExternals.clear();
+    }
+    Operation removeLastRedo() {
+        if (redos.size() < 1)
+            return null;
+        Operation op = redos.removeLast();
+        if (DEBUG)
+            System.out.println("Remove last redo id=" + op.getId() + ".");
+        return op;
+    }
+    void undoPair(Operation undo, Operation redo) {
+        operations.remove(undo.getId());
+        redos.addLast(redo);
+    }
+    void redoPair(Operation redo, Operation undo) {
+        redos.remove(redo);
+        operations.addLast(undo);
+    }
+    public void addChangeListener(ChangeListener cl) {
+        operations.addChangeListener(cl);
+    }
+    public void removeChangeListener(ChangeListener cl) {
+        operations.removeChangeListener(cl);
+    }
+    public void addExternalOperation(ExternalOperation op) {
+       pendingExternals.add(op);
+    }
+    public List<ExternalOperation> getPendingExternals() {
+       if(pendingExternals.isEmpty()) return Collections.emptyList();
+       if(!pendingExternals.isEmpty())
+               System.err.println("pending externals: " + pendingExternals);
+       return new ArrayList<ExternalOperation>(pendingExternals);
+    }
+    
+}