1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.diagram.handler.impl;
\r
14 import java.util.Collection;
\r
15 import java.util.concurrent.locks.ReadWriteLock;
\r
16 import java.util.concurrent.locks.ReentrantReadWriteLock;
\r
18 import org.simantics.g2d.diagram.IDiagram;
\r
19 import org.simantics.g2d.diagram.handler.LifeCycle;
\r
20 import org.simantics.g2d.diagram.handler.TransactionContext;
\r
21 import org.simantics.g2d.element.IElement;
\r
22 import org.simantics.utils.datastructures.ListenerList;
\r
23 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
24 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
\r
27 * @author Tuukka Lehtonen
\r
29 public class LockingTransactionContext implements TransactionContext, LifeCycle {
\r
31 public static final LockingTransactionContext INSTANCE = new LockingTransactionContext();
\r
33 private static final Key TRANSACTION_LISTENERS = new KeyOf(ListenerList.class, "TRANSACTION LISTENERS");
\r
34 private static final Key TRANSACTION_LOCK = new KeyOf(ReadWriteLock.class, "TRANSACTION LOCK");
\r
37 public void onDiagramCreated(IDiagram diagram) {
\r
38 diagram.setHint(TRANSACTION_LISTENERS, new ListenerList<TransactionListener>(TransactionListener.class));
\r
39 diagram.setHint(TRANSACTION_LOCK, new ReentrantReadWriteLock(true));
\r
43 public void onDiagramLoaded(IDiagram diagram, Collection<IElement> initialElements) {
\r
47 public void onDiagramDestroyed(IDiagram diagram) {
\r
51 public void onDiagramDisposed(IDiagram diagram) {
\r
52 diagram.removeHint(TRANSACTION_LISTENERS);
\r
53 diagram.removeHint(TRANSACTION_LOCK);
\r
57 public void addTransactionListener(IDiagram d, TransactionListener l) {
\r
58 ListenerList<TransactionListener> ll;
\r
60 ll = d.getHint(TRANSACTION_LISTENERS);
\r
62 ll = new ListenerList<TransactionListener>(TransactionListener.class);
\r
63 d.setHint(TRANSACTION_LISTENERS, ll);
\r
70 public void removeTransactionListener(IDiagram d, TransactionListener l) {
\r
72 ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
\r
79 void lock(ReadWriteLock lock, TransactionType type) {
\r
82 lock.readLock().lock();
\r
85 lock.writeLock().lock();
\r
90 void unlock(ReadWriteLock lock, TransactionType type) {
\r
93 lock.readLock().unlock();
\r
96 lock.writeLock().unlock();
\r
102 public Transaction startTransaction(IDiagram d, TransactionType type) {
\r
103 ReadWriteLock lock = d.getHint(TRANSACTION_LOCK);
\r
104 assert lock != null;
\r
107 Transaction t = new Transaction.Impl(type);
\r
108 ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
\r
110 for (TransactionListener l : ll.getListeners())
\r
111 l.transactionStarted(d, t);
\r
113 } catch (RuntimeException e) {
\r
114 unlock(lock, type);
\r
120 public void finishTransaction(IDiagram d, Transaction t) {
\r
121 ReadWriteLock lock = d.getHint(TRANSACTION_LOCK);
\r
122 assert lock != null;
\r
124 ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
\r
126 for (TransactionListener l : ll.getListeners())
\r
127 l.transactionFinished(d, t);
\r
129 unlock(lock, t.getType());
\r