blob: a26658afe12fb63bf99afcadf23fa248f766bd0b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.contentmergeviewer.accessor.impl;
import static org.eclipse.emf.compare.merge.AbstractMerger.isInTerminalState;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.compare.FeatureMapChange;
import org.eclipse.emf.compare.internal.merge.IMergeData;
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.FeatureMap;
/**
* A specific {@link AbstractStructuralFeatureAccessor} for FeatureMapChanges of kind DifferenceKind.CHANGE
* (represent a value that changed his key).
*
* @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a>
* @since 4.0
*/
public class FeatureMapKeyChangeAccessorImpl extends AbstractStructuralFeatureAccessor {
/**
* Default constructor.
*
* @param adapterFactory
* the adapater factory used to create the accessor.
* @param diff
* the diff associated with this accessor.
* @param side
* the side of the accessor.
*/
public FeatureMapKeyChangeAccessorImpl(AdapterFactory adapterFactory, FeatureMapChange diff,
MergeViewerSide side) {
super(adapterFactory, diff, side);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.ICompareAccessor#getItems()
*/
public ImmutableList<? extends IMergeViewerItem> getItems() {
final EStructuralFeature leftKey = getKey(MergeViewerSide.LEFT);
final EStructuralFeature rightKey = getKey(MergeViewerSide.RIGHT);
final EStructuralFeature ancestorKey = getKey(MergeViewerSide.ANCESTOR);
final MergeViewerItem item = new MergeViewerItem(getComparison(), getInitialDiff(), leftKey, rightKey,
ancestorKey, getSide(), getRootAdapterFactory());
return ImmutableList.of(item);
}
/**
* Returns the {@link FeatureMapChange} diff associated with this accessor.
*
* @return the {@link FeatureMapChange} diff associated with this accessor.
*/
public FeatureMapChange getFeatureMapChange() {
return (FeatureMapChange)getInitialDiff();
}
/**
* Returns the key of the FeatureMap.Entry for the given side.
*
* @param side
* the given side.
* @return the key of the FeatureMap.Entry for the given side, or null if not found.
*/
private EStructuralFeature getKey(MergeViewerSide side) {
EStructuralFeature key = null;
final FeatureMapChange diff = (FeatureMapChange)getInitialDiff();
final FeatureMap.Entry entry = (FeatureMap.Entry)diff.getValue();
if ((side != MergeViewerSide.ANCESTOR && side.convertToDifferenceSource().equals(diff.getSource()))
&& !isInTerminalState(diff)) {
key = entry.getEStructuralFeature();
} else if (isInTerminalState(diff) && !isMergedTargetIsSource(diff)) {
key = entry.getEStructuralFeature();
} else {
// The entry of the diff source side.
final Object value = entry.getValue();
// The feature map object of the opposite side of the diff source.
final EObject eObject = getEObject(side);
// The entries of the opposite side of the diff source.
final List<Object> list = ReferenceUtil.getAsList(eObject, getStructuralFeature());
final IEqualityHelper equalityHelper = getComparison().getEqualityHelper();
for (Object object : list) {
// We've found the same value on the opposite side, return the key associated
if (object instanceof FeatureMap.Entry
&& equalityHelper.matchingValues(value, ((FeatureMap.Entry)object).getValue())) {
key = ((FeatureMap.Entry)object).getEStructuralFeature();
break;
}
}
}
return key;
}
/**
* Returns true if the given diff is merged and the target side of the merge is the same as the diff
* source.
*
* @param diff
* the given {@link FeatureMapChange}.
* @return true if the given diff is merged and the target side of the merge is the same as the diff
* source, false otherwise.
*/
private boolean isMergedTargetIsSource(FeatureMapChange diff) {
IMergeData mergeData = (IMergeData)EcoreUtil.getExistingAdapter(ComparisonUtil.getComparison(diff),
IMergeData.class);
if (mergeData != null) {
MergeMode mode = MergeMode.getMergeMode(diff, mergeData.isLeftEditable(),
mergeData.isRightEditable());
return diff.getSource() == mode.getMergeTarget(mergeData.isLeftEditable(),
mergeData.isRightEditable());
}
return false;
}
}