Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 189e6d796eb4edf43d4965c3c34bb3c48b7faf57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*****************************************************************************
 * Copyright (c) 2015 Christian W. Damus and others.
 * 
 * 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:
 *   Christian W. Damus - Initial API and implementation
 *   
 *****************************************************************************/

package org.eclipse.papyrus.infra.sync.internal;

import static org.eclipse.papyrus.infra.core.utils.TransactionHelper.isTriggerTransaction;

import java.util.concurrent.ConcurrentMap;

import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.transaction.ResourceSetChangeEvent;
import org.eclipse.emf.transaction.RollbackException;
import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.papyrus.infra.sync.EMFListener;
import org.eclipse.papyrus.infra.sync.SyncFeature;
import org.eclipse.papyrus.infra.sync.policy.ISyncPolicyDelegate;

import com.google.common.collect.MapMaker;

/**
 * Default implementation of the sync-policy delegate registry.
 */
class SyncPolicyDelegateRegistryImpl implements ISyncPolicyDelegate.Registry {
	@SuppressWarnings("rawtypes")
	private ConcurrentMap<Class<? extends SyncFeature>, ISyncPolicyDelegate<?, ?>> delegates = new MapMaker().weakKeys().makeMap();

	private EMFListener listener;

	SyncPolicyDelegateRegistryImpl(TransactionalEditingDomain domain) {
		super();

		this.listener = createEMFListener(domain);
	}

	void dispose() {
		delegates.clear();

		if (listener != null) {
			listener.dispose();
			listener = null;
		}
	}

	EMFListener getEMFListener() {
		return listener;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <M, T> ISyncPolicyDelegate<M, T> get(SyncFeature<M, T, ?> syncFeature) {
		return (ISyncPolicyDelegate<M, T>) delegates.get(syncFeature.getClass());
	}

	@Override
	public void register(ISyncPolicyDelegate<?, ?> policyDelegate, Class<?> featureType) {
		delegates.putIfAbsent(featureType.asSubclass(SyncFeature.class), policyDelegate);
	}

	@Override
	public void deregister(ISyncPolicyDelegate<?, ?> policyDelegate, Class<?> featureType) {
		delegates.remove(featureType.asSubclass(SyncFeature.class), policyDelegate);
	}

	private EMFListener createEMFListener(TransactionalEditingDomain domain) {
		return new EMFListener(domain) {
			@Override
			public Command transactionAboutToCommit(ResourceSetChangeEvent event) throws RollbackException {
				// Don't respond to changes made by triggers because these are not explicit by the
				// user and they include the changes effected by synchronization in the first place.
				// We only want to detect the original user-initiated changes.
				// Note that initial-sync changes made in an unprotected transaction wouldn't trigger
				// the listener in any case
				Transaction transaction = event.getTransaction();
				return (transaction != null && isTriggerTransaction(transaction))
						? null
						: super.transactionAboutToCommit(event);
			}
		};
	}
}

Back to the top