/*
* Copyright (c) 2006, 2010 Borland Software Corporation and others
*
* 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:
* Boris Blajer (Borland) - initial API and implementation
*/
package org.eclipse.gmf.tests.setup;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gmf.codegen.gmfgen.GenCommonBase;
import org.eclipse.gmf.codegen.gmfgen.GenDiagram;
import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator;
import org.eclipse.gmf.codegen.util.CodegenEmitters;
import org.eclipse.gmf.codegen.util.Generator;
import org.eclipse.gmf.internal.common.codegen.GeneratorBase;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest.ConnectionViewAndElementDescriptor;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.swt.graphics.RGB;
public class RuntimeBasedGeneratorConfiguration extends AbstractGeneratorConfiguration {
public GeneratorBase createGenerator(GenDiagram diagram) {
final GenEditorGenerator editorGen = diagram.getEditorGen();
// using caching EmitterSource saves few seconds on test execution (115-118 compared to 112)
// but it seems reasonable to avoid unpredictability of reuse (due to use of soft references)
// and might be good idea to have separate test to test emitter reuse explicitly
return new Generator(editorGen, new CodegenEmitters(!editorGen.isDynamicTemplates(), editorGen.getTemplateDirectory(), editorGen.getModelAccess() != null));
}
public ViewerConfiguration createViewerConfiguration(EditPartViewer viewer, GeneratedDiagramPlugin genPlugin) {
return new DefaultViewerConfiguration(viewer, genPlugin);
}
protected EditPartViewer createViewerInstance() {
return new FakeViewer();
}
public static Diagram createDiagram(EObject domainElement, GeneratedDiagramPlugin genPlugin) {
try {
String pluginClassName = genPlugin.getGenDiagram().getEditorGen().getPlugin().getActivatorQualifiedClassName();
Class<?> pluginClass = genPlugin.loadGeneratedClass(pluginClassName);
Field field = pluginClass.getField("DIAGRAM_PREFERENCES_HINT");
final PreferencesHint hint = (PreferencesHint) field.get(null);
return ViewService.createDiagram(domainElement, genPlugin.getGenDiagram().getEditorGen().getModelID(), hint);
} catch (Exception ex) {
Assert.fail(ex.toString());
}
return null;
}
protected static class DefaultViewerConfiguration extends AbstractViewerConfiguration {
public DefaultViewerConfiguration(EditPartViewer viewer, GeneratedDiagramPlugin genPlugin) {
super(viewer, genPlugin);
}
public Command getSetBusinessElementStructuralFeatureCommand(View view, String featureName, Object value) {
EObject instance = view.getElement();
Assert.assertNotNull("No business element bound to notation element", instance); //$NON-NLS-1$
EStructuralFeature feature = instance.eClass().getEStructuralFeature(featureName);
if (feature == null) {
throw new IllegalArgumentException("Not existing feature: " + featureName); //$NON-NLS-1$
}
SetRequest setReq = new SetRequest(instance, feature, value);
EditPart editPart = findEditPart(view);
TransactionalEditingDomain txEditDomain = getEditDomain(editPart);
CompositeTransactionalCommand modelCmd = new CompositeTransactionalCommand(txEditDomain, "Set feature"); //$NON-NLS-1$
modelCmd.compose(new SetValueCommand(setReq));
return new ICommandProxy(modelCmd);
}
public Command getSetNotationalElementStructuralFeature(View view, final EStructuralFeature feature, final Object value) {
Assert.assertNotNull("Null view", view); //$NON-NLS-1$
Assert.assertNotNull("Null feature", feature); //$NON-NLS-1$
final EditPart editPart = findEditPart(view);
Assert.assertNotNull("Cannot find edit part", editPart); //$NON-NLS-1$
TransactionalEditingDomain ed = getEditDomain(editPart);
Assert.assertNotNull("No TransactionalEditingDomain found", ed); //$NON-NLS-1$
return new ICommandProxy(new AbstractTransactionalCommand(ed, "ChangeColor", Collections.EMPTY_LIST) {
protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
IGraphicalEditPart ep = (IGraphicalEditPart) editPart;
ep.setStructuralFeatureValue(feature, value);
return null;
}
});
}
protected TransactionalEditingDomain getEditDomain(EditPart editPart) {
Assert.assertTrue("IGraphicalEditPart expected", editPart instanceof IGraphicalEditPart); //$NON-NLS-1$
return ((IGraphicalEditPart) editPart).getEditingDomain();
}
public Command getCreateNodeCommand(View parentView, GenCommonBase nodeType) {
IElementType metamodelType = getElementType(nodeType);
CreateUnspecifiedTypeRequest req = new CreateUnspecifiedTypeRequest(Arrays.asList(new IElementType[] { metamodelType }), getDefaultPreferencesHint());
return findEditPart(parentView).getCommand(req);
}
public Command getStartLinkCommand(View source, GenCommonBase linkType) {
IElementType metamodelType = getElementType(linkType);
CreateRelationshipRequest req = new CreateRelationshipRequest(source.getElement(), null, metamodelType);
EditCommandRequestWrapper wrapper = new EditCommandRequestWrapper(req);
return findEditPart(source).getCommand(wrapper);
}
public Command getCreateLinkCommand(View source, View target, GenCommonBase linkType) {
IElementType metamodelType = getElementType(linkType);
CreateRelationshipRequest relationShipReq = new CreateRelationshipRequest(metamodelType);
ConnectionViewAndElementDescriptor desc = new ConnectionViewAndElementDescriptor(new CreateElementRequestAdapter(relationShipReq), metamodelType instanceof IHintedType ? ((IHintedType) metamodelType).getSemanticHint() : "", getDefaultPreferencesHint());
CreateConnectionViewAndElementRequest req = new CreateConnectionViewAndElementRequest(desc);
req.setType(RequestConstants.REQ_CONNECTION_START);
EditPart sourceEditPart = findEditPart(source);
req.setSourceEditPart(sourceEditPart);
// Note: initializes the sourceCommand in the request
Command sourceCmd = sourceEditPart.getCommand(req);
if (sourceCmd == null || !sourceCmd.canExecute()) {
return null;
}
EditPart targetEditPart = target != null ? findEditPart(target) : null;
if (targetEditPart != null) {
req.setType(RequestConstants.REQ_CONNECTION_END);
req.setTargetEditPart(targetEditPart);
req.setLocation(new Point(0, 0));
sourceEditPart.getCommand(req);
Command targetCmd = targetEditPart.getCommand(req);
return targetCmd;
}
return null;
}
public RGB getDefaultLinkColor() {
return PreferenceConverter.getColor(getDefaultPreferences(), IPreferenceConstants.PREF_LINE_COLOR);
}
private IElementType getElementType(GenCommonBase genElement) {
Class<?> clazz = null;
try {
clazz = loadGeneratedClass(getGenModel().getElementTypesQualifiedClassName());
} catch (Exception e) {
e.printStackTrace();
Assert.fail("ElementTypes class not loaded. " + e.getLocalizedMessage()); //$NON-NLS-1$
}
String identifier = genElement.getUniqueIdentifier();
try {
Object type = clazz.getField(identifier).get(null);
assert type != null : "Metatype field in the ElementTypes class should be initialized: " + identifier + " in " + getGenModel().getEditorGen().getPlugin().getID(); //$NON-NLS-1$ //$NON-NLS-2$
assert type instanceof IElementType : IElementType.class.getName() + ": metamodel type class required"; //$NON-NLS-1$
return (IElementType) type;
} catch (NoSuchFieldException e) {
Assert.fail("Metamodel type " + identifier + " is not registered"); //$NON-NLS-1$ //$NON-NLS-2$
} catch (Exception e) {
e.printStackTrace();
Assert.fail("Can't access metamodel type " + identifier); //$NON-NLS-1$
}
return null;
}
}
private static final class FakeViewer extends AbstractFakeViewer implements IDiagramGraphicalViewer{
private FakeViewer() {
/*
* When extends DiagramGraphicalViewer, don't forget to
* super.hookWorkspacePreferenceStore(new PreferenceStore());
*/
}
public void setContents(Object contents) {
GraphicalEditPart epart = (GraphicalEditPart)getEditPartFactory().createEditPart(null, contents);
DiagramEventBroker.startListening(epart.getEditingDomain());
super.setContents(epart);
}
public IDiagramEditDomain getDiagramEditDomain() {
return (IDiagramEditDomain) super.getEditDomain();
}
@SuppressWarnings("rawtypes")
public List findEditPartsForElement(String elementIdStr, Class editPartClass) {
return Collections.EMPTY_LIST;
}
public void registerEditPartForElement(String elementIdStr, EditPart ep) {
}
public void unregisterEditPartForElement(String elementIdStr, EditPart ep) {
}
}
}