Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 5c507079c2be843ce56f597c8c61971c330a4968 (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
package org.eclipse.emf.edapt.declaration.delegation;

import java.util.List;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edapt.declaration.EdaptConstraint;
import org.eclipse.emf.edapt.declaration.EdaptOperation;
import org.eclipse.emf.edapt.declaration.EdaptParameter;
import org.eclipse.emf.edapt.declaration.OperationImplementation;
import org.eclipse.emf.edapt.internal.common.MetamodelFactory;
import org.eclipse.emf.edapt.spi.migration.Instance;
import org.eclipse.emf.edapt.spi.migration.Metamodel;
import org.eclipse.emf.edapt.spi.migration.Model;

/**
 * {@description}
 *
 * @author herrmama
 * @author $Author$
 * @version $Rev$
 * @levd.rating YELLOW Hash: 92A023B7F2C535962246670FFB2B5BCF
 */
@EdaptOperation(identifier = "extractAndGroupAttribute", label = "Extract and Group Attribute", description = "In the metamodel, an attribute is extracted into a new class. This extracted class is contained by an existing container class and referenced from the context class. In the model, an instance of the extracted class is created for each different value of the extracted attribute.", breaking = true)
public class ExtractAndGroupAttribute extends OperationImplementation {

	/** {@description} */
	@EdaptParameter(main = true, description = "The attribute to be extracted")
	public EAttribute extractedAttribute;

	/** {@description} */
	@EdaptConstraint(restricts = "extractedAttribute", description = "The extracted attribute must be single-valued")
	public boolean checkExtractedAttribute(EAttribute extractedAttribute) {
		return !extractedAttribute.isMany();
	}

	/** {@description} */
	@EdaptParameter(description = "The package in which the extracted class is created")
	public EPackage contextPackage;

	/** {@description} */
	@EdaptParameter(description = "The name of the extracted class")
	public String extractedClassName;

	/** {@description} */
	@EdaptParameter(description = "The reference from the context class to the extracted class")
	public String referenceName;

	/** {@description} */
	@EdaptParameter(description = "The container class for the extracted class")
	public EClass containerClass;

	/** {@description} */
	@EdaptParameter(description = "The name of the containment reference from the container class to the extracted class")
	public String containerReferenceName;

	/** {@inheritDoc} */
	@Override
	public void execute(Metamodel metamodel, Model model) {
		final EClass contextClass = extractedAttribute.getEContainingClass();

		// metamodel adaptation
		final EClass extractedClass = MetamodelFactory.newEClass(contextPackage,
			extractedClassName);
		extractedClass.getEStructuralFeatures().add(extractedAttribute);
		extractedAttribute.setLowerBound(1);

		final EReference reference = MetamodelFactory.newEReference(contextClass,
			referenceName, extractedClass, 0, 1, false);

		final EReference containerReference = MetamodelFactory.newEReference(
			containerClass, containerReferenceName, extractedClass, 0, -1,
			true);

		// model migration
		for (final Instance contextElement : model.getAllInstances(contextClass)) {
			final Object value = contextElement.unset(extractedAttribute);
			if (value != null) {
				Instance containerElement = contextElement;
				while (containerElement != null
					&& !containerElement.instanceOf(containerClass)) {
					containerElement = containerElement.getContainer();
				}
				if (containerElement != null) {
					Instance extractedElement = getExtractedElement(
						containerElement, containerReference,
						extractedAttribute, value);
					if (extractedElement == null) {
						extractedElement = model.newInstance(extractedClass);
						extractedElement.set(extractedAttribute, value);
						containerElement.add(containerReference,
							extractedElement);
					}
					contextElement.set(reference, extractedElement);
				}
			}
		}
	}

	/** Get the extracted element that has a certain value for an attribute. */
	private Instance getExtractedElement(Instance containerElement,
		EReference containerReference, EAttribute extractedAttribute,
		Object value) {
		final List<Instance> elements = containerElement.get(containerReference);
		for (final Instance element : elements) {
			if (value.equals(element.get(extractedAttribute))) {
				return element;
			}
		}
		return null;
	}
}

Back to the top