/******************************************************************************* * Copyright (c) 2013, 2016 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.structuremergeviewer.groups.impl; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.MatchResource; import org.eclipse.emf.compare.ResourceAttachmentChange; import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.DiffNode; import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.MatchNode; import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.MatchResourceNode; import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.AbstractDifferenceGroupProvider; import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroup; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; import org.eclipse.emf.edit.tree.TreeNode; /** * This implementation of a * {@link org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider} will be used to * group the differences by their Resource. * * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @since 4.0 */ public class ByResourceGroupProvider extends AbstractDifferenceGroupProvider { /** * Specialized {@link BasicDifferenceGroupImpl} for Resources. * * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> */ public static class ResourceGroup extends BasicDifferenceGroupImpl { private Set<Match> roots; /** * {@inheritDoc}. * * @see org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.BasicDifferenceGroupImpl#BasicDifferenceGroupImpl(org.eclipse.emf.compare.Comparison) */ public ResourceGroup(Comparison comparison, ECrossReferenceAdapter crossReferenceAdapter) { super(comparison, Predicates.<Diff> alwaysTrue(), crossReferenceAdapter); } @Override public void buildSubTree() { // Prepare our "roots" list roots = new LinkedHashSet<Match>(); for (Match match : getComparison().getMatches()) { recursiveFindRoots(match); } super.buildSubTree(); } private void recursiveFindRoots(Match match) { if (hasRootSide(match)) { roots.add(match); } for (Match subMatch : match.getSubmatches()) { recursiveFindRoots(subMatch); } } /** * Checks if the given match has a side which is the root of its resource. * * @param match * The match. * @return <code>true</code> if this match has a "root" side (even if its the root of a fragment), * <code>false</code> otherwise. */ private boolean hasRootSide(Match match) { boolean hasRoot = match.getLeft() instanceof InternalEObject && ((InternalEObject)match.getLeft()).eDirectResource() != null; hasRoot = hasRoot || match.getRight() instanceof InternalEObject && ((InternalEObject)match.getRight()).eDirectResource() != null; hasRoot = hasRoot || match.getOrigin() instanceof InternalEObject && ((InternalEObject)match.getOrigin()).eDirectResource() != null; return hasRoot; } /** {@inheritDoc} */ @Override protected List<TreeNode> buildMatchTrees() { // All of our nodes will be under MatchResources for this group. return new ArrayList<TreeNode>(); } /** * {@inheritDoc} * * @see org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.BasicDifferenceGroupImpl#buildSubTree(MatchResource, * Set) */ @Override protected MatchResourceNode buildSubTree(MatchResource matchResource, Set<ResourceAttachmentChange> attachmentChanges) { MatchResourceNode matchResourceNode = createMatchResourceNode(matchResource); for (ResourceAttachmentChange attachmentChange : attachmentChanges) { DiffNode diffNode = createDiffNode(attachmentChange); matchResourceNode.addDiffNode(diffNode); } for (Match match : roots) { if (isUnderResourceWithURI(match.getLeft(), matchResource.getLeftURI()) || isUnderResourceWithURI(match.getRight(), matchResource.getRightURI()) || isUnderResourceWithURI(match.getOrigin(), matchResource.getOriginURI())) { MatchNode matchNode = createMatchNode(match); populateMatchNode(matchNode); if (!matchNode.getChildren().isEmpty()) { matchResourceNode.addMatchNode(matchNode); } } } return matchResourceNode; } /** * Check if the resource of the given object as the same uri as the given uri. * * @param eObject * the given object. * @param uri * the given uri. * @return true if the resource of the given object as the same uri as the given uri, false otherwise. */ private boolean isUnderResourceWithURI(EObject eObject, String uri) { if (eObject != null && uri != null) { final Resource resource = eObject.eResource(); return resource != null && uri.equals(resource.getURI().toString()); } return false; } } /** * {@inheritDoc} * * @see org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.AbstractBuildingDifferenceGroupProvider#buildGroups(org.eclipse.emf.compare.Comparison) */ @Override protected Collection<? extends IDifferenceGroup> buildGroups(Comparison comparison2) { ResourceGroup group = new ResourceGroup(comparison2, getCrossReferenceAdapter()); group.buildSubTree(); return ImmutableList.of(group); } }