blob: eb4069c5fc5efb0172c541cb9e7536275b4542b8 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}