View Javadoc
1   /*****************************************************************************
2    * Copyright (c) 2015 CEA LIST.
3    *
4    *
5    * All rights reserved. This program and the accompanying materials
6    * are made available under the terms of the Eclipse Public License v1.0
7    * which accompanies this distribution, and is available at
8    * http://www.eclipse.org/legal/epl-v10.html
9    *
10   * Contributors:
11   *  Francois Le Fevre francois.le-fevre@cea.fr  - Initial API and implementation
12   *****************************************************************************/
13  package org.eclipse.papyrus.sysml14.diagram.common.css.dom;
14  
15  
16  
17  import java.util.LinkedList;
18  import java.util.List;
19  
20  import org.eclipse.emf.ecore.EObject;
21  import org.eclipse.emf.ecore.EReference;
22  import org.eclipse.emf.ecore.EStructuralFeature;
23  import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
24  import org.eclipse.gmf.runtime.emf.type.core.IElementMatcher;
25  import org.eclipse.gmf.runtime.emf.type.core.ISpecializationType;
26  import org.eclipse.gmf.runtime.notation.BasicCompartment;
27  import org.eclipse.gmf.runtime.notation.DecorationNode;
28  import org.eclipse.gmf.runtime.notation.View;
29  import org.eclipse.papyrus.infra.gmfdiag.css.dom.GMFElementAdapter;
30  import org.eclipse.papyrus.infra.gmfdiag.css.engine.ExtendedCSSEngine;
31  import org.eclipse.papyrus.infra.tools.util.ListHelper;
32  import org.eclipse.papyrus.sysml14.diagram.common.css.helper.CSSDOMSYSMLSemanticElementHelper;
33  import org.eclipse.papyrus.sysml14.service.types.util.SysMLServiceTypeUtil;
34  import org.eclipse.papyrus.sysml14.util.DeprecatedElementUtil;
35  import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayConstant;
36  import org.eclipse.papyrus.uml.diagram.common.stereotype.display.helper.StereotypeDisplayUtil;
37  import org.eclipse.uml2.uml.Element;
38  import org.eclipse.uml2.uml.NamedElement;
39  import org.eclipse.uml2.uml.Property;
40  import org.eclipse.uml2.uml.Stereotype;
41  
42  /**
43   * DOM Element Adapter for SYSML Elements
44   *
45   * Supports applied stereotypes and stereotype properties
46   *
47   * @author Francois Le Fevre
48   *
49   */
50  public class GMFSYSMLElementAdapter extends GMFElementAdapter {
51  
52  
53  	/**
54  	 * Name of the CSS Simple Selector to match on the Stereotype Compartment Shape
55  	 */
56  	private static final String STEREOTYPE_COMMENT = "StereotypeComment"; //$NON-NLS-1$
57  
58  	/** The stereotype helper. */
59  	public final StereotypeDisplayUtil stereotypeHelper = StereotypeDisplayUtil.getInstance();
60  
61  	/** The Constant IS_CONSTRAINT. */
62  	private static final String IS_CONSTRAINT = "isConstraint"; //$NON-NLS-1$
63  
64  	/** The Constant IS_PART. */
65  	private static final String IS_PART = "isPart"; //$NON-NLS-1$
66  
67  	/** The Constant IS_REFERENCE. */
68  	private static final String IS_REFERENCE = "isReference"; //$NON-NLS-1$	
69  
70  	/** The Constant APPLIED_STEREOTYPES_PROPERTY. */
71  	public static final String APPLIED_STEREOTYPES_PROPERTY = "appliedStereotypes"; //$NON-NLS-1$
72  
73  	/** The Constant DEPRECATED. */
74  	public static final String DEPRECATED = "deprecated"; //$NON-NLS-1$
75  	
76  
77  	/**
78  	 * The CSS Separator for qualifiers, when we must use CSS ID
79  	 * When we can use CSS String, we use the standard UML "::" qualifier separator
80  	 *
81  	 * NOTE: Separator "__" does not work
82  	 */
83  	public static final String QUALIFIER_SEPARATOR = "--"; //$NON-NLS-1$
84  
85  	public GMFSYSMLElementAdapter(View view, ExtendedCSSEngine engine) {
86  		super(view, engine);
87  		helper = CSSDOMSYSMLSemanticElementHelper.getInstance();
88  	}
89  
90  	/**
91  	 * {@inheritDoc}
92  	 *
93  	 * Applied Stereotypes are manipulated as DOM Attributes
94  	 */
95  	@Override
96  	protected String doGetAttribute(String attr) {
97  		String parentValue = super.doGetAttribute(attr);
98  
99  		if (parentValue != null) {
100 			return parentValue;
101 		}
102 
103 		// get stereotype Label attribute
104 		if (stereotypeHelper.isStereotypeLabel(semanticElement)) {
105 			String value = getStereotypeLabelAttribute(attr);
106 			if (value != null && !value.isEmpty()) {
107 				return value;
108 			}
109 		}
110 
111 		// get stereotype Compartment attribute
112 		if (stereotypeHelper.isStereotypeCompartment(semanticElement) || stereotypeHelper.isStereotypeBrace(semanticElement)) {
113 			String value = getStereotypeCompartmentAttribute(attr);
114 			if (value != null && !value.isEmpty()) {
115 				return value;
116 			}
117 		}
118 
119 		// get stereotype Property attribute
120 		if (stereotypeHelper.isStereotypeProperty(semanticElement) || stereotypeHelper.isStereotypeBraceProperty(semanticElement)) {
121 			String value = getStereotypePropertyAttribute(attr);
122 			if (value != null && !value.isEmpty()) {
123 				return value;
124 			}
125 		}
126 
127 		if (semanticElement instanceof Element) {
128 
129 			// Applied stereotypes
130 			Element currentElement = (Element) semanticElement;
131 
132 			// Get applied STereotypes Attributes
133 			if (APPLIED_STEREOTYPES_PROPERTY.equals(attr)) {
134 				List<String> appliedStereotypes = new LinkedList<String>();
135 				for (Stereotype stereotype : currentElement.getAppliedStereotypes()) {
136 					appliedStereotypes.add(stereotype.getName());
137 					appliedStereotypes.add(stereotype.getQualifiedName());
138 				}
139 				if (!appliedStereotypes.isEmpty()) {
140 					return ListHelper.deepToString(appliedStereotypes, CSS_VALUES_SEPARATOR);
141 				}
142 			}
143 			for (EObject stereotypeApplication : currentElement.getStereotypeApplications()) {
144 				EStructuralFeature feature = stereotypeApplication.eClass().getEStructuralFeature(attr);
145 				if (feature != null) {
146 					if (feature.isMany()) {
147 						List<?> values = (List<?>) stereotypeApplication.eGet(feature);
148 						List<String> cssValues = new LinkedList<String>();
149 						for (Object value : values) {
150 							cssValues.add(getCSSValue(feature, value));
151 						}
152 						return ListHelper.deepToString(cssValues, CSS_VALUES_SEPARATOR);
153 					} else {
154 						Object value = stereotypeApplication.eGet(feature);
155 						return getCSSValue(feature, value);
156 					}
157 				}
158 			}
159 
160 			if (attr.contains(QUALIFIER_SEPARATOR)) {
161 				List<String> qualifiers = ListHelper.asList(attr.split(QUALIFIER_SEPARATOR)); // Writable list
162 				String propertyName = qualifiers.remove(qualifiers.size() - 1); // Last element is the property name
163 				// Remaining strings can be used to build the Stereotype's qualified name
164 				String stereotypeName = ListHelper.deepToString(qualifiers, "::"); //$NON-NLS-1$
165 				Stereotype appliedStereotype = currentElement.getAppliedStereotype(stereotypeName);
166 				if (appliedStereotype != null) {
167 					EObject stereotypeApplication = currentElement.getStereotypeApplication(appliedStereotype);
168 					EStructuralFeature feature = stereotypeApplication.eClass().getEStructuralFeature(propertyName);
169 					if (feature != null) {
170 						Object value = stereotypeApplication.eGet(feature);
171 						return getCSSValue(feature, value);
172 					}
173 				}
174 			}
175 			// manage of isConstraint=true attribute for Property
176 			if (IS_CONSTRAINT.equals(attr) && semanticElement instanceof Property) {
177 				IElementMatcher constraint = ((ISpecializationType) ElementTypeRegistry.getInstance().getType(SysMLServiceTypeUtil.ORG_ECLIPSE_PAPYRUS_SYSML14_CONSTRAINTPROPERTY)).getMatcher();
178 				return String.valueOf(constraint.matches((Property) semanticElement));
179 			}
180 			// manage of isPart=true attribute for Property
181 			if (IS_PART.equals(attr) && semanticElement instanceof Property) {
182 				IElementMatcher part = ((ISpecializationType) ElementTypeRegistry.getInstance().getType(SysMLServiceTypeUtil.ORG_ECLIPSE_PAPYRUS_SYSML14_PART)).getMatcher();
183 				return String.valueOf(part.matches((Property) semanticElement));
184 			}
185 			// manage of isReference=true attribute for Property
186 			if (IS_REFERENCE.equals(attr) && semanticElement instanceof Property) {
187 				IElementMatcher reference = ((ISpecializationType) ElementTypeRegistry.getInstance().getType(SysMLServiceTypeUtil.ORG_ECLIPSE_PAPYRUS_SYSML14_REFERENCE)).getMatcher();
188 				return String.valueOf(reference.matches((Property) semanticElement));
189 			}
190 			
191 			if(DEPRECATED.equals(attr)){
192 				return String.valueOf(DeprecatedElementUtil.isDeprecatedElement(semanticElement));
193 			}			
194 		}
195 		return null;
196 	}
197 
198 	/**
199 	 * Retrieve the Matching String Value for the StereotypeCompartment Element
200 	 *
201 	 * @param attr
202 	 *            Attribute of the String to match with
203 	 * @return The matching value for this Attribute
204 	 */
205 	protected String getStereotypeCompartmentAttribute(String attr) {
206 		if (StereotypeDisplayConstant.STEREOTYPE_COMPARTMENT_NAME.equals(attr)) {
207 
208 			BasicCompartment propertyCompartment = (BasicCompartment) semanticElement;
209 			return stereotypeHelper.getName(propertyCompartment);
210 
211 		}
212 		return "";//$NON-NLS-1$
213 	}
214 
215 	/**
216 	 * Retrieve the Matching String Value for the StereotypeCompartment Element
217 	 *
218 	 * @param attr
219 	 *            Attribute of the String to match with
220 	 * @return The matching value for this Attribute
221 	 */
222 	protected String getStereotypePropertyAttribute(String attr) {
223 		// CSS can match property level
224 		if (StereotypeDisplayConstant.STEREOTYPE_PROPERTY_NAME.equals(attr)) {
225 
226 			DecorationNode propertyLabel = (DecorationNode) semanticElement;
227 			if (propertyLabel.getElement() instanceof Property) {
228 				Property prop = (Property) propertyLabel.getElement();
229 				return prop.getName();
230 			}
231 			// CSS can match Container Name
232 		} else if (StereotypeDisplayConstant.STEREOTYPE_COMPARTMENT_NAME.equals(attr)) {
233 
234 			EObject propertyCompartment = ((DecorationNode) semanticElement).eContainer();
235 			if (stereotypeHelper.isStereotypeCompartment(propertyCompartment)) {
236 
237 				return stereotypeHelper.getName((DecorationNode) propertyCompartment);
238 			}
239 
240 		}
241 		return "";//$NON-NLS-1$
242 
243 	}
244 
245 	/**
246 	 * Get the matching Value of the Attribute
247 	 *
248 	 * @param attr
249 	 *            Attribute of the String to match with
250 	 * @return The matching value for this Attribute
251 	 */
252 	protected String getStereotypeLabelAttribute(String attr) {
253 
254 		if (StereotypeDisplayConstant.STEREOTYPE_LABEL_NAME.equals(attr)) {
255 			DecorationNode label = (DecorationNode) semanticElement;
256 			return stereotypeHelper.getName(label);
257 		}
258 
259 		if (KIND.equals(attr) && stereotypeHelper.isStereotypeLabel(semanticElement)) {
260 			return StereotypeDisplayConstant.STEREOTYPE_LABEL_TYPE;
261 		}
262 		return null;
263 	}
264 
265 	@Override
266 	protected String getCSSValue(EStructuralFeature feature, Object value) {
267 		if (feature instanceof EReference && value instanceof NamedElement) {
268 			String name = ((NamedElement) value).getName();
269 			return name == null || name.isEmpty() ? EMPTY_VALUE : name; // Bug 467716: Never return null or empty string if the value is not null
270 		}
271 		return super.getCSSValue(feature, value);
272 	}
273 
274 	/**
275 	 * @see org.eclipse.papyrus.infra.gmfdiag.css.dom.GMFElementAdapter#getLocalName()
276 	 *
277 	 * @return The Local name for the CSS matching.
278 	 */
279 	@Override
280 	public String getLocalName() {
281 		// In case of StereotypeComment type, the selector should match on the Stereotype Comment.
282 		if (localName == null && stereotypeHelper.isStereotypeComment(getNotationElement())) {
283 			return STEREOTYPE_COMMENT;
284 		}
285 		return super.getLocalName();
286 	}
287 }