/******************************************************************************* * Copyright (c) 2015 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.ide.ui.internal.structuremergeviewer.provider; import org.eclipse.compare.ICompareInputLabelProvider; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.MatchResource; import org.eclipse.emf.compare.ide.internal.utils.StoragePathAdapter; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.tree.TreeNode; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.swt.graphics.Image; /** * Provides labels for the content viewer pane. * * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> */ public class TreeNodeCompareInputLabelProvider implements ICompareInputLabelProvider { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ILabelProvider#getImage(Object element) */ public Image getImage(Object element) { return null; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ILabelProvider#getText(Object element) */ public String getText(Object element) { return null; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(ILabelProviderListener listener) */ public void addListener(ILabelProviderListener listener) { } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() */ public void dispose() { } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(Object element, String property) */ public boolean isLabelProperty(Object element, String property) { return false; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(ILabelProviderListener listener) */ public void removeListener(ILabelProviderListener listener) { } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getAncestorLabel(Object input) */ public String getAncestorLabel(Object input) { final Match match = getMatch(getTreeNode(input)); if (match != null) { if (match.getOrigin() != null) { final EObject origin = match.getOrigin(); final Resource originResource = origin.eResource(); final StoragePathAdapter adapter = getStoragePathAdapter(originResource); if (adapter != null) { return computeLabel(adapter); } } else { return computeFallbackLabel(match, Side.ORIGIN); } } return null; } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getAncestorImage(Object input) */ public Image getAncestorImage(Object input) { return null; } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getLeftLabel(Object input) */ public String getLeftLabel(Object input) { final Match match = getMatch(getTreeNode(input)); if (match != null) { StoragePathAdapter adapter = getLeftAdapter(match); if (adapter != null) { return computeLabel(adapter); } else { return computeFallbackLabel(match, Side.LEFT); } } return null; } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getLeftImage(Object input) */ public Image getLeftImage(Object input) { return null; } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getRightLabel(Object input) */ public String getRightLabel(Object input) { final Match match = getMatch(getTreeNode(input)); if (match != null) { StoragePathAdapter adapter = getRightAdapter(match); if (adapter != null) { return computeLabel(adapter); } else { return computeFallbackLabel(match, Side.RIGHT); } } return null; } /** * {@inheritDoc} * * @see org.eclipse.compare.ICompareInputLabelProvider#getRightImage(Object input) */ public Image getRightImage(Object input) { return null; } private TreeNode getTreeNode(Object input) { if (input instanceof TreeNodeCompareInput && ((TreeNodeCompareInput)input).getTarget() instanceof TreeNode) { return (TreeNode)((TreeNodeCompareInput)input).getTarget(); } return null; } private Match getMatch(EObject object) { final Match match; if (object instanceof Match) { match = (Match)object; } else if (object instanceof Diff) { if (object.eContainer() instanceof MatchResource) { match = null; } else { match = ((Diff)object).getMatch(); } } else if (object instanceof TreeNode) { match = getMatch(((TreeNode)object).getData()); } else { match = null; } return match; } private StoragePathAdapter getStoragePathAdapter(Resource resource) { if (resource != null) { for (Adapter adapter : resource.eAdapters()) { if (adapter instanceof StoragePathAdapter) { return (StoragePathAdapter)adapter; } } } return null; } /** * Get the left adapter for a match. * * @param match * The given match * @return the adapter */ private StoragePathAdapter getLeftAdapter(Match match) { if (match != null) { if (match.getLeft() != null) { final EObject left = match.getLeft(); final Resource leftResource = left.eResource(); final StoragePathAdapter adapter = getStoragePathAdapter(leftResource); return adapter; } } return null; } /** * Get the right adapter for a match. * * @param match * The given match * @return the adapter */ private StoragePathAdapter getRightAdapter(Match match) { if (match != null) { if (match.getRight() != null) { final EObject right = match.getRight(); final Resource rightResource = right.eResource(); final StoragePathAdapter adapter = getStoragePathAdapter(rightResource); return adapter; } } return null; } /** * Compute the label used as title in the ContentMergeViewer. * * @param adapter * The adapter containing file informations * @return the label */ private String computeLabel(StoragePathAdapter adapter) { String computedLabel = ""; //$NON-NLS-1$ if (adapter != null) { String commitId = adapter.getCommitId(); String username = adapter.getUsername(); if (adapter.isLocal()) { computedLabel = "Local: " + adapter.getStoragePath(); //$NON-NLS-1$ } else { computedLabel = adapter.getStoragePath(); } if (commitId != null) { // For merge conflicts, the commit ID from EGit can be "Index" if (commitId.length() > 7) { commitId = commitId.substring(0, 7); } computedLabel = String.format("%s %s", computedLabel, commitId).trim(); //$NON-NLS-1$ } if (username != null && !"".equals(username)) { //$NON-NLS-1$ computedLabel += " (" + username + ")"; //$NON-NLS-1$//$NON-NLS-2$ } } return computedLabel; } private String computeFallbackLabel(Match match, Side side) { // The "correct" way to find the fall back label would be to try and find the match resource for the // given match. Then, if its value for the given 'side' is not null, use that. Otherwise it is a // fragment that only exists for one side; in which case we need to find another MatchResource which // value for 'side' isn't null, and use this MatchResource's storage path adapter to determine if it // is local or not, then retrieve the given match's MatchResource, find a non-null side on it that has // a non-null resource, and use that resource for the "path" part of our label. // This gives a code very complex and costly only to solve the rare occurence of an added/deleted // fragment. // We'll instead try and find the first parent of 'Match' which value for 'side' is not null and use // that, even if the 'path' part of the label may be wrong with that algorithm. EObject parent = match.eContainer(); while (parent instanceof Match) { final Resource resource = getResourceOnSide((Match)parent, side); if (resource != null) { final StoragePathAdapter adapter = getStoragePathAdapter(resource); return computeLabel(adapter); } parent = parent.eContainer(); } return null; } private Resource getResourceOnSide(Match match, Side side) { Resource resource = null; switch (side) { case LEFT: if (match.getLeft() != null) { resource = match.getLeft().eResource(); } break; case RIGHT: if (match.getRight() != null) { resource = match.getRight().eResource(); } break; case ORIGIN: if (match.getOrigin() != null) { resource = match.getOrigin().eResource(); } break; default: break; } return resource; } private static enum Side { LEFT, RIGHT, ORIGIN; } }