Skip to main content
summaryrefslogtreecommitdiffstats
blob: 0f69b4d04e021f96404f3487121e9a8577872a14 (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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*****************************************************************************
 * Copyright (c) 2011-2012 CEA LIST.
 *
 * 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:
 *		
 *		CEA LIST - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.sysml.service.types.helper.advice;

import java.util.List;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.ConfigureElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.sysml.service.types.Activator;
import org.eclipse.papyrus.uml.service.types.utils.ClassifierUtils;
import org.eclipse.papyrus.uml.service.types.utils.NamedElementHelper;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;

/**
 * Edit helper advice for {@link Association} with "aggregation = none" (used for creation purpose only).
 */
public class AssociationNoneEditHelperAdvice extends AssociationEditHelperAdvice {

	/**
	 * This method provides the source type provided as {@link ConfigureRequest} parameter.
	 * 
	 * @return the target role
	 */
	protected Classifier getSourceOwnerType(ConfigureRequest req) {
		Classifier result = null;
		Object paramObject = req.getParameter(CreateRelationshipRequest.SOURCE);
		if(paramObject instanceof Classifier) {
			result = (Classifier)paramObject;
		}

		return result;
	}

	/**
	 * This method provides the target type provided as {@link ConfigureRequest} parameter.
	 * 
	 * @return the target role
	 */
	protected Classifier getTargetOwnerType(ConfigureRequest req) {
		Classifier result = null;
		Object paramObject = req.getParameter(CreateRelationshipRequest.TARGET);
		if(paramObject instanceof Classifier) {
			result = (Classifier)paramObject;
		}

		return result;
	}

	/**
	 * Creates a new {@link Property} from the propertyType in the propertyContainer
	 * 
	 * @param propertyContainer
	 *        the container of the {@link Property}
	 * @param propertyType
	 *        the type of the {@link Property}
	 * @return the new {@link Property}
	 * @throws ExecutionException 
	 */	
	protected Property createTargetProperty(Property targetProperty, Classifier propertyContainer, Type propertyType, Association association, TransactionalEditingDomain editingDomain, IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
		addSourceInModel(targetProperty, propertyContainer, propertyType, association);
		setPropertyType(targetProperty, propertyType, editingDomain, progressMonitor, info);
		setPropertyName(targetProperty);
		return targetProperty;
	}
	
	protected Property createSourceProperty(Property sourceProperty, Classifier propertyContainer, Type propertyType, Association association, TransactionalEditingDomain editingDomain, IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
		addTargetInModel(sourceProperty, propertyContainer, propertyType, association);
		setPropertyType(sourceProperty, propertyType, editingDomain, progressMonitor, info);
		setPropertyName(sourceProperty);
		return sourceProperty;
	}
	
	protected void setPropertyType(Property property, Type propertyType, TransactionalEditingDomain editingDomain, IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
		// Set type using all AdviceHelper (use ServiceEdit instead of manually set)
		SetRequest request = new SetRequest(property, UMLPackage.eINSTANCE.getTypedElement_Type(), propertyType);
		request.setEditingDomain(editingDomain);	
		IElementEditService commandProvider = ElementEditServiceUtils.getCommandProvider(property);
		ICommand editCommand = commandProvider.getEditCommand(request);
		editCommand.execute(progressMonitor, info);
	}

	private void setPropertyName(Property property) {
		String baseName = property.getType().getName().toLowerCase();
		Element owner = property.getOwner();
		if (owner instanceof Classifier) {
			List<Property> ownedAttributes = ClassifierUtils.getOwnedAttributes((Classifier)owner);
			String defaultNameWithIncrementFromBase = NamedElementHelper.getDefaultNameWithIncrementFromBase(
					property.getType().getName().toLowerCase(), ownedAttributes, "_");
			property.setName(defaultNameWithIncrementFromBase);
		}
		else {
			// default
			property.setName(baseName);
		}
	}

	/**
	 * This method has to be specialized by subclasses (AggregationKind)
	 * @param sourceProperty
	 * 			The property to configure
	 */
	protected void configureSourceProperty(Property sourceProperty)  {
		// do nothing
	}

	/**
	 * This method has to be specialized by subclasses (AggregationKind)
	 * @param sourceProperty
	 * 			The property to configure
	 */
	protected void configureTargetProperty(Property targetProperty) {
		// do nothing
	}

	/**
	 * This method has to be specialized by subclasses (owner)
	 * 
	 * @param sourceEnd
	 *        the semantic end
	 * @param owner
	 *        the end container
	 * @param targetType
	 *        the target type
	 * @param association
	 *        the association
	 * @throws UnsupportedOperationException
	 */
	protected void addSourceInModel(final Property sourceEnd, Classifier owner, Type targetType, Association association) throws UnsupportedOperationException {
		// set the container in order to allow Stereotype appliance
		boolean added = ClassifierUtils.addOwnedAttribute(owner, sourceEnd); 
		if(!added) {
			throw new UnsupportedOperationException("Cannot add a Property on Classifier " + owner.getQualifiedName());
		}
	}

	/**
	 * This method has to be specialized by subclasses (owner)
	 * 
	 * @param targetEnd
	 *        the semantic end
	 * @param owner
	 *        the end container
	 * @param sourceType
	 *        the source type
	 * @param association
	 *        the association
	 * @throws UnsupportedOperationException
	 */
	protected void addTargetInModel(Property targetEnd, Classifier owner, Type sourceType, Association association) {
		// set the container in order to allow Stereotype appliance
		boolean added = ClassifierUtils.addOwnedAttribute(owner, targetEnd); 
		if(!added) {
			throw new UnsupportedOperationException("Cannot add a Property on Classifier " + owner.getQualifiedName());
		}
	}

	/**
	 * <pre>
	 * {@inheritDoc}
	 * 
	 * Complete the {@link Association} creation by setting its ends.
	 * 
	 * </pre>
	 */
	@Override
	protected ICommand getBeforeConfigureCommand(final ConfigureRequest request) {

		final Association association = (Association)request.getElementToConfigure();
		final Classifier sourceType = getSourceOwnerType(request);
		final Classifier targetType = getTargetOwnerType(request);

		if((sourceType == null) || (targetType == null)) {
			return UnexecutableCommand.INSTANCE;
		}

		return new ConfigureElementCommand(request) {

			protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {

				try {
					Property targetProperty = UMLFactory.eINSTANCE.createProperty();
					Property sourceProperty = UMLFactory.eINSTANCE.createProperty();

					// TODO: problem with SysML. Link are inversed. A -> B => memberEnd={a, b} instead of {b, a}.
					// Problem seems to come from cached derivedFeature /endTypes
					// So we force to set memberEnd in this order before doing anything with the created properties
					association.getMemberEnds().add(targetProperty);
					association.getMemberEnds().add(sourceProperty);

					// Create source and target ends
					createTargetProperty(targetProperty, sourceType, targetType, association, request.getEditingDomain(), progressMonitor, info);
					configureSourceProperty(targetProperty);
					createSourceProperty(sourceProperty, targetType, sourceType, association, request.getEditingDomain(), progressMonitor, info);
					configureTargetProperty(sourceProperty);
	
				} catch (Exception e) {
					Activator.log.error(e);
					return CommandResult.newCancelledCommandResult();
				}

				return CommandResult.newOKCommandResult(association);
			}
		};
	}
}

Back to the top