/******************************************************************************* | |
* Copyright (C) 2018 Fondazione Bruno Kessler. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v2.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v20.html | |
* | |
* Contributors: | |
* Alberto Debiasi - initial API and implementation | |
* Luca Cristoforetti - initial API and implementation | |
******************************************************************************/ | |
package org.polarsys.chess.OSSImporter.core.utils; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Set; | |
import org.apache.log4j.Logger; | |
import org.eclipse.emf.common.util.BasicEList; | |
import org.eclipse.emf.common.util.EList; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.jface.viewers.ILabelProvider; | |
import org.eclipse.jface.viewers.LabelProvider; | |
import org.eclipse.papyrus.infra.core.services.ServiceException; | |
import org.eclipse.papyrus.infra.core.services.ServicesRegistry; | |
import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; | |
import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; | |
import org.eclipse.papyrus.infra.services.navigation.service.ExtendedNavigableElement; | |
import org.eclipse.papyrus.infra.services.navigation.service.NavigableElement; | |
import org.eclipse.papyrus.infra.services.navigation.service.NavigationService; | |
import org.eclipse.papyrus.infra.services.viewersearch.impl.ViewerSearchService; | |
import org.eclipse.papyrus.sysml.portandflows.FlowDirection; | |
import org.eclipse.papyrus.sysml.portandflows.FlowPort; | |
import org.eclipse.uml2.uml.Class; | |
import org.eclipse.uml2.uml.Constraint; | |
import org.eclipse.uml2.uml.FunctionBehavior; | |
import org.eclipse.uml2.uml.NamedElement; | |
import org.eclipse.uml2.uml.Property; | |
import org.eclipse.uml2.uml.Stereotype; | |
import org.eclipse.uml2.uml.Type; | |
import org.polarsys.chess.contracts.profile.chesscontract.ContractProperty; | |
import org.polarsys.chess.contracts.profile.chesscontract.FormalProperty; | |
import org.polarsys.chess.contracts.profile.chesscontract.util.ContractEntityUtil; | |
import org.polarsys.chess.contracts.profile.chesscontract.util.EntityUtil; | |
import org.polarsys.chess.service.core.model.ChessSystemModel; | |
public class ChessElementsUtil { | |
// Logger for messages | |
private static final Logger logger = Logger.getLogger(ChessElementsUtil.class); | |
private final ChessSystemModel chessSystemModel = ChessSystemModel.getInstance(); | |
private final EntityUtil entityUtil = EntityUtil.getInstance(); | |
private final ContractEntityUtil contractEntityUtil = ContractEntityUtil.getInstance(); | |
private static ChessElementsUtil chessElementsUtilInstance; | |
/** | |
* Gets an instance of the class if already present, or a new one if not. | |
* | |
* @return the instance of this class | |
*/ | |
public static ChessElementsUtil getInstance() { | |
if (chessElementsUtilInstance == null) { | |
chessElementsUtilInstance = new ChessElementsUtil(); | |
} | |
return chessElementsUtilInstance; | |
} | |
public void updateUmlFunctionBehaviour(FunctionBehavior functionBehavior, EList<Type> inputTypes,EList<String[]> inputMultiplicities, | |
Type outputType,String[] outputMultiplicity, HashMap<String, Boolean> mapFunctionBehaviorsToKeep) { | |
// Get all the existing parameters of the functionBehavior | |
final EList<org.eclipse.uml2.uml.Parameter> existingFunctionBehaviorParameters = functionBehavior | |
.getOwnedParameters(); | |
// Stategy here is a little different. Remove all the parameters | |
// and add them from scratch | |
final EList<org.eclipse.uml2.uml.Parameter> toRemoveFunctionBehaviorParameters = new BasicEList<org.eclipse.uml2.uml.Parameter>( | |
existingFunctionBehaviorParameters); | |
// Remove all the existing parameters | |
for (org.eclipse.uml2.uml.Parameter parameter : toRemoveFunctionBehaviorParameters) { | |
entityUtil.removeFunctionBehaviorParameter(existingFunctionBehaviorParameters, | |
parameter.getQualifiedName()); | |
} | |
entityUtil.createUmlFunctionBehaviorParameters(functionBehavior, inputTypes, inputMultiplicities, outputType, outputMultiplicity); | |
// Old code that tries to solve it in a different manner | |
// // Prepare the map to mark existing parameters | |
// final HashMap<String, Boolean> mapFunctionBehaviorParameters | |
// = | |
// Maps.newHashMapWithExpectedSize(existingFunctionBehaviorParameters.size()); | |
// for (org.eclipse.uml2.uml.Parameter parameter : | |
// existingFunctionBehaviorParameters) { | |
// mapFunctionBehaviorParameters.put(parameter.getQualifiedName(), | |
// null); | |
// } | |
// | |
// org.eclipse.uml2.uml.Parameter parameter = null; | |
// | |
// // Check the input parameters | |
// for (SimpleType parameterType : parameters) { | |
// if ((parameter = | |
// chessElementsUtil.getExistingFunctionBehaviorParameter(existingFunctionBehaviorParameters, | |
// parameterType, true)) != null) { | |
// mapFunctionBehaviorParameters.put(parameter.getQualifiedName(), | |
// Boolean.TRUE); | |
// logger.debug("functionBehavior input parameter already | |
// present"); | |
// } else { | |
// logger.debug("functionBehavior input parameter is not | |
// present"); | |
// | |
// // Create the input parameter | |
// chessElementsUtil.createFunctionBehaviorParameter(functionBehavior, | |
// parameterType, true); | |
// } | |
// } | |
// | |
// // Check the output parameter | |
// if ((parameter = | |
// chessElementsUtil.getExistingFunctionBehaviorParameter(existingFunctionBehaviorParameters, | |
// dslVariableType, false)) != null) { | |
// logger.debug("functionBehavior output parameter already | |
// present"); | |
// mapFunctionBehaviorParameters.put(parameter.getQualifiedName(), | |
// Boolean.TRUE); | |
// } else { | |
// logger.debug("functionBehavior output parameter is not | |
// present"); | |
// | |
// // Create the output parameter | |
// chessElementsUtil.createFunctionBehaviorParameter(functionBehavior, | |
// dslVariableType, false); | |
// } | |
// | |
// // Parameters cleanup time | |
// for (String qualifiedElement : | |
// mapFunctionBehaviorParameters.keySet()) { | |
// if (mapFunctionBehaviorParameters.get(qualifiedElement) == | |
// null) { | |
// System.out.println("functionBehaviorParameter " + | |
// qualifiedElement + " should be removed"); | |
// chessElementsUtil.removeFunctionBehaviorParameter(existingFunctionBehaviorParameters, | |
// qualifiedElement); | |
// } | |
// } | |
// Set the flag to signal the functionBehavior is still used | |
mapFunctionBehaviorsToKeep.put(functionBehavior.getQualifiedName(), Boolean.TRUE); | |
} | |
// checked methods | |
public void updateUmlStaticPort(org.eclipse.uml2.uml.Port port, String[] newMultiplicityRange, | |
HashMap<String, Boolean> mapPortsToKeep) { | |
// Update its multiplicity if needed | |
entityUtil.updateUmlStaticPort(port, newMultiplicityRange); | |
// Set the flag to signal the port is still used | |
mapPortsToKeep.put(port.getQualifiedName(), Boolean.TRUE); | |
} | |
public void updateUmlNonStaticPort(org.eclipse.uml2.uml.Port port, eu.fbk.tools.editor.oss.oss.Port ossPort, | |
Type newType, String[] newMultiplicityRange, FlowDirection portDirection, Stereotype flowPortStereotype, | |
HashMap<String, Boolean> mapPortsToKeep) { | |
// Port found, update its direction if needed | |
final FlowPort flowPort = (FlowPort) port.getStereotypeApplication(flowPortStereotype); | |
if (flowPort.getDirection() != portDirection) { | |
flowPort.setDirection(portDirection); | |
} | |
// Update its type if needed | |
entityUtil.updateUmlNonStaticPort(port, newType, newMultiplicityRange); | |
// Set the flag to signal the port is still used | |
mapPortsToKeep.put(port.getQualifiedName(), Boolean.TRUE); | |
// Add the port to the list of changes NOT NEEDED BECAUSE | |
// DIAGRAMS ARE AUTO-UPDATING | |
// addedElements.add(port); | |
} | |
public void updateUmlRefinementFormalProperty(Constraint umlConstraint, String updatedText, String language, | |
HashMap<String, Boolean> mapFormalPropertiesToKeep) { | |
// Update the formal property if needed | |
entityUtil.updateUmlConstraint(umlConstraint, updatedText, language); | |
// Set the flag to signal the formal property is | |
// still used | |
mapFormalPropertiesToKeep.put(umlConstraint.getQualifiedName(), Boolean.TRUE); | |
} | |
public void updateUmlFormalProperty(Constraint umlConstraint, String assertionText,String language, | |
HashMap<String, FormalProperty> hashFormalProperties, HashMap<String, Boolean> mapFormalPropertiesToKeep) { | |
// Update the formal property if needed | |
final String formalPropertyText = entityUtil.getConstraintBodyStr(umlConstraint,language); | |
// If the expression is different, save it, otherwise go on | |
if (!assertionText.equals(formalPropertyText)) { | |
entityUtil.setTextInUMLConstraint(umlConstraint, assertionText, language); | |
} | |
// Set the flag to signal the formal property is still used | |
mapFormalPropertiesToKeep.put(umlConstraint.getQualifiedName(), Boolean.TRUE); | |
} | |
public void updateUmlContract(Class umlContract, String ossAssumptionText, String ossGuaranteeText, String language, | |
HashMap<String, FormalProperty> hashFormalProperties, HashMap<String, Boolean> mapContractPropertiesToKeep, | |
HashMap<String, Boolean> mapFormalPropertiesToKeep, Class owner) { | |
final org.polarsys.chess.contracts.profile.chesscontract.Contract contract = | |
contractEntityUtil.getContract(umlContract); | |
final FormalProperty contractAssumption = contract.getAssume(); | |
final FormalProperty contractGuarantee = contract.getGuarantee(); | |
// Check if the assumption formal property is already present in the hash | |
final FormalProperty hashAssumption = hashFormalProperties.get(ossAssumptionText); | |
if (hashAssumption != null) { | |
logger.debug("assumption already present in the hash = " + hashAssumption); | |
// Check if the assumption is different from the one already set | |
if (hashAssumption != contractAssumption) { | |
// Check if the current assumption is child of the contract. If so, it can be removed | |
if (contractAssumption.getBase_Constraint().getOwner() == contract.getBase_Class()) { | |
// The old assumption needs to be removed from the contract | |
final EList<Constraint> fpList = new BasicEList<Constraint>(); | |
fpList.add(contractAssumption.getBase_Constraint()); | |
entityUtil.removeFormalProperty(fpList, contractAssumption.getBase_Constraint().getQualifiedName()); | |
} | |
// Set the new assumption | |
contract.setAssume(hashAssumption); | |
} | |
} else { | |
logger.debug("assumption not present in the hash"); | |
// Check if the current assumption is child of the contract. If so, it can be edited | |
if (contractAssumption.getBase_Constraint().getOwner() == contract.getBase_Class()) { | |
// The assumption is the same, update it if needed | |
entityUtil.updateUmlConstraint(contractAssumption.getBase_Constraint(), ossAssumptionText, language); | |
} else { | |
// The assumption is a block formal property, cannot be modified or removed | |
// A new one has to be created | |
contractEntityUtil.createAssumptionToUmlContract(umlContract); | |
final FormalProperty assumptionFormalProperty = contractEntityUtil.getAssumeFromUmlContract(umlContract); | |
entityUtil.setTextInUMLConstraint(assumptionFormalProperty.getBase_Constraint(), ossAssumptionText, language); | |
} | |
} | |
// Check if the guarantee formal property is already present in the hash | |
final FormalProperty hashGuarantee = hashFormalProperties.get(ossGuaranteeText); | |
if (hashGuarantee != null) { | |
logger.debug("guarantee already present in the hash = " + hashGuarantee); | |
// Check if the guarantee is different from the one already set | |
if (hashGuarantee != contractGuarantee) { | |
// Check if the current guarantee is child of the contract. If so, it can be removed | |
if (contractGuarantee.getBase_Constraint().getOwner() == contract.getBase_Class()) { | |
// The old guarantee needs to be removed from the contract | |
final EList<Constraint> fpList = new BasicEList<Constraint>(); | |
fpList.add(contractGuarantee.getBase_Constraint()); | |
entityUtil.removeFormalProperty(fpList, contractGuarantee.getBase_Constraint().getQualifiedName()); | |
} | |
// Set the new guarantee | |
contract.setGuarantee(hashGuarantee); | |
} | |
} else { | |
logger.debug("guarantee not present in the hash"); | |
// Check if the current guarantee is child of the contract. If so, it can be edited | |
if (contractGuarantee.getBase_Constraint().getOwner() == contract.getBase_Class()) { | |
// The guarantee is the same, update it if needed | |
entityUtil.updateUmlConstraint(contractGuarantee.getBase_Constraint(), ossGuaranteeText, language); | |
} else { | |
// The guarantee is a block formal property, cannot be modified or removed | |
// A new one has to be created | |
contractEntityUtil.createGuaranteeToUmlContract(umlContract); | |
final FormalProperty guaranteeFormalProperty = contractEntityUtil.getGuaranteeFromUmlContract(umlContract); | |
entityUtil.setTextInUMLConstraint(guaranteeFormalProperty.getBase_Constraint(), ossGuaranteeText, language); | |
} | |
} | |
// Set the flag to signal the contractProperty is still used | |
final ContractProperty contractProperty = (ContractProperty) chessSystemModel.getContract(owner, | |
// dslContract.getName() should be the same | |
umlContract.getName()); | |
mapContractPropertiesToKeep.put(contractProperty.getBase_Property().getQualifiedName(), Boolean.TRUE); | |
} | |
public void updateUmlAssociation(Property componentInstance, Type type, String[] ossSubComponentMultiplicity, | |
HashMap<String, Boolean> mapComponentInstancesToKeep) throws Exception { | |
entityUtil.updateUmlAssociation(componentInstance, type, ossSubComponentMultiplicity); | |
// Set the flag to signal the componentInstance is still used | |
mapComponentInstancesToKeep.put(componentInstance.getQualifiedName(), Boolean.TRUE); | |
} | |
public Constraint createUmlInterfaceFormalProperty(String assertionName, String assertionText, | |
HashMap<String, FormalProperty> hashFormalProperties, Class owner) { | |
Constraint umlConstraint = entityUtil.createInterfaceFormalProperty(owner, assertionName, assertionText); | |
// Add the formal property to the hash | |
hashFormalProperties.put(assertionName, entityUtil.getFormalProperty(umlConstraint)); | |
return umlConstraint; | |
} | |
public Class createUmlContract(String contractName, String ossAssumptionText, String ossGuaranteeText, | |
HashMap<String, FormalProperty> hashFormalProperties, Class owner, Stereotype contractStereotype) { | |
// Create an empty Contract | |
Class umlContract = contractEntityUtil.createContract(owner, contractName, contractStereotype); | |
org.polarsys.chess.contracts.profile.chesscontract.Contract contract = | |
contractEntityUtil.getContract(umlContract); | |
// Check if the assumption formal property is already defined | |
final FormalProperty assumption = hashFormalProperties.get(ossAssumptionText); | |
if (assumption != null) { | |
logger.debug("assumption already present = " + assumption); | |
// Add the assume formal property | |
contract.setAssume(assumption); | |
} else { | |
logger.debug("assumption not present"); | |
// Create a new formal property | |
contractEntityUtil.setTextToAssumeOrCreateAssume(ossAssumptionText, umlContract); | |
} | |
// Check if the guarantee formal property is already defined | |
final FormalProperty guarantee = hashFormalProperties.get(ossGuaranteeText); | |
if (guarantee != null) { | |
logger.debug("guarantee already present = " + guarantee); | |
// Add the assume formal property | |
contract.setGuarantee(guarantee); | |
} else { | |
logger.debug("guarantee not present"); | |
// Create a new formal property | |
contractEntityUtil.setTextToGuaranteeOrCreateGuarantee(ossGuaranteeText, umlContract); | |
} | |
return umlContract; | |
} | |
/** | |
* Updates the expression of the given Macro Definition, if needed. | |
* @param umlConstraint the Macro Definition as Constraint | |
* @param macroDefinitionExpression the new expression | |
* @param mapMacroDefinitionsToKeep the map of existing Macro Definitions | |
*/ | |
public void updateMacroDefinition(Constraint umlConstraint, String macroDefinitionExpression, String language, | |
HashMap<String, Boolean> mapMacroDefinitionsToKeep) { | |
entityUtil.updateMacroDefinition(umlConstraint, macroDefinitionExpression,language); | |
// Set the flag to signal the macro definition is still used | |
mapMacroDefinitionsToKeep.put(umlConstraint.getQualifiedName(), Boolean.TRUE); | |
} | |
/** | |
* Returns the list of diagrams in which the given element is present. | |
* @param members the list of members in which the element is present | |
* @param qualifiedElement the qualified name of element | |
* @return names of the diagrams | |
*/ | |
public Set<String> getInvolvedDiagrams(EList<?> members, String qualifiedElement) { | |
final Set<String> diagramNames = new HashSet<String>(); | |
for (Object object : members) { | |
NamedElement element = null; | |
if (object instanceof NamedElement) { | |
element = (NamedElement) object; | |
} else if (object instanceof ContractProperty) { | |
element = ((ContractProperty) object).getBase_Property(); | |
} | |
if (element != null && element instanceof NamedElement) { | |
if (element.getQualifiedName().equals(qualifiedElement)) { | |
try { | |
NavigationService navigationService = null; | |
try { | |
final ServicesRegistry registry = ServiceUtilsForEObject.getInstance().getServiceRegistry(element); | |
if (registry != null) { | |
navigationService = registry.getService(NavigationService.class); | |
} | |
} catch (ServiceException e) { | |
e.printStackTrace(); | |
} | |
if (navigationService != null) { | |
final List<NavigableElement> navigableElements = navigationService.getNavigableElements(element); | |
if (navigableElements != null) { | |
for (NavigableElement navigableElement : navigableElements) { | |
final List<Object> viewsToSelect = getViewsToSelect(navigableElement, false); | |
for (Object view : viewsToSelect) { | |
diagramNames.add(getText(view)); | |
} | |
} | |
} | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
break; | |
} | |
} else { | |
logger.debug("cannot find a reprentation for " + qualifiedElement); | |
} | |
} | |
return diagramNames; | |
} | |
// The following code has been taken from these classes: | |
// org.eclipse.papyrus.infra.gmfdiag.navigation.ui.DynamicNavigateLabelProvider | |
// org.eclipse.papyrus.infra.gmfdiag.navigation.ui.DynamicNavigate | |
protected static boolean isLocalLabelProvider; | |
private static String getText(Object element) { | |
if (element instanceof NavigableElement) { | |
return ((NavigableElement) element).getLabel(); | |
} else if (element instanceof EObject) { | |
return getName((EObject) element); | |
} | |
return element.toString(); | |
} | |
private static String getName(EObject element) { | |
ILabelProvider labelProvider = getLabelProvider((EObject) element); | |
String name = labelProvider.getText(element); | |
if (isLocalLabelProvider) { | |
labelProvider.dispose(); | |
} | |
if (name != null) { | |
return name; | |
} else { | |
return element.toString(); | |
} | |
} | |
private static ILabelProvider getLabelProvider(EObject element) { | |
ILabelProvider labelProvider = null; | |
try { | |
labelProvider = ServiceUtilsForEObject.getInstance().getService(LabelProviderService.class, element).getLabelProvider("org.eclipse.papyrus.infra.services.navigation.menu.labelprovider"); | |
} catch (ServiceException e) { | |
e.printStackTrace(); | |
} | |
if (labelProvider == null) { | |
labelProvider = new LabelProvider(); | |
isLocalLabelProvider = true; | |
} else { | |
isLocalLabelProvider = false; | |
} | |
return labelProvider; | |
} | |
/** | |
* Get views representing a navigable element | |
* | |
* @param navElement | |
* The navigable element represented in views | |
* @param onlyOpened | |
* Only opened views are returned | |
* @return | |
* List of views representing the navigable element | |
*/ | |
private List<Object> getViewsToSelect(NavigableElement navElement, boolean onlyOpened) { | |
if (navElement == null) { | |
return null; | |
} | |
EObject element = null; | |
if (navElement instanceof ExtendedNavigableElement | |
&& ((ExtendedNavigableElement) navElement).getSemanticElement() instanceof EObject) { | |
element = (EObject) ((ExtendedNavigableElement) navElement).getSemanticElement(); | |
} | |
if (element != null) { | |
ViewerSearchService viewerSearchService = null; | |
try { | |
viewerSearchService = ServiceUtilsForEObject.getInstance().getService(ViewerSearchService.class, element); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
if (viewerSearchService != null) { | |
return viewerSearchService.getViewersInCurrentModel(element, null, false, onlyOpened); | |
} | |
} | |
return new LinkedList<Object>(); | |
} | |
} |