| /******************************************************************************* |
| * Copyright (c) 2016 ALL4TEC & 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: |
| * ALL4TEC & CEA LIST - initial API and implementation |
| ******************************************************************************/ |
| package org.polarsys.esf.core.profile.esfarchitectureconcepts.application; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.papyrus.uml.tools.utils.PackageUtil; |
| import org.eclipse.uml2.uml.Class; |
| import org.eclipse.uml2.uml.Comment; |
| import org.eclipse.uml2.uml.Connector; |
| import org.eclipse.uml2.uml.Element; |
| import org.eclipse.uml2.uml.Model; |
| import org.eclipse.uml2.uml.Port; |
| import org.eclipse.uml2.uml.Profile; |
| import org.eclipse.uml2.uml.Property; |
| import org.eclipse.uml2.uml.Type; |
| import org.eclipse.uml2.uml.util.UMLUtil; |
| import org.polarsys.esf.core.profile.esfarchitectureconcepts.set.ESFArchitectureConceptsSet; |
| import org.polarsys.esf.core.utils.ModelUtil; |
| import org.polarsys.esf.esfarchitectureconcepts.SDirection; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.ESFArchitectureConceptsPackage; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.SBlock; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.SConnector; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.SModel; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.SPart; |
| import org.polarsys.esf.esfarchitectureconcepts.impl.SPort; |
| |
| /** |
| * Class responsible of the ESFArchitectureConcepts' annotation application on the model. |
| * |
| * @author $Author: ymunoz $ |
| * @version $Revision: 168 $ |
| */ |
| public final class ApplyESFArchitectureConceptsAnnotation { |
| |
| /** Label of the command to apply annotation on the UML model. */ |
| private static final String CMD_LABEL_APPLY_ANNOTATION_ON_UML_MODEL = |
| "ApplyESFArchitectureConceptsAnnotation: Apply Annotation on the UML model"; //$NON-NLS-1$ |
| |
| /** Key words for Output port. */ |
| private static final String[] OUTPUT = {"out", "output"}; //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| /** Key words for Input port. */ |
| private static final String[] INPUT = {"in", "input"}; //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| /** Regular expression used to verify if a line contains more than one word. */ |
| private static final String REGEX_MORE_THAN_ONE_WORD = "(\\w)(\\s)(\\w)"; //$NON-NLS-1$ |
| |
| /** |
| * Default constructor. |
| */ |
| private ApplyESFArchitectureConceptsAnnotation() { |
| } |
| |
| /** |
| * Verify if the ESFArchitectureConcepts profile is applied to this model. |
| * |
| * @param pModel The model |
| * @return True or false |
| */ |
| public static Boolean isProfileApplied(final Model pModel) { |
| return pModel.isProfileApplied(getProfile(pModel)); |
| } |
| |
| /** |
| * Retrieve the ESFArchitectureConcepts profile. |
| * |
| * @param pModel The model |
| * @return The ESFArchitectureConcepts profile |
| */ |
| public static Profile getProfile(final Model pModel) { |
| Profile vESFArchiConceptsProfile = (Profile) PackageUtil |
| .loadPackage(URI.createURI(ESFArchitectureConceptsSet.PROFILE_PATH), pModel.eResource().getResourceSet()); |
| return vESFArchiConceptsProfile; |
| } |
| |
| /** |
| * Apply the ESFArchitectureConcepts profile to this model. |
| * |
| * @param pModel The model |
| */ |
| public static void applyProfile(final Model pModel) { |
| // Retrieve the ESFArchitectureConcepts profile and apply it |
| Profile vESFArchiConceptsProfile = getProfile(pModel); |
| |
| if (vESFArchiConceptsProfile != null) { |
| PackageUtil.applyProfile(pModel, vESFArchiConceptsProfile, true); |
| } |
| } |
| |
| /** |
| * Apply ESFArchitectureConcepts' annotation on the UML model. |
| * |
| * @param pModel The UML model object {@link Model} |
| */ |
| public static void applyAnnotationOnUMLModel(final Model pModel) { |
| |
| TransactionalEditingDomain vDomain = ModelUtil.getTransactionalEditingDomain(pModel); |
| |
| RecordingCommand vApplyAnnotationCmd = new RecordingCommand(vDomain, CMD_LABEL_APPLY_ANNOTATION_ON_UML_MODEL) { |
| |
| /** |
| * ESFArchitectureConcepts' application annotation on the UML model. |
| */ |
| @Override |
| protected void doExecute() { |
| if (!isProfileApplied(pModel)) { |
| applyProfile(pModel); |
| } |
| // Apply the SModel stereotype on the UML model object "Model" |
| if (UMLUtil.getStereotypeApplication(pModel, SModel.class) == null) { |
| UMLUtil.StereotypeApplicationHelper.getInstance(pModel) |
| .applyStereotype(pModel, ESFArchitectureConceptsPackage.eINSTANCE.getSModel()); |
| } |
| // Walk through the Model and apply the ESFArchitectureConcepts' annotation |
| walkThroughModelAndApplyAnnotation(pModel); |
| } |
| |
| }; |
| |
| try { |
| vDomain.getCommandStack().execute(vApplyAnnotationCmd); |
| } catch (final IllegalArgumentException pException) { |
| ESFArchitectureConceptsProfileApplicationActivator.logError( |
| "Error during the application of the ESFArchitectureConcepts annotation on the model", //$NON-NLS-1$ |
| pException); |
| } |
| } |
| |
| /** |
| * Walk the Model and apply the ESFArchitectureConcepts' annotation. |
| * |
| * @param pModel the UML model object {@link Model} |
| */ |
| private static void walkThroughModelAndApplyAnnotation(final Model pModel) { |
| for (Element vElement : pModel.allOwnedElements()) { |
| // Apply the SBlock stereotype on the UML model object "Class" |
| if ((vElement instanceof Class) && (UMLUtil.getStereotypeApplication(vElement, SBlock.class) == null)) { |
| UMLUtil.StereotypeApplicationHelper.getInstance(vElement) |
| .applyStereotype(vElement, ESFArchitectureConceptsPackage.eINSTANCE.getSBlock()); |
| |
| // Apply the SPort stereotype on the UML model object "Port" |
| } else if ((vElement instanceof Port) |
| && (UMLUtil.getStereotypeApplication(vElement, SPort.class) == null)) { |
| UMLUtil.StereotypeApplicationHelper.getInstance(vElement) |
| .applyStereotype(vElement, ESFArchitectureConceptsPackage.eINSTANCE.getSPort()); |
| Port vPort = (Port) vElement; |
| SDirection vPortDirection = findPortDirection(vPort); |
| |
| // If the port direction is not default direction |
| if (SDirection.INOUT != vPortDirection) { |
| // Set the port direction |
| SPort vSPort = UMLUtil.getStereotypeApplication(vPort, SPort.class); |
| vSPort.setSDirection(vPortDirection); |
| } |
| |
| // Apply the SConnector stereotype on the UML model object "Connector" |
| } else if ((vElement instanceof Connector) |
| && (UMLUtil.getStereotypeApplication(vElement, SConnector.class) == null)) { |
| UMLUtil.StereotypeApplicationHelper.getInstance(vElement) |
| .applyStereotype(vElement, ESFArchitectureConceptsPackage.eINSTANCE.getSConnector()); |
| |
| // Apply the SPart stereotype on the UML model object "Property" typed by a Class |
| } else if ((vElement instanceof Property) |
| && (UMLUtil.getStereotypeApplication(vElement, SPart.class) == null)) { |
| Type vType = ((Property) vElement).getType(); |
| if ((vType != null) && (vType instanceof Class)) { |
| UMLUtil.StereotypeApplicationHelper.getInstance(vElement) |
| .applyStereotype(vElement, ESFArchitectureConceptsPackage.eINSTANCE.getSPart()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Find port direction from comments. |
| * |
| * @param pPort The UML model object {@link Port} |
| * @return The SDirection |
| */ |
| private static SDirection findPortDirection(final Port pPort) { |
| List<Comment> vCommentsList = pPort.getOwnedComments(); |
| SDirection vSDirection = SDirection.INOUT; |
| |
| Iterator<Comment> vIterator = vCommentsList.iterator(); |
| while (SDirection.INOUT == vSDirection && vIterator.hasNext()) { |
| Comment vComment = vIterator.next(); |
| |
| String vBody = vComment.getBody(); |
| Pattern vMoreThanOneWord = Pattern.compile(REGEX_MORE_THAN_ONE_WORD); |
| Matcher vMatcher = vMoreThanOneWord.matcher(vBody); |
| |
| // Verify if the first line of the comment contains the only one word |
| if (!vMatcher.find()) { |
| boolean vFind = false; |
| int vIndex = 0; |
| |
| // Verify if the comment contains "in" or "input" substring |
| while ((!vFind) && (INPUT.length > vIndex)) { |
| String vInput = INPUT[vIndex]; |
| if (StringUtils.lowerCase(vBody).contains(vInput)) { |
| vSDirection = SDirection.IN; |
| vFind = true; |
| } |
| vIndex++; |
| } |
| |
| if (vSDirection.equals(SDirection.INOUT)) { |
| vIndex = 0; |
| // Verify if the comment contains "out" or "output" substring |
| while ((!vFind) && (OUTPUT.length > vIndex)) { |
| String vOutput = OUTPUT[vIndex]; |
| if (StringUtils.lowerCase(vBody).contains(vOutput)) { |
| vSDirection = SDirection.OUT; |
| vFind = true; |
| } |
| vIndex++; |
| } |
| } |
| } |
| } |
| |
| return vSDirection; |
| } |
| } |