blob: cc2cac3f92daf9c4abca2b47b0062d56c37073a8 [file] [log] [blame]
/*
-----------------------------------------------------------------------
-- CHESS M2M plugin --
-- --
-- Copyright (C) 2011-2012 --
-- University of Padova, ITALY --
-- --
-- Authors: -Alessandro Zovi azovi@math.unipd.it
-- -Intecs
-- --
-- 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-v20.html --
-----------------------------------------------------------------------
*/
package org.polarsys.chess.m2m.handlers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.polarsys.chess.chessmlprofile.Predictability.DeploymentConfiguration.HardwareBaseline.CH_HwProcessor;
import org.polarsys.chess.chessmlprofile.Predictability.RTComponentModel.CHRtPortSlot;
import org.polarsys.chess.core.util.CHESSProjectSupport;
import org.polarsys.chess.core.util.uml.ResourceUtils;
import org.polarsys.chess.core.util.uml.UMLUtils;
import org.polarsys.chess.core.views.ViewUtils;
import org.polarsys.chess.m2m.Activator;
import org.polarsys.chess.m2m.transformations.PIMPSMTransformationEnd2End;
import org.polarsys.chess.m2m.transformations.TransUtil;
import org.polarsys.chess.m2m.transformations.TransformationResultsData;
import org.polarsys.chess.m2m.ui.AnalysisContextSelectionDialog;
import org.polarsys.chess.m2m.ui.End2EndResultDialog;
import org.polarsys.chess.service.gui.utils.CHESSEditorUtils;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.m2m.internal.qvt.oml.emf.util.ModelContent;
import org.eclipse.papyrus.MARTE.MARTE_AnalysisModel.GQAM.GaWorkloadBehavior;
import org.eclipse.papyrus.MARTE.MARTE_AnalysisModel.SAM.SaAnalysisContext;
import org.eclipse.papyrus.MARTE.MARTE_AnalysisModel.SAM.SaEndtoEndFlow;
import org.eclipse.papyrus.MARTE.MARTE_Foundations.Alloc.Assign;
import org.eclipse.papyrus.editor.PapyrusMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.uml2.uml.Activity;
import org.eclipse.uml2.uml.ActivityNode;
import org.eclipse.uml2.uml.CallBehaviorAction;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Interaction;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Stereotype;
/**
* The Class QVToUIHandlerEnd2End realizes the handler for the end-to-end analysis command.
* @since 0.9
*/
public class QVToUIHandlerEnd2End extends AbstractHandler {
/** The Constant SAANALYSISCONTEXT. */
private static final String SAANALYSISCONTEXT = "MARTE::MARTE_AnalysisModel::SAM::SaAnalysisContext";
/** The Constant SAENDTOENDFLOW. */
private static final String SAENDTOENDFLOW = "MARTE::MARTE_AnalysisModel::SAM::SaEndtoEndFlow";
/** The active shell. */
private Shell activeShell = null;
/** The in resource. */
private Resource inResource = null;
/** The context class. */
private Class contextClass;
/** The deadline. */
private String deadline;
/** The scenario. */
private String scenario;
/** The sa analysis name. */
private String saAnalysisName;
/** The sa e2 e flow name. */
private String saE2EFlowName;
/** The sa e2 e flow. */
private SaEndtoEndFlow saE2EFlow;
/** The sa analysis ctx. */
private SaAnalysisContext saAnalysisCtx;
/** The psm package name. */
private String psmPackageName;
/**
* Gets the active project.
*
* @param editor the editor
* @return the active project
*/
private IProject getActiveProject(IEditorPart editor) {
IFileEditorInput input = (IFileEditorInput) editor.getEditorInput();
IFile file = input.getFile();
return file.getProject();
}
/**
* Executes the end-to-end response time analysis and shows the results.
* The end-to-end analysis context to be analyzed is asked to the user through a dedicated dialog.
*
*
* @param event the event resulting from the command invocation
* @return null
* @throws ExecutionException the execution exception
* @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
* @see org.polarsys.chess.m2m.ui.AnalysisContextSelectionDialog
*/
public Object execute(final ExecutionEvent event) throws ExecutionException {
final IEditorPart editor = HandlerUtil.getActiveEditor(event);
if (!(CHESSEditorUtils.isCHESSProject(editor)))
return null;
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
activeShell = window.getShell();
try {
inResource = ResourceUtils.getUMLResource(((PapyrusMultiDiagramEditor) editor).getServicesRegistry());
} catch (ServiceException e) {
e.printStackTrace();
}
//open a dialog to select the end-to-end analysis context to be analyzed
//first get all the classes stereotyped as SaAnalysisContext
final List<Class> selection = new ArrayList<Class>();
final Model model = (Model) inResource.getContents().get(0);
EList<Element> elemList = model.allOwnedElements();
for (Element elem : elemList) {
//we're looking for a class stereotyped <<saAnalysisContext>> and NOT in PSM
if(elem instanceof Class && elem.getAppliedStereotype(SAANALYSISCONTEXT) != null
&& !ViewUtils.isPSMView(ViewUtils.getView(elem))){
//as additional constraint, at least one workload is specified
SaAnalysisContext saAnalysisCtx = (SaAnalysisContext) elem.getStereotypeApplication
(elem.getAppliedStereotype(SAANALYSISCONTEXT));
if(saAnalysisCtx.getWorkload().size() > 0){
selection.add((Class) elem);
}
}
}
if(selection.size() == 0){
MessageDialog.openWarning(activeShell, "CHESS", "no suitable analysis contexts in the model");
return null;
}
//then open the dialog
String contextQN = null;
AnalysisContextSelectionDialog dialog = new AnalysisContextSelectionDialog(activeShell, selection, "Select End-To-End Context to analyze");
if (dialog.open() == Window.OK) {
contextQN = dialog.getContext();
if(contextQN == null || contextQN.isEmpty()){
return null;
}
for (Element elem : model.allOwnedElements()){
if(elem.getAppliedStereotype(SAANALYSISCONTEXT) != null &&
((NamedElement) elem).getQualifiedName().equals(contextQN)){
contextClass = (Class) elem;
}
}
}else{
return null;
}
saAnalysisName = contextClass.getQualifiedName();
psmPackageName = contextClass.getName() +"_PSM";
Stereotype stereo = contextClass.getAppliedStereotype(SAANALYSISCONTEXT);
saAnalysisCtx = (SaAnalysisContext) contextClass.getStereotypeApplication(stereo);
EList<GaWorkloadBehavior> workloadList = saAnalysisCtx.getWorkload();
//assume there's only one workload
if(workloadList.size() != 1){
return null;
}
GaWorkloadBehavior workload = workloadList.get(0);
NamedElement nelem = workload.getBase_NamedElement();
if (!(nelem instanceof Activity)){
return null;
}
Activity workloadActivity = (Activity) nelem;
saE2EFlowName = workloadActivity.getQualifiedName();
//check that the activity is also a SaEndToEndFlow (assumption)
stereo = workloadActivity.getApplicableStereotype(SAENDTOENDFLOW);
saE2EFlow = (SaEndtoEndFlow) workloadActivity.getStereotypeApplication(stereo);
//deadline is to be passed to the QVTO transformation
deadline = saE2EFlow.getEnd2EndD().get(0); //note: in MARTE this relationship is [0..1] not [0..*] as in Papyrus
//assume the activity has exactly one callbehaviour node
CallBehaviorAction callbehaviour = null;
EList<ActivityNode> nodes = workloadActivity.getNodes();
for (ActivityNode activityNode : nodes) {
if(activityNode instanceof CallBehaviorAction){
callbehaviour = (CallBehaviorAction)activityNode;
}
}
if (!(callbehaviour.getBehavior() instanceof Interaction)){
return null;
}
//scenario is to be passed to the QVTO transformation
final Interaction interaction = ((Interaction) callbehaviour.getBehavior());
scenario = interaction .getQualifiedName();
final Job job = new Job("Transforming") {
protected IStatus run(IProgressMonitor monitor) {
try {
TransformationResultsData result =null;
try {
result = QVToUIHandlerEnd2End.this.executeTimingAnalysis(editor, monitor);
//Reopen the editor
CHESSEditorUtils.reopenEditor(editor, false);
} catch (Exception e) {
throw e;
} finally {
getActiveProject(editor).refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
//open sched analysis result
try {
//can active editor be different from just reopened CHESS ones? it should be not the case given that it has been just reopened
//inResource = ResourceUtils.getUMLResource(((CHESSEditor) editor).getServicesRegistry());
//Model model = (Model) inResource.getContents().get(0);
ModelContent inModel = TransUtil.loadModel(result.umlFile);
Model model = (Model) inModel.getContent().get(0);
openE2EAnalysisReport(model, saAnalysisName, interaction);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Unable to load the model and so open the schedAnalysisReport");
}
} catch (Exception e) {
e.printStackTrace();
return new Status(Status.ERROR, Activator.PLUGIN_ID, 1,
"Error in transformation "+ e.getMessage(), null);
}
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
return Status.OK_STATUS;
}
};
job.addJobChangeListener(new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
if (event.getResult().isOK())
CHESSProjectSupport.printlnToCHESSConsole("Job completed successfully");
else
CHESSProjectSupport.printlnToCHESSConsole("Job did not complete successfully");
}
});
job.setUser(true);
job.setPriority(Job.SHORT);
job.schedule();
return null;
}
/**
* Collects all the needed information and invokes the PIMPSMTransformationEnd2End.performTimingAnalysisWithMAST method
*
* @param editor the current active editor
* @param monitor the progress monitor
* @return the string resulting from the MAST execution (i.e. the system is/not schedulable) and the modified model
* @throws Exception the exception
* @see org.polarsys.chess.m2m.transformations.PIMPSMTransformationEnd2End#performTimingAnalysisWithMAST(PapyrusMultiDiagramEditor, IFile, IProgressMonitor)
*/
public TransformationResultsData executeTimingAnalysis(IEditorPart editor, IProgressMonitor monitor) throws Exception {
monitor.beginTask("Transforming", 4);
if (!(CHESSEditorUtils.isCHESSProject(editor)))
return null;
IFile inputFile = CHESSProjectSupport.resourceToFile(inResource);
//finally call the transformation
PIMPSMTransformationEnd2End t = new PIMPSMTransformationEnd2End();
t.setFolder(TransUtil.TRANSFORMATIONS_DIR_E2E);
Map<String, String> configProps = new HashMap<String, String>();
configProps.put("deadline", deadline);
configProps.put("scenario", scenario);
configProps.put("saAnalysis",saAnalysisName);
configProps.put("saE2EFlow", saE2EFlowName);
configProps.put("analysisType", "EndToEnd");
t.setConfigProperty(configProps);
t.setPsmPackageName(psmPackageName);
TransformationResultsData result = t.performTimingAnalysisWithMAST((PapyrusMultiDiagramEditor) editor, inputFile, monitor);
return result;
}
/**
* Opens the end-to-end analysis report dialog.
*
* @param model the model
* @param saAnalysisName the sa analysis name
* @param interaction the interaction
*/
public void openE2EAnalysisReport(final Model model, String saAnalysisName, Interaction interaction){
//get all the e2e analysis result info from the model and open a simple, user-friendly report
SaAnalysisContext saAnCtx = null;
SaEndtoEndFlow saflow = null;
Package anView = (Package) ViewUtils.getCHESSRtAnalysisPackage(model);
for (Element elem : anView.allOwnedElements()) {
if(elem instanceof Class && ((Class)elem).getQualifiedName().equals(saAnalysisName)){
saAnCtx = UMLUtils.getStereotypeApplication(elem, SaAnalysisContext.class);
if(saAnCtx.getWorkload().size() > 0){
saflow = UMLUtils.getStereotypeApplication(saAnCtx.getWorkload().get(0).getBase_NamedElement(), SaEndtoEndFlow.class);
}
}
}
EList<Message> messages = interaction.getMessages();
final List<Operation> e2eOperations = new ArrayList<Operation>();
for (Message msg : messages) {
Operation op = (Operation) msg.getSignature();
if (op.eIsProxy()){
op = (Operation) EcoreUtil.resolve(op, model.eResource().getResourceSet());
}
e2eOperations.add(op);
}
final List<CH_HwProcessor> cpus = new ArrayList<CH_HwProcessor>();
final List<CHRtPortSlot> specifications = new ArrayList<CHRtPortSlot>();
final List<Assign> assigns = new ArrayList<Assign>();
for (Element elem : model.allOwnedElements()) {
CHRtPortSlot chrtSlot = UMLUtils.getStereotypeApplication(elem, CHRtPortSlot.class);
//if(chrtSlot != null && UMLUtils.getStereotypeApplication(chrtSlot.getBase_Slot().getOwner(), IdentifInstance.class) != null){
if(chrtSlot != null){
specifications.add(chrtSlot);
}
if(elem instanceof InstanceSpecification){
CH_HwProcessor chHwProc = UMLUtils.getStereotypeApplication(elem, CH_HwProcessor.class);
if(chHwProc != null){
cpus.add(chHwProc);
}
}
Assign assign = UMLUtils.getStereotypeApplication(elem, Assign.class);
if(assign != null){
assigns.add(assign);
}
};
launchDialog(model, cpus, saAnCtx, saflow, e2eOperations, assigns, specifications);
}
/**
* Launch dialog.
*
* @param model the model
* @param cpus the cpus
* @param saAnCtx the sa an ctx
* @param saflow the saflow
* @param e2eOperations the e2e operations
* @param assigns the assigns
* @param specifications the specifications
*/
private static void launchDialog(final Model model, final List<CH_HwProcessor> cpus, final SaAnalysisContext saAnCtx, final SaEndtoEndFlow saflow, final List<Operation> e2eOperations, final List<Assign> assigns, final List<CHRtPortSlot> specifications){
final Display display = PlatformUI.getWorkbench().getDisplay();
display.asyncExec(new Runnable() {
@Override
public void run() {
Shell shell = new Shell(display);
End2EndResultDialog e2eDialog = new End2EndResultDialog(shell, model);
e2eDialog.setCpus(cpus);
e2eDialog.setSpecifications(specifications);
e2eDialog.setSaAnalysisCtx(saAnCtx);
e2eDialog.setSaE2EFlow(saflow);
e2eDialog.setMessages(e2eOperations);
e2eDialog.setAssigns(assigns);
if (e2eDialog.open() == Window.OK) {
System.out.println("OK");
}
}
});
}
}