Skip to main content
summaryrefslogtreecommitdiffstats
blob: 57172a54ededa8f5c5ff40c466f4c2c72a603769 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*******************************************************************************
 * Copyright (c) 2016-2017, Thales Global Services S.A.S.
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Abel Hegedus, Tamas Borbas, Peter Lunk (IncQuery Labs Ltd.) - initial API and implementation
 *******************************************************************************/
package org.eclipse.emf.diffmerge.patch.ui.handlers

import java.lang.reflect.InvocationTargetException
import java.util.ArrayList
import java.util.Collection
import java.util.Collections
import java.util.HashSet
import java.util.List
import java.util.Map.Entry
import java.util.Set
import org.eclipse.core.runtime.IProgressMonitor
import org.eclipse.emf.common.util.EMap
import org.eclipse.emf.diffmerge.api.IMatch
import org.eclipse.emf.diffmerge.api.Role
import org.eclipse.emf.diffmerge.api.diff.IDifference
import org.eclipse.emf.diffmerge.api.diff.IPresenceDifference
import org.eclipse.emf.diffmerge.diffdata.EMatch
import org.eclipse.emf.diffmerge.ui.diffuidata.ComparisonSelection
import org.eclipse.emf.diffmerge.ui.viewers.EMFDiffNode
import org.eclipse.emf.diffmerge.ui.viewers.MergeImpactViewer.ImpactInput
import org.eclipse.jface.operation.IRunnableWithProgress
import org.eclipse.ui.PlatformUI
import org.eclipse.ui.progress.IProgressService

class ComparisonSelectionUtil {

  protected def Collection<IDifference> getDiffsToMerge(ComparisonSelection selection, boolean toLeft_p,
    EMFDiffNode input) {
    val Role destination = Role.REFERENCE;
    val isCoverChildren = true;
    val isIncrementalMode = false;
    val List<EMatch> selectedMatches = getSelectedMatchesForInteractions(selection)
    val Collection<IDifference> toMerge = if (!selectedMatches.isEmpty()) {
        getDifferencesToMerge(selectedMatches, destination, isCoverChildren, isIncrementalMode, input)
      } else {
        input.categoryManager.getPendingDifferencesFiltered(selection.asDifferencesToMerge())
      }
    val ImpactInput mergeInput = new ImpactInput(toMerge, toLeft_p, input);
    val IProgressService progress = PlatformUI.getWorkbench().getProgressService();
    try {
      progress.busyCursorWhile(new IRunnableWithProgress() {
        /**
         * @see IRunnableWithProgress#run(IProgressMonitor)
         */
        override void run(IProgressMonitor monitor_p) throws InvocationTargetException, InterruptedException {
          mergeInput.compute(monitor_p);
        }
      });
    } catch (Exception ex) {
      return null;
    }

    val EMap<IMatch, Collection<IDifference>> explicitImpacts = mergeInput.getImpact(true);
    val EMap<IMatch, Collection<IDifference>> implicitImpacts = mergeInput.getImpact(false);
    val Set<IDifference> diffs = new HashSet<IDifference>();
    for (Entry<IMatch, Collection<IDifference>> impact : implicitImpacts) {
      diffs.addAll(impact.getValue());
    }
    for (Entry<IMatch, Collection<IDifference>> impact : explicitImpacts) {
      diffs.addAll(impact.getValue());
    }

    return diffs;
  }

  protected def List<EMatch> getSelectedMatchesForInteractions(ComparisonSelection selection_p) {
    var List<EMatch> selectedMatches = selection_p.getSelectedMatches();
    if (selectedMatches.isEmpty()) {
      val List<EMatch> treePath = selection_p.getSelectedTreePath();
      if (!treePath.isEmpty()) {
        selectedMatches = Collections.singletonList(treePath.get(treePath.size() - 1));
      }
    }
    return selectedMatches;
  }

  /**
   * Copied from {@link org.eclipse.emf.diffmerge.ui.viewers.ComparisonViewer}
   *
   * Return the differences to merge from a given list of selected matches and the given
   * criteria
   * @param selectedMatches_p a non-null list
   * @param coverChildren_p whether children of the matches must be covered
   * @param incrementalMode_p whether optional deletions must be skipped
   * @return a non-null, potentially empty, unmodifiable list
   */
  protected def List<IDifference> getDifferencesToMerge(List<EMatch> selectedMatches_p, Role destination_p,
    boolean coverChildren_p, boolean incrementalMode_p, EMFDiffNode input) {
    val List<IDifference> result = new ArrayList<IDifference>();
    val IProgressService progress = PlatformUI.getWorkbench().getProgressService();
    try {
      progress.busyCursorWhile(new IRunnableWithProgress() {
        /**
         * @see IRunnableWithProgress#run(IProgressMonitor)
         */
        override void run(IProgressMonitor monitor_p) throws InvocationTargetException, InterruptedException {
          for (EMatch selectedMatch : selectedMatches_p) {
            if (coverChildren_p) {
              addDifferencesToMergeRec(result, selectedMatch, destination_p, incrementalMode_p, input);
            } else {
              addDifferencesToMerge(result, selectedMatch, destination_p, incrementalMode_p, input);
            }
          }
        }
      });
    } catch (Exception e) {
      // Proceed
    }
    return Collections.unmodifiableList(result);
  }

  /**
   * Copied from {@link org.eclipse.emf.diffmerge.ui.viewers.ComparisonViewer}
   *
   * Add differences to merge on the given match to the given list according
   * to the given criteria
   * @param toMerge_p a non-null, modifiable list
   * @param match_p a non-null match
   * @param destination_p a non-null role which is TARGET or REFERENCE
   * @param incrementalMode_p whether optional deletions must be skipped
   */
  protected def void addDifferencesToMerge(List<IDifference> toMerge_p, IMatch match_p, Role destination_p,
    boolean incrementalMode_p, EMFDiffNode input) {
    for (IDifference difference : match_p.getAllDifferences()) {
      if (!input.getCategoryManager().isFiltered(difference)) {
        if (!incrementalMode_p || difference instanceof IPresenceDifference &&
          (difference as IPresenceDifference).getPresenceRole() != destination_p)
          toMerge_p.add(difference);
      }
    }
  }

  /**
   * Copied from {@link org.eclipse.emf.diffmerge.ui.viewers.ComparisonViewer}
   *
   * Add differences to merge on the given match and its children to the given list according
   * to the given criteria
   * @param toMerge_p a non-null, modifiable list
   * @param match_p a non-null match
   * @param destination_p a non-null role which is TARGET or REFERENCE
   * @param incrementalMode_p whether optional deletions must be skipped
   */
  protected def void addDifferencesToMergeRec(List<IDifference> toMerge_p, IMatch match_p, Role destination_p,
    boolean incrementalMode_p, EMFDiffNode input) {
    addDifferencesToMerge(toMerge_p, match_p, destination_p, incrementalMode_p, input);
    for (IMatch child : input.getCategoryManager().getChildrenForMerge(match_p)) {
      addDifferencesToMergeRec(toMerge_p, child, destination_p, incrementalMode_p, input);
    }
  }
}

Back to the top