Skip to main content
summaryrefslogtreecommitdiffstats
blob: 6dda059f61027d66c49be90da7e276e2ec2a2b98 (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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/*****************************************************************************
 * Copyright (c) 2010 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.marte.textedit.stereotypeapplicationwithvsl.xtext.ui.contributions;

import java.util.ArrayList;
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.ecore.EObject;
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.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.papyrus.extensionpoints.editors.configuration.ICustomDirectEditorConfiguration;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.marte.textedit.stereotypeapplicationwithvsl.xtext.stereotypeApplicationWithVSL.ExpressionValueRule;
import org.eclipse.papyrus.marte.textedit.stereotypeapplicationwithvsl.xtext.stereotypeApplicationWithVSL.StereotypeApplicationRule;
import org.eclipse.papyrus.marte.textedit.stereotypeapplicationwithvsl.xtext.stereotypeApplicationWithVSL.StereotypeApplicationsRule;
import org.eclipse.papyrus.marte.textedit.stereotypeapplicationwithvsl.xtext.stereotypeApplicationWithVSL.TagSpecificationRule;
import org.eclipse.papyrus.marte.textedit.stereotypeapplicationwithvsl.xtext.ui.internal.StereotypeApplicationWithVSLActivator;
import org.eclipse.papyrus.marte.vsl.extensions.VSLSerializationUtil;
import org.eclipse.papyrus.marte.vsl.ui.contentassist.VSLProposalUtils;
import org.eclipse.papyrus.marte.vsl.vSL.CollectionOrTuple;
import org.eclipse.papyrus.marte.vsl.vSL.Expression;
import org.eclipse.papyrus.marte.vsl.vSL.NameOrChoiceOrBehaviorCall;
import org.eclipse.papyrus.marte.vsl.validation.VSLJavaValidator;
import org.eclipse.papyrus.uml.xtext.integration.DefaultXtextDirectEditorConfiguration;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.util.UMLUtil;

import com.google.inject.Injector;

/**
 * @author CEA LIST
 *
 *
 */
public class StereotypeApplicationPopupEditorConfigurationContribution extends DefaultXtextDirectEditorConfiguration implements ICustomDirectEditorConfiguration {


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.papyrus.infra.gmfdiag.xtext.glue.PopupEditorConfiguration#getTextToEdit(java.lang.Object)
	 */

	@Override
	public String getTextToEdit(Object editedObject) {
		if(editedObject instanceof Element) {
			Element stereotypedElement = (Element)editedObject;
			String textToEdit = "";

			for(Stereotype stereotype : stereotypedElement.getAppliedStereotypes()) {
				textToEdit += "<<" + stereotype.getName() + ">>";
				boolean first = true;
				for(Property p : stereotype.getAllAttributes()) {
					if(!(p.getName().startsWith("base_") || p.isDerived())) {
						Object value = stereotypedElement.getValue(stereotype, p.getName());
						if(value instanceof EnumerationLiteral) {
							if(p.getType() instanceof Stereotype || p.getType() instanceof org.eclipse.uml2.uml.Class) {
								value = VSLProposalUtils.getNameLabel((NamedElement)value);
							} else {
								value = ((NamedElement)value).getName();
							}
						} else if(value instanceof NamedElement) {
							value = VSLProposalUtils.getNameLabel((NamedElement)value);
						} else if(value instanceof EObject) {
							Element stereoElement = UMLUtil.getBaseElement((EObject)value);
							if(stereoElement != null && stereoElement instanceof NamedElement) {
								value = VSLProposalUtils.getNameLabel(((NamedElement)stereoElement));
							} else {
								// TODO ... Compute a label in case of Element without Name
								value = "/* The referenced element is not a named element. You should edit this stereotype with the property view */";
							}
						} else if(value instanceof String) {
							if((p.getType() instanceof PrimitiveType) && (p.getType().getName().equals("String"))) {
								// quote strings
								value = "\"" + value + "\"";
							}
						}

						if(value != null && value instanceof List) {
							List listOfValues = (List)value;
							if(!listOfValues.isEmpty()) {
								String collString = "{";
								boolean nestedFirst = true;
								for(Object o : listOfValues) {
									if(!nestedFirst) {
										collString += ", ";
									} else {
										nestedFirst = false;
									}
									if(o instanceof EnumerationLiteral) {
										if(p.getType() instanceof Stereotype || p.getType() instanceof org.eclipse.uml2.uml.Class) {
											value = VSLProposalUtils.getNameLabel((NamedElement)value);
										} else {
											value = ((NamedElement)value).getName();
										}
									} else if(o instanceof NamedElement) {
										collString += VSLProposalUtils.getNameLabel((NamedElement)o);
									} else if(o instanceof EObject) {
										Element stereoElement = UMLUtil.getBaseElement((EObject)o);
										if(stereoElement != null && stereoElement instanceof NamedElement) {
											collString += VSLProposalUtils.getNameLabel((NamedElement)stereoElement);
										} else {
											// TODO ... Compute a label in case of Element without Name
											collString += "/* The referenced element is not a named element. You should edit this stereotype with the property view */";
										}
									} else {
										// o is a string
										collString += o;
									}
								}
								collString += "}";
								if(first) {
									textToEdit += "\n";
									first = false;
								} else {
									textToEdit += ",\n";
								}
								textToEdit += p.getName() + " = " + collString;
							}
						} else if(value != null) {
							if(first) {
								textToEdit += "\n";
								first = false;
							} else {
								textToEdit += ",\n";
							}
							textToEdit += p.getName() + " = " + value;
						}
					}
				}
				textToEdit += "\n\n";
			}

			return textToEdit;
		}

		return "// not an Element";
	}

	/**
	 * @author CEA LIST
	 *
	 *         A command for updating the context UML model
	 */
	protected class UpdateStereotypeApplicationsCommand extends AbstractTransactionalCommand {

		private Element stereotypedElement;

		private StereotypeApplicationsRule stereotypeApplicationsObject;

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doExecuteWithResult(org.eclipse.core.runtime.IProgressMonitor
		 * , org.eclipse.core.runtime.IAdaptable)
		 */

		@Override
		protected CommandResult doExecuteWithResult(IProgressMonitor arg0, IAdaptable arg1) throws ExecutionException {

			////////////////////////////////////////////////////////////
			// First delete any stereotype application associated with the stereotyped element
			////////////////////////////////////////////////////////////
			List<Stereotype> appliedStereotypes = stereotypedElement.getAppliedStereotypes();
			for(Stereotype s : appliedStereotypes) {
				stereotypedElement.unapplyStereotype(s);
			}


			//////////////////////////////////////////////////////////////////////////////////////////////////
			// Then extract any relevant information from the StereotypeApplicationRules object, and update the stereotypedElement
			//////////////////////////////////////////////////////////////////////////////////////////////////
			for(StereotypeApplicationRule sApp : stereotypeApplicationsObject.getStereotypeApplications()) {
				Stereotype stereotype = sApp.getStereotype();
				stereotypedElement.applyStereotype(stereotype);
				for(TagSpecificationRule tag : sApp.getTagSpecification()) {
					Property property = tag.getProperty();
					Type type = property.getType();
					ExpressionValueRule value = tag.getValue();
					Object valueRepresentation = null;

					// TODO shouldStoreObjectsAndNotStrings is not enough. Should have a specific boolean for the case of stereotype applications
					boolean shouldStoreObjectsAndNotStrings = (type instanceof Stereotype || type instanceof org.eclipse.uml2.uml.Class);
					boolean propertyIsACollection = VSLJavaValidator.isACollection(value.getExpression()) != null;

					if(!propertyIsACollection) {
						if(!shouldStoreObjectsAndNotStrings) {
							valueRepresentation = VSLSerializationUtil.printExpression(value.getExpression());
							if((type instanceof PrimitiveType) && (type.getName().equals("String")) && (valueRepresentation instanceof String)) {
								// unquote Strings, remove 1st and last character
								String stringValue = (String)valueRepresentation;
								if(stringValue.length() > 2) {
									valueRepresentation = stringValue.substring(1, stringValue.length() - 1);
								} else {
									valueRepresentation = "";
								}
							}
						} else {
							NameOrChoiceOrBehaviorCall nameRule = VSLSerializationUtil.extractNameReference(value.getExpression());
							if(nameRule != null) {
								if(!(property.getType() instanceof Stereotype)) {
									valueRepresentation = nameRule.getId();
								} else {
									valueRepresentation = nameRule.getId().getStereotypeApplication(((Stereotype)property.getType()));
								}
							}
							// TODO: specific case of stereotype applications
						}
					} else {
						// the property has an upper bound > 1
						if(!shouldStoreObjectsAndNotStrings) {
							List<String> listOfValues = new ArrayList<String>();
							CollectionOrTuple collection = VSLJavaValidator.isACollection(value.getExpression());
							for(Expression e : collection.getListOfValues().getValues()) {
								listOfValues.add(VSLSerializationUtil.printExpression(e));
							}
							valueRepresentation = listOfValues;
						} else {
							List<Object> listOfValues = new ArrayList<Object>();
							CollectionOrTuple collection = VSLJavaValidator.isACollection(value.getExpression());
							for(Expression e : collection.getListOfValues().getValues()) {
								NameOrChoiceOrBehaviorCall nameRule = VSLSerializationUtil.extractNameReference(e);
								if(nameRule != null) {
									if(!(property.getType() instanceof Stereotype)) {
										listOfValues.add(nameRule.getId());
									} else {
										listOfValues.add(nameRule.getId().getStereotypeApplication(((Stereotype)property.getType())));
									}
								}
								// TODO: specific case of stereotype applications
							}
							valueRepresentation = listOfValues;
						}
					}

					stereotypedElement.setValue(stereotype, property.getName(), valueRepresentation);

				}
			}

			return CommandResult.newOKCommandResult(stereotypedElement);
		}

		public UpdateStereotypeApplicationsCommand(Element stereotypedElement, StereotypeApplicationsRule stereotypeApplicationsObject) {
			super((TransactionalEditingDomain)EMFHelper.resolveEditingDomain(stereotypedElement), "Stereotype Applications Update", getWorkspaceFiles(stereotypedElement));
			this.stereotypedElement = stereotypedElement;
			this.stereotypeApplicationsObject = stereotypeApplicationsObject;
		}
	}

	@Override
	public Injector getInjector() {
		return StereotypeApplicationWithVSLActivator.getInstance().getInjector(StereotypeApplicationWithVSLActivator.ORG_ECLIPSE_PAPYRUS_MARTE_TEXTEDIT_STEREOTYPEAPPLICATIONWITHVSL_XTEXT_STEREOTYPEAPPLICATIONWITHVSL);
	}

	@Override
	protected ICommand getParseCommand(EObject modelObject, EObject xtextObject) {
		// first: retrieves / determines if the xtextObject is a TransitionRule object
		EObject modifiedObject = xtextObject;
		if(!(modelObject instanceof Element)) {
			return UnexecutableCommand.INSTANCE;
		}
		while(xtextObject != null && !(xtextObject instanceof StereotypeApplicationsRule)) {
			modifiedObject = modifiedObject.eContainer();
		}
		if(modifiedObject == null) {
			return UnexecutableCommand.INSTANCE;
		}

		Element stereotypedElement = (Element)modelObject;
		StereotypeApplicationsRule stereotypeApplicationsObject = (StereotypeApplicationsRule)xtextObject;

		// Creates and executes the update command
		UpdateStereotypeApplicationsCommand updateCommand = new UpdateStereotypeApplicationsCommand(stereotypedElement, stereotypeApplicationsObject);
		return updateCommand;
	}
}

Back to the top