/*******************************************************************************
* Copyright (c) 2008, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.eef.modelingBot.interpreter;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.eef.components.PropertiesEditionContext;
import org.eclipse.emf.eef.components.PropertiesEditionElement;
import org.eclipse.emf.eef.extended.editor.ReferenceableObject;
import org.eclipse.emf.eef.modelingBot.Action;
import org.eclipse.emf.eef.modelingBot.DetailsPage;
import org.eclipse.emf.eef.modelingBot.IModelingBot;
import org.eclipse.emf.eef.modelingBot.ModelingBot;
import org.eclipse.emf.eef.modelingBot.Processing;
import org.eclipse.emf.eef.modelingBot.PropertiesView;
import org.eclipse.emf.eef.modelingBot.Scenario;
import org.eclipse.emf.eef.modelingBot.Sequence;
import org.eclipse.emf.eef.modelingBot.SequenceType;
import org.eclipse.emf.eef.modelingBot.Wizard;
import org.eclipse.emf.eef.modelingBot.EEFActions.Add;
import org.eclipse.emf.eef.modelingBot.EEFActions.Cancel;
import org.eclipse.emf.eef.modelingBot.EEFActions.EditAction;
import org.eclipse.emf.eef.modelingBot.EEFActions.MoveDown;
import org.eclipse.emf.eef.modelingBot.EEFActions.MoveUp;
import org.eclipse.emf.eef.modelingBot.EEFActions.OpenEEFEditor;
import org.eclipse.emf.eef.modelingBot.EEFActions.Remove;
import org.eclipse.emf.eef.modelingBot.EEFActions.SetAttribute;
import org.eclipse.emf.eef.modelingBot.EEFActions.SetReference;
import org.eclipse.emf.eef.modelingBot.EEFActions.Unset;
import org.eclipse.emf.eef.modelingBot.EEFActions.UnsetAttribute;
import org.eclipse.emf.eef.modelingBot.EEFActions.UnsetReference;
import org.eclipse.emf.eef.modelingBot.EclipseActions.CloseEditor;
import org.eclipse.emf.eef.modelingBot.EclipseActions.CloseProject;
import org.eclipse.emf.eef.modelingBot.EclipseActions.CreateModel;
import org.eclipse.emf.eef.modelingBot.EclipseActions.CreateProject;
import org.eclipse.emf.eef.modelingBot.EclipseActions.OpenEditor;
import org.eclipse.emf.eef.modelingBot.EclipseActions.Redo;
import org.eclipse.emf.eef.modelingBot.EclipseActions.RemoveProject;
import org.eclipse.emf.eef.modelingBot.EclipseActions.Save;
import org.eclipse.emf.eef.modelingBot.EclipseActions.Undo;
import org.eclipse.emf.eef.modelingBot.helper.EEFModelingBotHelper;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
/**
* Interpreter for SWTEEFBot or BatchModelingBot.
*
* @author <a href="mailto:nathalie.lepine@obeo.fr">Nathalie Lepine</a>
*/
public class EEFInterpreter implements IModelingBotInterpreter {
/**
* Editing domain.
*/
private EditingDomain editingDomain;
/**
* Map ReFerenceableObject -> EObject created.
*/
private Map<ReferenceableObject, EObject> refObjectToEObjectMap = new HashMap<ReferenceableObject, EObject>();
/**
* Map Sequence -> boolean to know if the sequence has been canceled.
*/
private Map<Sequence, Boolean> mapSequenceToCancel = new HashMap<Sequence, Boolean>();
/**
* Set Action to know if the action has to be canceled.
*/
private Set<PropertiesEditionElement> actionsToCancel = new HashSet<PropertiesEditionElement>();
/**
* Modeling bot.
*/
private IModelingBot bot;
/**
* PropertiesEditionContext.
*/
private PropertiesEditionContext propertiesEditionContext;
/**
* Collection of Actions already processed.
*/
private Collection<Action> processedActions = new HashSet<Action>();
/**
* Create the interpreter.
*
* @param editingDomain
* editing domain
* @param bot
* the modelingbot
*/
public EEFInterpreter(IModelingBot bot, EditingDomain editingDomain) {
super();
this.editingDomain = editingDomain;
this.bot = bot;
}
/**
* @return the map of ReferenceableObject
*/
public Map<ReferenceableObject, EObject> getRefObjectToEObject() {
return refObjectToEObjectMap;
}
/**
* Set the object corresponding to the referenceable object.
*
* @param refObjectToEObject
* ReferenceableObject
*/
public void setRefObjectToEObject(Map<ReferenceableObject, EObject> refObjectToEObject) {
this.refObjectToEObjectMap = refObjectToEObject;
}
/**
* Returns the referenced object.
*
* @param ref
* ReferenceableObject
* @return the object corresponding to the referenceable object
*/
public EObject getEObjectFromReferenceableEObject(ReferenceableObject ref) {
return refObjectToEObjectMap.get(ref);
}
/**
* @return
*/
public Set<PropertiesEditionElement> getActionsToCancel() {
return actionsToCancel;
}
public Map<Sequence, Boolean> getMapSequenceToCancel() {
return mapSequenceToCancel;
}
/**
* Dispose the maps of the interpreter.
*/
public void dispose() {
refObjectToEObjectMap.clear();
mapSequenceToCancel.clear();
refObjectToEObjectMap = null;
mapSequenceToCancel = null;
}
/**
* Get the loaded resource.
*
* @param path
* path of the model
* @return the resource loaded
*/
public Resource loadModel(String path) {
final URI fileURI = URI.createPlatformPluginURI(path, true);
final Resource resource = editingDomain.getResourceSet().getResource(fileURI, true);
assertNotNull("The modeling bot resource can not be loaded.", resource);
return resource;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#runModelingBot(java.lang.String,
* org.eclipse.emf.eef.modelingBot.IModelingBot)
*/
public void runModelingBot(String path) throws CoreException, IOException {
final Resource modelingBotResource = loadModel(path);
EcoreUtil.resolveAll(modelingBotResource.getResourceSet());
assertFalse("The modeling bot resource is empty.", modelingBotResource.getContents().isEmpty());
assertTrue("The modeling bot model contains errors, correct them first", modelingBotResource
.getErrors().isEmpty());
final ModelingBot mbot = (ModelingBot)modelingBotResource.getContents().get(0);
final Diagnostic diag = Diagnostician.INSTANCE.validate(mbot);
if (diag.getSeverity() != Diagnostic.OK) {
displayDiag(diag);
}
assertTrue("The modeling bot model contains errors, correct them first",
diag.getSeverity() == Diagnostic.OK);
assertNotNull("The modeling bot resource is empty.", mbot);
propertiesEditionContext = mbot.getPropertiesEditionContext();
for (Sequence sequence : mbot.getSequences()) {
if (sequence instanceof Scenario) {
final Scenario scenario = (Scenario)sequence;
runSequence(scenario);
}
}
}
private void displayDiag(final Diagnostic diag) {
System.out.println("Source: " + diag.getSource() + " - Message: " + diag.getMessage() + " - Ex:" + diag.getException());
for (Diagnostic subDiag : diag.getChildren()) {
displayDiag(subDiag);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#runSequence(org.eclipse.emf.eef.modelingBot.Sequence)
*/
public void runSequence(Sequence sequence) {
preProcessing(sequence);
for (Processing processing : sequence.getProcessings()) {
if (processing instanceof Action) {
runAction((Action)processing);
} else if (processing instanceof DetailsPage) {
bot.setSequenceType(SequenceType.DETAILS_PAGE);
runSequence((DetailsPage)processing);
} else if (processing instanceof PropertiesView) {
bot.setSequenceType(SequenceType.PROPERTIES_VIEW);
runSequence((PropertiesView)processing);
} else if (processing instanceof Wizard) {
bot.setSequenceType(SequenceType.WIZARD);
runSequence((Wizard)processing);
}
}
postProcessing(sequence);
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#preProcessing(org.eclipse.emf.eef.modelingBot.Sequence)
*/
public void preProcessing(Sequence sequence) {
if (sequence instanceof Wizard) {
bot.initWizard((Wizard)sequence);
}
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#postProcessing(org.eclipse.emf.eef.modelingBot.Sequence)
*/
public void postProcessing(Sequence sequence) {
if (sequence instanceof Wizard) {
final Boolean hasCanceled = mapSequenceToCancel.get(sequence);
if (hasCanceled == null || !hasCanceled) {
try {
bot.validateBatchEditing();
} catch (WidgetNotFoundException e) {
// Cancel has been done
}
}
mapSequenceToCancel.remove(sequence);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#runAction(org.eclipse.emf.eef.modelingBot.Action)
*/
public void runAction(Action action) {
if (!processedActions.contains(action)) {
if (action instanceof EditAction && EEFModelingBotHelper.isFollowingByCancel(action)) {
actionsToCancel.add(((EditAction)action).getPropertiesEditionElement());
// if (bot instanceof SWTEEFBot) {
// processedActions.add(EEFModelingBotHelper.getFollowingCancelAction(action));
// }
}
if (action instanceof CreateProject) {
bot.createProject(((CreateProject)action).getProjectName());
} else if (action instanceof OpenEEFEditor) {
bot.openEEFEditor(((OpenEEFEditor)action).getEditorName());
} else if (action instanceof OpenEditor) {
final EObject root = bot.openEditor(((OpenEditor)action).getEditorName());
for (ReferenceableObject refObj : refObjectToEObjectMap.keySet()) {
if (refObj instanceof CreateModel) {
refObjectToEObjectMap.put(refObj, root);
}
}
} else if (action instanceof CreateModel) {
final EObject addedObject = bot.createModel(((CreateModel)action).getPath(),
((CreateModel)action).getModelName(), ((CreateModel)action).getRoot());
addModelMap((CreateModel)action, addedObject);
} else if (action instanceof Add) {
PropertiesEditionElement propertiesEditionElement = ((Add)action)
.getPropertiesEditionElement();
if (propertiesEditionElement != null) {
final EObject addedObject = bot.add(propertiesEditionElement,
((Add)action).getReferenceableObject(), (ReferenceableObject)action,
((Add)action).getEContainingFeature(), ((Add)action).getType());
if (addedObject != null) {
addActionMap((Add)action, addedObject);
}
} else {
final EObject addedObject = bot.add(propertiesEditionElement, null,
((Add)action).getReferenceableObject(), ((Add)action).getEContainingFeature(),
((Add)action).getType());
if (addedObject != null) {
addActionMap((Add)action, addedObject);
}
}
} else if (action instanceof MoveDown) {
bot.moveDown(((MoveDown)action).getPropertiesEditionElement(),
((MoveDown)action).getReferenceableObject());
} else if (action instanceof MoveUp) {
bot.moveUp(((MoveUp)action).getPropertiesEditionElement(),
((MoveUp)action).getReferenceableObject());
} else if (action instanceof SetAttribute) {
bot.setAttribute(((SetAttribute)action).getPropertiesEditionElement(),
((SetAttribute)action).getReferenceableObject(),
((SetAttribute)action).getEContainingFeature(), ((SetAttribute)action).getValues());
} else if (action instanceof SetReference) {
bot.setReference(((SetReference)action).getPropertiesEditionElement(),
((SetReference)action).getReferenceableObject(),
((SetReference)action).getEContainingFeature(), ((SetReference)action).getValues());
} else if (action instanceof Save) {
bot.save();
} else if (action instanceof CloseEditor) {
bot.closeEditor(((CloseEditor)action).getPath());
} else if (action instanceof CloseProject) {
bot.closeProject(((CloseProject)action).getProjectName());
} else if (action instanceof RemoveProject) {
bot.removeProject(((RemoveProject)action).getProjectName());
} else if (action instanceof Cancel) {
Sequence eContainerSequence = (Sequence)action.eContainer();
mapSequenceToCancel.put(eContainerSequence, true);
if (eContainerSequence instanceof Wizard ||
((eContainerSequence instanceof DetailsPage
|| eContainerSequence instanceof PropertiesView) && !actionsToCancel.isEmpty())) {
bot.cancel(((Cancel)action).getProcessing());
}
} else if (action instanceof Unset) {
bot.unset(((Unset)action).getPropertiesEditionElement(),
((Unset)action).getReferenceableObject(), ((Unset)action).getFeature());
} else if (action instanceof UnsetAttribute) {
bot.unsetAttribute(((UnsetAttribute)action).getPropertiesEditionElement(),
((UnsetAttribute)action).getReferenceableObject(),
((UnsetAttribute)action).getEContainingFeature(),
((UnsetAttribute)action).getValues());
} else if (action instanceof UnsetReference) {
bot.unsetReference(((UnsetReference)action).getPropertiesEditionElement(),
((UnsetReference)action).getReferenceableObject(),
((UnsetReference)action).getFeature(), ((UnsetReference)action).getValues());
} else if (action instanceof Remove) {
bot.remove(((Remove)action).getPropertiesEditionElement(),
((Remove)action).getReferenceableObject());
refObjectToEObjectMap.remove(((Remove)action).getReferenceableObject());
} else if (action instanceof Undo) {
bot.undo(action);
} else if (action instanceof Redo) {
bot.redo(action);
}
processedActions.add(action);
}
}
private void addActionMap(ReferenceableObject action, EObject obj) {
refObjectToEObjectMap.put(action, obj);
}
private void addModelMap(CreateModel action, EObject obj) {
refObjectToEObjectMap.put(action, obj);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.eef.modelingBot.interpreter.IModelingBotInterpreter#getPropertiesEditionContext()
*/
public PropertiesEditionContext getPropertiesEditionContext() {
return propertiesEditionContext;
}
/**
* @param pec
* the propertiesEditionContext to set
*/
public void setPropertiesEditionContext(PropertiesEditionContext pec) {
this.propertiesEditionContext = pec;
}
}