/**
* <copyright>
*
* Copyright (c) 2010-2016 Thales Global Services S.A.S.
* 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:
* Thales Global Services S.A.S. - initial API and implementation
*
* </copyright>
*/
package org.eclipse.emf.diffmerge.ui.setup;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.compare.IPropertyChangeNotifier;
import org.eclipse.emf.diffmerge.api.Role;
import org.eclipse.emf.diffmerge.ui.specification.IComparisonMethod;
import org.eclipse.emf.diffmerge.ui.specification.IComparisonMethodFactory;
import org.eclipse.emf.diffmerge.ui.specification.IModelScopeDefinition;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
/**
* A simple structure that associates scope definitions with corresponding
* compatible comparison method factories and allows selecting one of the factories
* for creating a comparison method.
* @author Olivier Constant
*/
public class ComparisonSetup implements IPropertyChangeNotifier {
/** An identifier for changes to the roles of the scope definitions */
public static final String PROPERTY_ROLES = "ComparisonSetup.Property.Roles"; //$NON-NLS-1$
/** An identifier for changes to the roles of the scope definitions */
public static final String PROPERTY_COMPARISON_METHOD =
"ComparisonSetup.Property.ComparisonMethod"; //$NON-NLS-1$
/** The map from roles to the corresponding scope definitions */
private final Map<Role, IModelScopeDefinition> _roleToScopeDefinition;
/** Whether scope definitions can be swapped by the end user */
private boolean _canSwapScopeDefinitions;
/** The potentially null role to use as a reference in a two-way comparison */
private Role _twoWayReferenceRole;
/** Whether the two-way reference role can be changed by the end user */
private boolean _canChangeTwoWayReferenceRole;
/** The non-null, non-empty list of applicable method factories */
private final List<IComparisonMethodFactory> _compatibleMethodFactories;
/** The potentially null selected factory (among the compatible factories) */
private IComparisonMethodFactory _selectedFactory;
/** The potentially null comparison method */
private IComparisonMethod _comparisonMethod;
/** A non-null set of listeners on this object */
private final Set<IPropertyChangeListener> _listeners;
/**
* Constructor
* @param scopeSpec1_p a non-null scope definition
* @param scopeSpec2_p a non-null scope definition
* @param scopeSpec3_p a potentially null scope definition
* @param compatibleFactories_p a non-null, non-empty list
*/
public ComparisonSetup(IModelScopeDefinition scopeSpec1_p, IModelScopeDefinition scopeSpec2_p,
IModelScopeDefinition scopeSpec3_p, List<IComparisonMethodFactory> compatibleFactories_p) {
_roleToScopeDefinition = new HashMap<Role, IModelScopeDefinition>();
_roleToScopeDefinition.put(Role.TARGET, scopeSpec1_p);
_roleToScopeDefinition.put(Role.REFERENCE, scopeSpec2_p);
_roleToScopeDefinition.put(Role.ANCESTOR, scopeSpec3_p);
_canSwapScopeDefinitions = true;
_twoWayReferenceRole = null;
_canChangeTwoWayReferenceRole = true;
_comparisonMethod = null;
_compatibleMethodFactories = new ArrayList<IComparisonMethodFactory>(compatibleFactories_p);
_listeners = new HashSet<IPropertyChangeListener>();
}
/**
* Return whether the two-way reference role can be changed by the end user
*/
public boolean canChangeTwoWayReferenceRole() {
return _canChangeTwoWayReferenceRole;
}
/**
* Return whether scope definitions can be swapped by the end user
*/
public boolean canSwapScopeDefinitions() {
return _canSwapScopeDefinitions;
}
/**
* Return the list of comparison factories which are compatible with the
* scope definitions
* @return a non-null, non-empty list
*/
public List<IComparisonMethodFactory> getApplicableComparisonMethodFactories() {
return Collections.unmodifiableList(_compatibleMethodFactories);
}
/**
* Return the comparison method created by the selected factory, if any
* @return a potentially null object
*/
public IComparisonMethod getComparisonMethod() {
return _comparisonMethod;
}
/**
* Return the scope definition that plays the given role
* @param role_p a non-null role
* @return a scope definition which may only be null if role is ANCESTOR
*/
public IModelScopeDefinition getScopeDefinition(Role role_p) {
return _roleToScopeDefinition.get(role_p);
}
/**
* Return the selected factory among the compatible ones
* @return a potentially null factory
*/
public IComparisonMethodFactory getSelectedFactory() {
return _selectedFactory;
}
/**
* @see org.eclipse.emf.diffmerge.ui.specification.IComparisonMethod#getTwoWayReferenceRole()
*/
public Role getTwoWayReferenceRole() {
return _twoWayReferenceRole;
}
/**
* Return whether the comparison will be three-way
*/
public boolean isThreeWay() {
return getScopeDefinition(Role.ANCESTOR) != null;
}
/**
* Notify listeners of the given property change event
* @param event_p a non-null event
*/
protected void notify(PropertyChangeEvent event_p) {
for (IPropertyChangeListener listener : _listeners) {
listener.propertyChange(event_p);
}
}
/**
* Update the current comparison method with all available information
*/
public void performFinish() {
if (!isThreeWay() && _comparisonMethod != null)
_comparisonMethod.setTwoWayReferenceRole(getTwoWayReferenceRole());
}
/**
* Set whether the two-way reference role can be changed by the end user
* @param canChange_p whether it can be changed
*/
public void setCanChangeTwoWayReferenceRole(boolean canChange_p) {
_canChangeTwoWayReferenceRole = canChange_p;
}
/**
* Set whether scope definitions can be swapped by the end user
* @param canSwap_p whether they can be swapped
*/
public void setCanSwapScopeDefinitions(boolean canSwap_p) {
_canSwapScopeDefinitions = canSwap_p;
}
/**
* Set the selected method factory and consequently update the comparison method
* @param selectedFactory_p a factory which is null or belongs to getCompatibleFactories()
*/
public void setSelectedFactory(IComparisonMethodFactory selectedFactory_p) {
_selectedFactory = selectedFactory_p;
if (_selectedFactory != null) {
_comparisonMethod = _selectedFactory.createComparisonMethod(
getScopeDefinition(Role.TARGET), getScopeDefinition(Role.REFERENCE),
getScopeDefinition(Role.ANCESTOR));
} else {
_comparisonMethod = null;
}
notify(new PropertyChangeEvent(this, PROPERTY_COMPARISON_METHOD, null, null));
}
/**
* @see org.eclipse.emf.diffmerge.ui.specification.IComparisonMethod#setTwoWayReferenceRole(org.eclipse.emf.diffmerge.api.Role)
*/
public void setTwoWayReferenceRole(Role role_p) {
if (!isThreeWay() && Role.TARGET == role_p || Role.REFERENCE == role_p)
_twoWayReferenceRole = role_p;
}
/**
* Swap the scope definitions that play the given roles
* @param role1_p a non-null role
* @param role2_p a non-null role
* @return whether the operation succeeded (it may only fail to prevent inconsistencies)
*/
public boolean swapScopeDefinitions(Role role1_p, Role role2_p) {
boolean result = true;
if (_comparisonMethod != null)
result = _comparisonMethod.swapScopeDefinitions(role1_p, role2_p);
if (result) {
IModelScopeDefinition scope1 = getScopeDefinition(role1_p);
IModelScopeDefinition scope2 = getScopeDefinition(role2_p);
if (scope1 != null && scope2 != null) {
_roleToScopeDefinition.put(role1_p, scope2);
_roleToScopeDefinition.put(role2_p, scope1);
}
notify(new PropertyChangeEvent(this, PROPERTY_ROLES, null, null));
}
return result;
}
/**
* @see org.eclipse.compare.IPropertyChangeNotifier#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
*/
public void addPropertyChangeListener(IPropertyChangeListener listener_p) {
_listeners.add(listener_p);
}
/**
* @see org.eclipse.compare.IPropertyChangeNotifier#removePropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
*/
public void removePropertyChangeListener(IPropertyChangeListener listener_p) {
_listeners.remove(listener_p);
}
/**
* Remove all property change listeners
*/
public void removePropertyChangeListeners() {
_listeners.clear();
}
}