/***************************************************************************** * Copyright (c) 2010-2011 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: * * Arthur daussy (Atos) arthur.daussy@atos.net - Bug 361643: [StateMachine Diagram] Display of Guards doesn't work. * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.statemachine.custom.parsers; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.common.ui.services.parser.IParser; import org.eclipse.gmf.runtime.common.ui.services.parser.IParserEditStatus; import org.eclipse.gmf.runtime.common.ui.services.parser.ParserEditStatus; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.ui.services.parser.ISemanticParser; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.papyrus.infra.core.utils.EditorUtils; import org.eclipse.papyrus.uml.tools.utils.ValueSpecificationUtil; import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.CallEvent; import org.eclipse.uml2.uml.ChangeEvent; import org.eclipse.uml2.uml.Constraint; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Event; import org.eclipse.uml2.uml.NamedElement; import org.eclipse.uml2.uml.OpaqueBehavior; import org.eclipse.uml2.uml.OpaqueExpression; import org.eclipse.uml2.uml.SignalEvent; import org.eclipse.uml2.uml.TimeEvent; import org.eclipse.uml2.uml.Transition; import org.eclipse.uml2.uml.Trigger; import org.eclipse.uml2.uml.UMLFactory; import org.eclipse.uml2.uml.ValueSpecification; public class TransitionPropertiesParser implements IParser, ISemanticParser { private static final String ONE_SPACE_STRING = " "; //$NON-NLS-1$ protected Constraint guardConstraint = null; private static String EMPTY_STRING = ""; //$NON-NLS-1$ public IContentAssistProcessor getCompletionProcessor(IAdaptable element) { return null; } public String getEditString(IAdaptable element, int flags) { return EMPTY_STRING; } public ICommand getParseCommand(IAdaptable element, String newString, int flags) { final Transition transition = ((Transition)((EObjectAdapter)element).getRealObject()); final String result = newString; AbstractTransactionalCommand tc = new AbstractTransactionalCommand(EditorUtils.getTransactionalEditingDomain(), "Edit Transition Properties", (List)null) { //$NON-NLS-1$ @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { SafeRunnable.run(new SafeRunnable() { public void run() { RecordingCommand rc = new RecordingCommand(EditorUtils.getTransactionalEditingDomain()) { protected void doExecute() { // 1. Cherchez dans le model, si une contrainst // avec le meme nom existe EList<Element> elements = (transition.getModel()).allOwnedElements(); Iterator<Element> modelElement = elements.iterator(); while(modelElement.hasNext()) { Element pElement = (Element)modelElement.next(); if(pElement instanceof Constraint && (result.equals(((NamedElement)pElement).getName()))) { guardConstraint = (Constraint)pElement; transition.setGuard(guardConstraint); } } // 2.Si aucune constraint n'existe deja if(guardConstraint == null) { guardConstraint = UMLFactory.eINSTANCE.createConstraint(); guardConstraint.setName(result); guardConstraint.setContext(transition.getNamespace()); transition.setGuard(guardConstraint); } // transition.setName(result); } }; EditorUtils.getTransactionalEditingDomain().getCommandStack().execute(rc); } }); return CommandResult.newOKCommandResult(); }; }; return tc; } public String getPrintString(IAdaptable element, int flags) { String label = getValueString(element, flags); if(label == null || label.length() == 0) { label = ONE_SPACE_STRING; } return label; } public boolean isAffectingEvent(Object event, int flags) { if(event instanceof Notification) { int notificationType = ((Notification)event).getEventType(); if(Notification.SET == notificationType) { if(((Notification)event).getNewValue() instanceof Constraint) guardConstraint = (Constraint)((Notification)event).getNewValue(); return true; } } return false; } /** * Get the unformatted registered string value which shall be displayed */ protected String getValueString(IAdaptable element, int flags) { Object obj = element.getAdapter(EObject.class); if(obj instanceof Transition) { Transition trans = (Transition)obj; StringBuilder result = new StringBuilder(); String textForTrigger = getTextForTrigger(trans); if(textForTrigger != null && !EMPTY_STRING.equals(textForTrigger)) { result.append(textForTrigger).append(ONE_SPACE_STRING); } result.append(getTextForGuard(trans)); String textForEffect = getTextForEffect(trans); if(textForEffect != null && !EMPTY_STRING.equals(textForEffect)) { result.append("/\n").append(textForEffect); //$NON-NLS-1$ } return result.toString(); } return EMPTY_STRING; } /** * get the text concerning guard * * @param trans * @return */ protected String getTextForGuard(Transition trans) { Constraint valueSpec = trans.getGuard(); if(valueSpec != null) { String value = ValueSpecificationUtil.getConstraintnValue(valueSpec); if(value != null) { return String.format("[%s]", value); //$NON-NLS-1$ } } return EMPTY_STRING; } /** * get the text concerning Effects * * @param trans * @return */ protected String getTextForEffect(Transition trans) { StringBuilder result = new StringBuilder(); Behavior effect = trans.getEffect(); if(effect != null) { EClass eClass = effect.eClass(); if(effect instanceof OpaqueBehavior) { OpaqueBehavior ob = (OpaqueBehavior)effect; if(ob.getBodies().size() > 0) { // return body of behavior (only handle case of a single body) result.append(ob.getBodies().get(0)); return result.toString(); } } if(eClass != null) { result.append(eClass.getName()).append(": ").append(effect.getName()); //$NON-NLS-1$ } } return result.toString(); } /** * Get the text concerning Trigger * * @param trans * @return */ protected String getTextForTrigger(Transition trans) { StringBuilder result = new StringBuilder(); boolean isFirstTrigger = true; for(Trigger t : trans.getTriggers()) { if(t != null) { if(!isFirstTrigger) result.append(", "); //$NON-NLS-1$ else isFirstTrigger = false; Event e = t.getEvent(); if(e instanceof CallEvent) { if(((CallEvent)e).getOperation() != null) result.append(((CallEvent)e).getOperation().getName()); else result.append(((CallEvent)e).getName()); } else if(e instanceof SignalEvent) { if(((SignalEvent)e).getSignal() != null) result.append(((SignalEvent)e).getSignal().getName()); else result.append(((SignalEvent)e).getName()); } else if(e instanceof ChangeEvent) { result.append("when ").append("\"").append(retrieveBody((OpaqueExpression)((ChangeEvent)e).getChangeExpression(), "Natural language")).append("\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } else if(e instanceof TimeEvent) { //absRelPrefix result.append((((TimeEvent)e).isRelative() ? "after " : "at ")); //$NON-NLS-1$ //$NON-NLS-2$ // body result.append("\"").append(retrieveBody((OpaqueExpression)((TimeEvent)e).getWhen().getExpr(), "Natural language")).append("\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } else { // any receive event result.append("all"); //$NON-NLS-1$ } } } return result.toString(); } public IParserEditStatus isValidEditString(IAdaptable element, String editString) { return new ParserEditStatus(org.eclipse.papyrus.uml.diagram.statemachine.part.UMLDiagramEditorPlugin.ID, IParserEditStatus.OK, ""); //$NON-NLS-1$ } public List getSemanticElementsBeingParsed(EObject element) { Element umlElement = (Element)element; List<EObject> result = new LinkedList<EObject>(); if(umlElement instanceof Transition) { Transition trans = (Transition)umlElement; if(trans != null) { result.add(trans); /** * Listen constraint modification */ Constraint constraint = trans.getGuard(); if(constraint != null) { result.add(constraint); ValueSpecification specification = constraint.getSpecification(); if(specification != null) { result.add(specification); } } /** * Listen trigger modification */ for(Trigger t : trans.getTriggers()) { if(t != null) { result.add(t); } } /** * Listen effect modification */ Behavior effect = trans.getEffect(); if(effect != null) { result.add(effect); } } // if(constraint.getSpecification() != null) { // ValueSpecification value = constraint.getSpecification(); // result.add(value); // } } return result; } public boolean areSemanticElementsAffected(EObject listener, Object notification) { return true; } private String retrieveBody(OpaqueExpression exp, String languageName) { String body = EMPTY_STRING; if(exp == null) return body; int index = 0; for(String _languageName : exp.getLanguages()) { if(_languageName.equals(languageName)) { if(index < exp.getBodies().size()) return exp.getBodies().get(index); else return EMPTY_STRING; } index++; } return body; } }