Skip to main content
summaryrefslogtreecommitdiffstats
blob: 66cb1c18d73e18c2a2d255b844af3c34c9fb59d5 (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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*******************************************************************************
 * Copyright (c) 2010 Technical University of Denmark.
 * 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:
 *    Patrick Koenemann, DTU Informatics - initial API and implementation
 *******************************************************************************/
package org.eclipse.emf.compare.mpatch.extension;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.compare.mpatch.IElementReference;
import org.eclipse.emf.compare.mpatch.IndepChange;
import org.eclipse.emf.compare.mpatch.MPatchModel;
import org.eclipse.emf.compare.mpatch.IndepReferenceChange;
import org.eclipse.emf.compare.mpatch.binding.MPatchModelBinding;
import org.eclipse.emf.compare.mpatch.binding.BindingFactory;
import org.eclipse.emf.ecore.EObject;

/**
 * This class is used to store the resolved binding for applying an mpatch to a particular model.<br>
 * <br>
 * It provides the raw results, i.e. a map from symbolic references to a set of resolved elements, as well as a grouped
 * result, i.e. a map from {@link IndepChange}s to the actual required symbolic references depending on the application
 * direction. For example, if a {@link IndepReferenceChange} is resolved for the left side (
 * {@link ResolvedSymbolicReferences#RESOLVE_LEFT}), then only the references <i>correspondingElement</i> and
 * <i>oldReference</i> are resolved, but not <i>newReference</i>.<br>
 * <br>
 * An instance of this should only be created by implementations of {@link IMPatchApplication}.
 * 
 * @author Patrick Koenemann (pk@imm.dtu.dk)
 * 
 */
public final class ResolvedSymbolicReferences {

	private final MPatchModel mpatch;
	private final EObject model;
	private final int direction;
	private final Map<IndepChange, Map<IElementReference, List<EObject>>> resolution;
	private final Map<IndepChange, ValidationResult> validation;
	private final Map<IElementReference, List<EObject>> resolutionRaw;
	private final Map<IElementReference, List<IElementReference>> equallyResolvingReferences;
	private final MPatchModelBinding binding;

	/** A constant defining the resolution of elements in the unchanged model of an mpatch. */
	public static final int RESOLVE_UNCHANGED = 1;

	/** A constant defining the resolution of elements in the changed model of an mpatch. */
	public static final int RESOLVE_CHANGED = 2;

	/**
	 * Classification of validation result (
	 * {@link MPatchValidator#validateElementState(IndepChange, Map, boolean, boolean)}).<br>
	 * <br>
	 * 
	 * {@link ValidationResult#STATE_BEFORE} - State before the change found (=successful).<br>
	 * {@link ValidationResult#STATE_AFTER} - State after the change found (=applied).<br>
	 * {@link ValidationResult#STATE_INVALID} - Model elements resolved but neither state (before, after) could be
	 * found.<br> {@link ValidationResult#REFERENCE} - Wrong number of resolved references.<br>
	 * {@link ValidationResult#UNKNOWN_CHANGE} - The change is unknown.
	 */
	public static enum ValidationResult {
		/** State before the change found (=successful). */
		STATE_BEFORE,
		/** State after the change found (=applied). */
		STATE_AFTER,
		/** Model elements resolved but neither state (before, after) could be found. */
		STATE_INVALID,
		/** Wrong number of resolved references. */
		REFERENCE,
		/** the change is unknown. */
		UNKNOWN_CHANGE,
	}

	/**
	 * A mapping from {@link ValidationResult} to a human-readable String.
	 */
	public static final Map<ValidationResult, String> VALIDATION_RESULTS;

	static {
		final Map<ValidationResult, String> messageMap = new HashMap<ValidationResult, String>();
		messageMap.put(ValidationResult.STATE_BEFORE, "ok");
		messageMap.put(ValidationResult.STATE_AFTER, "applied");
		messageMap.put(ValidationResult.STATE_INVALID, "invalid state in model");
		messageMap.put(ValidationResult.REFERENCE, "check reference resolutions");
		messageMap.put(ValidationResult.UNKNOWN_CHANGE, "unknown change");
		VALIDATION_RESULTS = Collections.unmodifiableMap(messageMap);
	}

	/**
	 * Create a wrapper object for the resolution of symbolic references. See {@link IResolvedSymbolicReferences} for
	 * details.
	 */
	public ResolvedSymbolicReferences(MPatchModel mpatch, EObject model, int direction,
			Map<IndepChange, Map<IElementReference, List<EObject>>> resolution,
			Map<IElementReference, List<EObject>> resolutionRaw,
			Map<IElementReference, List<IElementReference>> equallyResolvingReferences,
			Map<IndepChange, ValidationResult> validation) {
		this.mpatch = mpatch;
		this.direction = direction;
		this.model = model;
		this.resolution = resolution;
		this.resolutionRaw = resolutionRaw;
		this.equallyResolvingReferences = equallyResolvingReferences;
		this.validation = validation;
		binding = BindingFactory.eINSTANCE.createMPatchModelBinding();
		binding.setMPatchModel(mpatch);
		binding.setModel(model);
	}

	/**
	 * The differences for which the symbolic references were resolved.
	 */
	public MPatchModel getMPatchModel() {
		return mpatch;
	}

	/**
	 * The direction for which the symbolic reference resolution was performed. Either
	 * {@link ResolvedSymbolicReferences#RESOLVE_CHANGED} or {@link ResolvedSymbolicReferences#RESOLVE_UNCHANGED}.
	 */
	public int getDirection() {
		return direction;
	}

	/**
	 * A serializable form of the resolution of symbolic references for traceability.
	 */
	public MPatchModelBinding getMPatchModelBinding() {
		return binding;
	}

	/**
	 * The model for which the symbolic references were resolved.
	 */
	public EObject getModel() {
		return model;
	}

	/**
	 * A map containing all symbolic references which resolve to the same elements. More specifically speaking, groups
	 * of symbolic references for which {@link IElementReference#resolvesEqual(IElementReference)} returns
	 * <code>true</code>.
	 */
	public Map<IElementReference, List<IElementReference>> getEquallyResolvingReferences() {
		return equallyResolvingReferences;
	}

	/**
	 * @param reference
	 *            A symbolic reference.
	 * @return A list of all equally resolving references excluding <code>reference</code>.
	 * @throws IllegalArgumentException
	 *             If the reference is not listed in {@link ResolvedSymbolicReferences#getEquallyResolvingReferences()}.
	 */
	public List<IElementReference> getEquallyResolvingReferences(IElementReference reference) {
		if (!getEquallyResolvingReferences().containsKey(reference))
			throw new IllegalArgumentException(
					"Reference not found in equally resolved references. Make sure that it belongs to the differences! "
							+ reference);
		final List<IElementReference> list = new ArrayList<IElementReference>(getEquallyResolvingReferences().get(
				reference));
		list.remove(reference);
		return list;
	}

	/**
	 * This returns the raw resolution of symbolic references.<br>
	 * This means that all {@link IndepChange}s from the {@link MPatchModel} are mapped to a set of {@link EObject} for
	 * which the resolution was performed.
	 */
	public Map<IElementReference, List<EObject>> getRawResolution() {
		return resolutionRaw;
	}

	/**
	 * The result contains a direction-sensitive mapping from {@link IndepChange}s to all relevant symbolic references,
	 * depending on the direction of resolution. For example, if a {@link IndepReferenceChange} is resolved for the left
	 * side ( {@link ResolvedSymbolicReferences#RESOLVE_LEFT}), then only the references <i>correspondingElement</i> and
	 * <i>oldReference</i> are resolved, but not <i>newReference</i>.
	 * 
	 * The {@link IndepChange}s contained in this map might be a subset of those in
	 * {@link ResolvedSymbolicReferences#getMPatchModel()}; e.g. for difference application, only these changes are
	 * applied.
	 */
	public Map<IndepChange, Map<IElementReference, List<EObject>>> getResolutionByChange() {
		return resolution;
	}

	/**
	 * The result contains the states of all changes. It is the responsibility of the validator to update this map
	 * accordingly after each validation.
	 */
	public Map<IndepChange, ValidationResult> getValidation() {
		return validation;
	}
}

Back to the top