blob: 4145eb6adac198489b30dba866fcbd108087548f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
* All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
*
* @author Innar Made
******************************************************************************/
package org.eclipse.bpmn2.modeler.ui.editor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.bpmn2.Activity;
import org.eclipse.bpmn2.Assignment;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.BoundaryEvent;
import org.eclipse.bpmn2.CallActivity;
import org.eclipse.bpmn2.CallChoreography;
import org.eclipse.bpmn2.CatchEvent;
import org.eclipse.bpmn2.Category;
import org.eclipse.bpmn2.CompensateEventDefinition;
import org.eclipse.bpmn2.ConditionalEventDefinition;
import org.eclipse.bpmn2.DataInput;
import org.eclipse.bpmn2.DataObject;
import org.eclipse.bpmn2.DataObjectReference;
import org.eclipse.bpmn2.DataOutput;
import org.eclipse.bpmn2.DataStore;
import org.eclipse.bpmn2.DataStoreReference;
import org.eclipse.bpmn2.EndEvent;
import org.eclipse.bpmn2.ErrorEventDefinition;
import org.eclipse.bpmn2.EscalationEventDefinition;
import org.eclipse.bpmn2.Event;
import org.eclipse.bpmn2.Expression;
import org.eclipse.bpmn2.FormalExpression;
import org.eclipse.bpmn2.Gateway;
import org.eclipse.bpmn2.GlobalBusinessRuleTask;
import org.eclipse.bpmn2.GlobalManualTask;
import org.eclipse.bpmn2.GlobalScriptTask;
import org.eclipse.bpmn2.GlobalTask;
import org.eclipse.bpmn2.GlobalUserTask;
import org.eclipse.bpmn2.HumanPerformer;
import org.eclipse.bpmn2.Import;
import org.eclipse.bpmn2.InputOutputSpecification;
import org.eclipse.bpmn2.Interface;
import org.eclipse.bpmn2.ItemDefinition;
import org.eclipse.bpmn2.LinkEventDefinition;
import org.eclipse.bpmn2.ManualTask;
import org.eclipse.bpmn2.Message;
import org.eclipse.bpmn2.MessageEventDefinition;
import org.eclipse.bpmn2.MessageFlow;
import org.eclipse.bpmn2.MultiInstanceLoopCharacteristics;
import org.eclipse.bpmn2.Performer;
import org.eclipse.bpmn2.PotentialOwner;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.Property;
import org.eclipse.bpmn2.ResourceAssignmentExpression;
import org.eclipse.bpmn2.ResourceParameterBinding;
import org.eclipse.bpmn2.ResourceRole;
import org.eclipse.bpmn2.ScriptTask;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.SignalEventDefinition;
import org.eclipse.bpmn2.StandardLoopCharacteristics;
import org.eclipse.bpmn2.StartEvent;
import org.eclipse.bpmn2.SubProcess;
import org.eclipse.bpmn2.Task;
import org.eclipse.bpmn2.TextAnnotation;
import org.eclipse.bpmn2.ThrowEvent;
import org.eclipse.bpmn2.TimerEventDefinition;
import org.eclipse.bpmn2.di.BPMNDiagram;
import org.eclipse.bpmn2.modeler.core.Bpmn2TabbedPropertySheetPage;
import org.eclipse.bpmn2.modeler.core.ModelHandler;
import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;
import org.eclipse.bpmn2.modeler.core.ProxyURIConverterImplExtension;
import org.eclipse.bpmn2.modeler.core.di.DIImport;
import org.eclipse.bpmn2.modeler.core.di.DIUtils;
import org.eclipse.bpmn2.modeler.core.merrimac.clad.DefaultDetailComposite;
import org.eclipse.bpmn2.modeler.core.merrimac.clad.DefaultDialogComposite;
import org.eclipse.bpmn2.modeler.core.merrimac.clad.DefaultListComposite;
import org.eclipse.bpmn2.modeler.core.merrimac.clad.PropertiesCompositeFactory;
import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerResourceImpl;
import org.eclipse.bpmn2.modeler.core.preferences.Bpmn2Preferences;
import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.utils.DiagramEditorAdapter;
import org.eclipse.bpmn2.modeler.core.utils.ErrorUtils;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil.Bpmn2DiagramType;
import org.eclipse.bpmn2.modeler.core.utils.StyleUtil;
import org.eclipse.bpmn2.modeler.core.validation.BPMN2ProjectValidator;
import org.eclipse.bpmn2.modeler.core.validation.BPMN2ValidationStatusLoader;
import org.eclipse.bpmn2.modeler.ui.Activator;
import org.eclipse.bpmn2.modeler.ui.property.artifact.CategoryDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.artifact.TextAnnotationDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.connectors.MessageFlowDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.connectors.SequenceFlowDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ConditionalEventDefinitionDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.DataAssignmentDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.DataObjectPropertySection.DataObjectDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.DataObjectReferencePropertySection.DataObjectReferenceDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.DataStorePropertySection.DataStoreDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.DataStoreReferencePropertySection.DataStoreReferenceDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ExpressionDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.InterfaceDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ItemAwareElementDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.MessageDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.MessageListComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ResourceAssignmentExpressionDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ResourceParameterBindingDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.data.ResourceRoleDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.DefinitionsPropertyComposite.ImportDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.ItemDefinitionDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.ItemDefinitionListComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.ProcessDiagramPropertyComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.PropertyListComposite;
import org.eclipse.bpmn2.modeler.ui.property.diagrams.ResourceRoleListComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.BoundaryEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.CatchEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.CommonEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.CommonEventPropertySection.EventDefinitionDialogComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.EndEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.StartEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.ThrowEventDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.events.TimerEventDefinitionDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.gateways.GatewayDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.ActivityDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.ActivityInputDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.ActivityOutputDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.DataAssociationDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.IoParametersDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.ManualTaskDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.MultiInstanceLoopCharacteristicsDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.ScriptTaskDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.StandardLoopCharacteristicsDetailComposite;
import org.eclipse.bpmn2.modeler.ui.property.tasks.TaskDetailComposite;
import org.eclipse.bpmn2.modeler.ui.views.outline.BPMN2EditorOutlinePage;
import org.eclipse.bpmn2.modeler.ui.wizards.BPMN2DiagramCreator;
import org.eclipse.bpmn2.modeler.ui.wizards.Bpmn2DiagramEditorInput;
import org.eclipse.bpmn2.modeler.ui.wizards.FileService;
import org.eclipse.bpmn2.util.Bpmn2ResourceImpl;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain.Lifecycle;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IPeService;
import org.eclipse.graphiti.ui.editor.DefaultPersistencyBehavior;
import org.eclipse.graphiti.ui.editor.DefaultUpdateBehavior;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.graphiti.ui.editor.DiagramEditorInput;
import org.eclipse.graphiti.ui.internal.editor.GFPaletteRoot;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabDescriptorProvider;
/**
*
*/
@SuppressWarnings("restriction")
public class BPMN2Editor extends DiagramEditor implements IPropertyChangeListener, IGotoMarker {
// Register the Default List and Detail Composites as fallback for rendering EObject
static {
PropertiesCompositeFactory.register(EObject.class, DefaultDetailComposite.class);
PropertiesCompositeFactory.register(EObject.class, DefaultListComposite.class);
PropertiesCompositeFactory.register(EObject.class, DefaultDialogComposite.class);
PropertiesCompositeFactory.register(Message.class, MessageDetailComposite.class);
PropertiesCompositeFactory.register(Message.class, MessageListComposite.class);
PropertiesCompositeFactory.register(MessageFlow.class, MessageFlowDetailComposite.class);
PropertiesCompositeFactory.register(Property.class, ItemAwareElementDetailComposite.class);
PropertiesCompositeFactory.register(CallActivity.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(GlobalTask.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(GlobalBusinessRuleTask.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(GlobalManualTask.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(GlobalScriptTask.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(GlobalUserTask.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(Import.class, ImportDetailComposite.class);
PropertiesCompositeFactory.register(Category.class, CategoryDetailComposite.class);
PropertiesCompositeFactory.register(TextAnnotation.class, TextAnnotationDetailComposite.class);
PropertiesCompositeFactory.register(SequenceFlow.class, SequenceFlowDetailComposite.class);
PropertiesCompositeFactory.register(DataObject.class, DataObjectDetailComposite.class);
PropertiesCompositeFactory.register(DataObjectReference.class, DataObjectDetailComposite.class);
PropertiesCompositeFactory.register(Assignment.class, DataAssignmentDetailComposite.class);
PropertiesCompositeFactory.register(Expression.class, ExpressionDetailComposite.class);
PropertiesCompositeFactory.register(FormalExpression.class, ExpressionDetailComposite.class);
PropertiesCompositeFactory.register(ResourceAssignmentExpression.class, ResourceAssignmentExpressionDetailComposite.class);
PropertiesCompositeFactory.register(ResourceParameterBinding.class, ResourceParameterBindingDetailComposite.class);
PropertiesCompositeFactory.register(PotentialOwner.class, ResourceRoleDetailComposite.class);
PropertiesCompositeFactory.register(HumanPerformer.class, ResourceRoleDetailComposite.class);
PropertiesCompositeFactory.register(Performer.class, ResourceRoleDetailComposite.class);
PropertiesCompositeFactory.register(DataObjectReference.class, DataObjectReferenceDetailComposite.class);
PropertiesCompositeFactory.register(DataStore.class, DataStoreDetailComposite.class);
PropertiesCompositeFactory.register(DataStoreReference.class, DataStoreReferenceDetailComposite.class);
PropertiesCompositeFactory.register(Interface.class, InterfaceDetailComposite.class);
PropertiesCompositeFactory.register(ItemDefinition.class, ItemDefinitionDetailComposite.class);
PropertiesCompositeFactory.register(ItemDefinition.class, ItemDefinitionListComposite.class);
PropertiesCompositeFactory.register(Property.class, PropertyListComposite.class);
PropertiesCompositeFactory.register(ResourceRole.class, ResourceRoleListComposite.class);
PropertiesCompositeFactory.register(Event.class, CommonEventDetailComposite.class);
PropertiesCompositeFactory.register(StartEvent.class, StartEventDetailComposite.class);
PropertiesCompositeFactory.register(EndEvent.class, EndEventDetailComposite.class);
PropertiesCompositeFactory.register(CatchEvent.class, CatchEventDetailComposite.class);
PropertiesCompositeFactory.register(ThrowEvent.class, ThrowEventDetailComposite.class);
PropertiesCompositeFactory.register(BoundaryEvent.class, BoundaryEventDetailComposite.class);
PropertiesCompositeFactory.register(TimerEventDefinition.class, TimerEventDefinitionDetailComposite.class);
PropertiesCompositeFactory.register(ConditionalEventDefinition.class, ConditionalEventDefinitionDetailComposite.class);
PropertiesCompositeFactory.register(CompensateEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(ConditionalEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(ErrorEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(EscalationEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(LinkEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(MessageEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(SignalEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(TimerEventDefinition.class, EventDefinitionDialogComposite.class);
PropertiesCompositeFactory.register(Process.class, ProcessDiagramPropertyComposite.class);
PropertiesCompositeFactory.register(EndEvent.class, EndEventDetailComposite.class);
PropertiesCompositeFactory.register(StartEvent.class, StartEventDetailComposite.class);
PropertiesCompositeFactory.register(ThrowEvent.class, ThrowEventDetailComposite.class);
PropertiesCompositeFactory.register(StandardLoopCharacteristics.class, StandardLoopCharacteristicsDetailComposite.class);
PropertiesCompositeFactory.register(MultiInstanceLoopCharacteristics.class, MultiInstanceLoopCharacteristicsDetailComposite.class);
PropertiesCompositeFactory.register(Gateway.class, GatewayDetailComposite.class);
PropertiesCompositeFactory.register(Activity.class, ActivityInputDetailComposite.class);
PropertiesCompositeFactory.register(InputOutputSpecification.class, ActivityInputDetailComposite.class);
PropertiesCompositeFactory.register(Activity.class, ActivityOutputDetailComposite.class);
PropertiesCompositeFactory.register(CallChoreography.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(InputOutputSpecification.class, IoParametersDetailComposite.class);
PropertiesCompositeFactory.register(DataInput.class, DataAssociationDetailComposite.class);
PropertiesCompositeFactory.register(DataOutput.class, DataAssociationDetailComposite.class);
PropertiesCompositeFactory.register(ManualTask.class, ManualTaskDetailComposite.class);
PropertiesCompositeFactory.register(ScriptTask.class, ScriptTaskDetailComposite.class);
PropertiesCompositeFactory.register(SubProcess.class, ActivityDetailComposite.class);
PropertiesCompositeFactory.register(Task.class, TaskDetailComposite.class);
}
public static final String EDITOR_ID = "org.eclipse.bpmn2.modeler.ui.bpmn2editor";
public static final String CONTRIBUTOR_ID = "org.eclipse.bpmn2.modeler.ui.PropertyContributor";
private ModelHandler modelHandler;
private URI modelUri;
private URI diagramUri;
private boolean editable = true;
protected BPMNDiagram bpmnDiagram;
protected Bpmn2ResourceImpl bpmnResource;
private IWorkbenchListener workbenchListener;
private IPartListener2 selectionListener;
private IResourceChangeListener markerChangeListener;
private boolean workbenchShutdown = false;
private static BPMN2Editor activeEditor;
private static ITabDescriptorProvider tabDescriptorProvider;
private BPMN2EditingDomainListener editingDomainListener;
private Bpmn2Preferences preferences;
private TargetRuntime targetRuntime;
// private Hashtable<BPMNDiagram, GraphicalViewer> mapDiagramToViewer = new Hashtable<BPMNDiagram, GraphicalViewer>();
protected DiagramEditorAdapter editorAdapter;
protected BPMN2MultiPageEditor multipageEditor;
public BPMN2Editor(BPMN2MultiPageEditor mpe) {
multipageEditor = mpe;
}
public static BPMN2Editor getActiveEditor() {
return activeEditor;
}
private void setActiveEditor(BPMN2Editor editor) {
activeEditor = editor;
if (activeEditor!=null) {
Bpmn2Preferences.setActiveProject(activeEditor.getProject());
TargetRuntime.setCurrentRuntime( activeEditor.getTargetRuntime() );
}
}
public BPMN2MultiPageEditor getMultipageEditor() {
return multipageEditor;
}
protected DiagramEditorAdapter getEditorAdapter() {
return editorAdapter;
}
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
try {
Bpmn2DiagramType diagramType = Bpmn2DiagramType.NONE;
String targetNamespace = null;
bpmnDiagram = null;
if (input instanceof IStorageEditorInput) {
input = createNewDiagramEditorInput(site, input, diagramType, targetNamespace);
}
else if (input instanceof DiagramEditorInput) {
if (input instanceof Bpmn2DiagramEditorInput) {
diagramType = ((Bpmn2DiagramEditorInput)input).getInitialDiagramType();
targetNamespace = ((Bpmn2DiagramEditorInput)input).getTargetNamespace();
bpmnDiagram = ((Bpmn2DiagramEditorInput)input).getBpmnDiagram();
}
if (bpmnDiagram==null) {
// This was incorrectly constructed input, we ditch the old one and make a new and clean one instead
// This code path comes in from the New File Wizard
input = createNewDiagramEditorInput(site, input, diagramType, targetNamespace);
}
else {
BPMNDiagram d = bpmnDiagram;
bpmnDiagram = null;
setBpmnDiagram(d);
return;
}
}
else {
throw new PartInitException("Invalid Editor Input: "
+input.getClass().getSimpleName()+" "
+input.getName());
}
} catch (Exception e) {
Activator.showErrorWithLogging(e);
throw new PartInitException(e.getMessage());
}
// add a listener so we get notified if the workbench is shutting down.
// in this case we don't want to delete the temp file!
addWorkbenchListener();
getTargetRuntime(input);
setActiveEditor(this);
super.init(site, input);
addSelectionListener();
addMarkerChangeListener();
}
public void setEditable(boolean editable) {
this.editable = editable;
}
public boolean isEditable() {
return editable;
}
@Override
public boolean isDirty() {
if (!editable)
return false;
return super.isDirty();
}
@Override
protected DefaultUpdateBehavior createUpdateBehavior() {
return new BPMN2EditorUpdateBehavior(this);
}
@Override
protected DefaultPersistencyBehavior createPersistencyBehavior() {
return new BPMN2PersistencyBehavior(this);
}
public Bpmn2Preferences getPreferences() {
if (preferences==null) {
loadPreferences(getProject());
}
return preferences;
}
private void loadPreferences(IProject project) {
preferences = Bpmn2Preferences.getInstance(project);
preferences.load();
preferences.getGlobalPreferences().addPropertyChangeListener(this);
}
/**
* ID for tabbed property sheets.
*
* @return the contributor id
*/
@Override
public String getContributorId() {
return CONTRIBUTOR_ID;
}
public TargetRuntime getTargetRuntime(ITabDescriptorProvider tdp) {
tabDescriptorProvider = tdp;
return getTargetRuntime();
}
public TargetRuntime getTargetRuntime() {
if (targetRuntime==null) {
targetRuntime = getTargetRuntime(getEditorInput());
}
return targetRuntime;
}
protected TargetRuntime getTargetRuntime(IEditorInput input) {
if (targetRuntime==null) {
// If the project has not been configured for a specific runtime through the "BPMN2"
// project properties page (i.e. the target is "None") then allow the runtime extension
// plug-ins an opportunity to identify the given process file contents as their own.
// If none of the plug-ins respond with "yes, this file is targeted for my runtime",
// then use the "None" as the extension. This will configure the BPMN2 Modeler with
// generic property sheets and other default behavior.
targetRuntime = getPreferences().getRuntime();
if (targetRuntime == TargetRuntime.getDefaultRuntime()) {
for (TargetRuntime rt : TargetRuntime.getAllRuntimes()) {
if (rt.getRuntimeExtension().isContentForRuntime(input)) {
targetRuntime = rt;
break;
}
}
}
}
return targetRuntime;
}
/**
* Beware, creates a new input and changes this editor!
*/
private Bpmn2DiagramEditorInput createNewDiagramEditorInput(IEditorSite site, IEditorInput input, Bpmn2DiagramType diagramType, String targetNamespace)
throws CoreException {
modelUri = FileService.getInputUri(input);
input = BPMN2DiagramCreator.createDiagram(modelUri, diagramType,targetNamespace,this);
diagramUri = ((Bpmn2DiagramEditorInput)input).getUri();
return (Bpmn2DiagramEditorInput)input;
}
private void saveModelFile() {
modelHandler.save();
((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();
updateDirtyState();
}
@Override
protected void setInput(IEditorInput input) {
super.setInput(input);
// Hook a transaction exception handler so we can get diagnostics about EMF validation errors.
getEditingDomainListener();
BasicCommandStack basicCommandStack = (BasicCommandStack) getEditingDomain().getCommandStack();
if (input instanceof DiagramEditorInput) {
ResourceSet resourceSet = getEditingDomain().getResourceSet();
getTargetRuntime().setResourceSet(resourceSet);
bpmnResource = (Bpmn2ResourceImpl) resourceSet.createResource(modelUri,
Bpmn2ModelerResourceImpl.BPMN2_CONTENT_TYPE_ID);
resourceSet.setURIConverter(new ProxyURIConverterImplExtension());
resourceSet.eAdapters().add(editorAdapter = new DiagramEditorAdapter(this));
modelHandler = ModelHandlerLocator.createModelHandler(modelUri, bpmnResource);
ModelHandlerLocator.put(diagramUri, modelHandler);
getTargetRuntime(input);
setActiveEditor(this);
// allow the runtime extension to construct custom tasks and whatever else it needs
// custom tasks should be added to the current target runtime's custom tasks list
// where they will be picked up by the toolpalette refresh.
getTargetRuntime().getRuntimeExtension().initialize(this);
try {
if (getModelFile()==null || getModelFile().exists()) {
bpmnResource.load(null);
} else {
saveModelFile();
}
} catch (IOException e) {
Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
ErrorUtils.showErrorWithLogging(status);
}
basicCommandStack.execute(new RecordingCommand(getEditingDomain()) {
@Override
protected void doExecute() {
importDiagram();
}
});
}
basicCommandStack.saveIsDone();
basicCommandStack.flush();
loadMarkers();
}
private void importDiagram() {
// make sure this guy is active, otherwise it's not selectable
Diagram diagram = getDiagramTypeProvider().getDiagram();
IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();
diagram.setActive(true);
Bpmn2DiagramEditorInput input = (Bpmn2DiagramEditorInput) getEditorInput();
Bpmn2DiagramType diagramType = input.getInitialDiagramType();
String targetNamespace = input.getTargetNamespace();
if (diagramType != Bpmn2DiagramType.NONE) {
bpmnDiagram = modelHandler.createDiagramType(diagramType, targetNamespace);
featureProvider.link(diagram, bpmnDiagram);
saveModelFile();
}
DIImport di = new DIImport(this);
di.setModelHandler(modelHandler);
di.generateFromDI();
// this needs to happen AFTER the diagram has been imported because we need
// to be able to determine the diagram type from the file's contents in order
// to build the right tool palette for the target runtime and model enablements.
GFPaletteRoot pr = (GFPaletteRoot)getPaletteRoot();
pr.updatePaletteEntries();
}
@Override
protected PictogramElement[] getPictogramElementsForSelection() {
// filter out invisible elements when setting selection
PictogramElement[] pictogramElements = super.getPictogramElementsForSelection();
if (pictogramElements==null)
return null;
ArrayList<PictogramElement> visibleList = new ArrayList<PictogramElement>();
for (PictogramElement pe : pictogramElements) {
if (pe.isVisible())
visibleList.add(pe);
}
return visibleList.toArray(new PictogramElement[visibleList.size()]);
}
private void addWorkbenchListener() {
if (workbenchListener==null) {
workbenchListener = new IWorkbenchListener() {
@Override
public boolean preShutdown(IWorkbench workbench, boolean forced) {
workbenchShutdown = true;
return true;
}
@Override
public void postShutdown(IWorkbench workbench) {
}
};
PlatformUI.getWorkbench().addWorkbenchListener(workbenchListener);
}
}
@Override
public void gotoMarker(IMarker marker) {
final EObject target = getTargetObject(marker);
if (target == null) {
return;
}
final PictogramElement pe = getDiagramTypeProvider().getFeatureProvider().getPictogramElementForBusinessObject(
target);
if (pe == null) {
return;
}
selectPictogramElements(new PictogramElement[] {pe });
}
private void loadMarkers() {
if (getModelFile()!=null) {
// read in the markers
BPMN2ValidationStatusLoader vsl = new BPMN2ValidationStatusLoader(this);
try {
vsl.load(Arrays.asList(getModelFile().findMarkers(
BPMN2ProjectValidator.BPMN2_MARKER_ID, true, IResource.DEPTH_ZERO)));
} catch (CoreException e) {
Activator.logStatus(e.getStatus());
}
}
}
private EObject getTargetObject(IMarker marker) {
final String uriString = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
final URI uri = uriString == null ? null : URI.createURI(uriString);
if (uri == null) {
return null;
}
return getEditingDomain().getResourceSet().getEObject(uri, false);
}
private void removeWorkbenchListener()
{
if (workbenchListener!=null) {
PlatformUI.getWorkbench().removeWorkbenchListener(workbenchListener);
workbenchListener = null;
}
}
private void addSelectionListener() {
if (selectionListener == null) {
IWorkbenchPage page = getSite().getPage();
selectionListener = new IPartListener2() {
public void partActivated(IWorkbenchPartReference partRef) {
}
@Override
public void partBroughtToTop(IWorkbenchPartReference partRef) {
IWorkbenchPart part = partRef.getPart(false);
if (part instanceof BPMN2MultiPageEditor) {
BPMN2MultiPageEditor mpe = (BPMN2MultiPageEditor)part;
setActiveEditor(mpe.getDesignEditor());
}
}
@Override
public void partClosed(IWorkbenchPartReference partRef) {
}
@Override
public void partDeactivated(IWorkbenchPartReference partRef) {
}
@Override
public void partOpened(IWorkbenchPartReference partRef) {
}
@Override
public void partHidden(IWorkbenchPartReference partRef) {
}
@Override
public void partVisible(IWorkbenchPartReference partRef) {
}
@Override
public void partInputChanged(IWorkbenchPartReference partRef) {
}
};
page.addPartListener(selectionListener);
}
}
private void removeSelectionListener()
{
if (selectionListener!=null) {
getSite().getPage().removePartListener(selectionListener);
selectionListener = null;
}
}
private void addMarkerChangeListener() {
if (getModelFile()!=null) {
if (markerChangeListener==null) {
markerChangeListener = new BPMN2MarkerChangeListener(this);
getModelFile().getWorkspace().addResourceChangeListener(markerChangeListener, IResourceChangeEvent.POST_BUILD);
}
}
}
private void removeMarkerChangeListener() {
if (markerChangeListener!=null) {
getModelFile().getWorkspace().removeResourceChangeListener(markerChangeListener);
markerChangeListener = null;
}
}
public void setEditorTitle(final String title) {
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
setPartName(title);
}
});
}
public BPMN2EditingDomainListener getEditingDomainListener() {
if (editingDomainListener==null) {
TransactionalEditingDomainImpl editingDomain = (TransactionalEditingDomainImpl)getEditingDomain();
if (editingDomain==null) {
return null;
}
editingDomainListener = new BPMN2EditingDomainListener(this);
Lifecycle domainLifeCycle = (Lifecycle) editingDomain.getAdapter(Lifecycle.class);
domainLifeCycle.addTransactionalEditingDomainListener(editingDomainListener);
}
return editingDomainListener;
}
public BasicDiagnostic getDiagnostics() {
return getEditingDomainListener().getDiagnostics();
}
@Override
public Object getAdapter(Class required) {
if (required==ITabDescriptorProvider.class) {
if (tabDescriptorProvider==null) {
IWorkbenchPage page = getEditorSite().getPage();
String viewID = "org.eclipse.ui.views.PropertySheet";
try {
page.showView(viewID, null, IWorkbenchPage.VIEW_CREATE);
page.showView(viewID, null, IWorkbenchPage.VIEW_ACTIVATE);
}
catch (Exception e) {}
}
return tabDescriptorProvider;
}
if (required==TargetRuntime.class)
return getTargetRuntime();
if (required==Bpmn2Preferences.class)
return getPreferences();
if (required == IPropertySheetPage.class) {
return new Bpmn2TabbedPropertySheetPage(this);
}
if (required == IContentOutlinePage.class) {
if (getDiagramTypeProvider() != null) {
BPMN2EditorOutlinePage outlinePage = new BPMN2EditorOutlinePage(this);
return outlinePage;
}
}
return super.getAdapter(required);
}
@Override
public void dispose() {
// clear ID mapping tables if no more instances of editor are active
int instances = 0;
IWorkbenchPage[] pages = getEditorSite().getWorkbenchWindow().getPages();
for (IWorkbenchPage p : pages) {
IEditorReference[] refs = p.getEditorReferences();
instances += refs.length;
}
ModelUtil.clearIDs(modelHandler.getResource(), instances==0);
getPreferences().getGlobalPreferences().removePropertyChangeListener(this);
getResourceSet().eAdapters().remove(getEditorAdapter());
removeSelectionListener();
if (instances==0)
setActiveEditor(null);
super.dispose();
ModelHandlerLocator.remove(modelUri);
// get rid of temp files and folders, but NOT if the workbench is being shut down.
// when the workbench is restarted, we need to have those temp files around!
if (!workbenchShutdown) {
if (FileService.isTempFile(modelUri)) {
FileService.deleteTempFile(modelUri);
}
}
removeWorkbenchListener();
removeMarkerChangeListener();
getPreferences().dispose();
}
public IPath getModelPath() {
if (getModelFile()!=null)
return getModelFile().getFullPath();
return null;
}
public IProject getProject() {
if (getModelFile()!=null)
return getModelFile().getProject();
return null;
}
public IFile getModelFile() {
if (modelUri!=null) {
String uriString = modelUri.trimFragment().toPlatformString(true);
if (uriString!=null) {
IPath fullPath = new Path(uriString);
return ResourcesPlugin.getWorkspace().getRoot().getFile(fullPath);
}
}
return null;
}
public ModelHandler getModelHandler() {
return modelHandler;
}
public void createPartControl(Composite parent) {
if (getGraphicalViewer()==null) {
super.createPartControl(parent);
}
}
public BPMNDiagram getBpmnDiagram() {
if (bpmnDiagram==null)
bpmnDiagram = getModelHandler().getDefinitions().getDiagrams().get(0);
// if (bpmnDiagram!=null) {
// GraphicalViewer viewer = getGraphicalViewer();
// mapDiagramToViewer.put(bpmnDiagram, viewer);
// }
return bpmnDiagram;
}
public void setBpmnDiagram(final BPMNDiagram bpmnDiagram) {
// create a new Graphiti Diagram if needed
Diagram diagram = DIUtils.getOrCreateDiagram(this, bpmnDiagram);
// Tell the DTP about the new Diagram
getDiagramTypeProvider().resourceReloaded(diagram);
getRefreshBehavior().initRefresh();
setPictogramElementsForSelection(null);
// set Diagram as contents for the graphical viewer and refresh
getGraphicalViewer().setContents(diagram);
refreshContent();
// remember this for later
this.bpmnDiagram = bpmnDiagram;
}
@Override
public void doSave(IProgressMonitor monitor) {
super.doSave(monitor);
Resource resource = getResourceSet().getResource(modelUri, false);
BPMN2ProjectValidator.validateOnSave(resource, monitor);
}
@Override
public boolean isSaveAsAllowed() {
return getModelFile()!=null;
}
@Override
public void doSaveAs() {
IFile oldFile = getModelFile();
SaveAsDialog saveAsDialog = new SaveAsDialog(getSite().getShell());
saveAsDialog.setOriginalFile(oldFile);
saveAsDialog.create();
if (saveAsDialog.open() == SaveAsDialog.CANCEL) {
return;
}
IPath newFilePath = saveAsDialog.getResult();
if (newFilePath == null){
return;
}
IFile newFile = ResourcesPlugin.getWorkspace().getRoot().getFile(newFilePath);
IWorkbenchPage page = getSite().getPage();
try {
// Save the current(old) file
doSave(null);
// if new file exists, close its editor (if open) and delete the existing file
if (newFile.exists()) {
IEditorPart editorPart = ResourceUtil.findEditor(page, newFile);
if (editorPart!=null)
page.closeEditor(editorPart, false);
newFile.delete(true, null);
}
// make a copy
oldFile.copy(newFilePath, true, null);
} catch (CoreException e) {
showErrorDialogWithLogging(e);
return;
}
// open new editor
try {
page.openEditor(new FileEditorInput(newFile), BPMN2Editor.EDITOR_ID);
} catch (PartInitException e1) {
showErrorDialogWithLogging(e1);
return;
}
// and close the old editor
IEditorPart editorPart = ResourceUtil.findEditor(page, oldFile);
if (editorPart!=null)
page.closeEditor(editorPart, false);
try {
newFile.refreshLocal(IResource.DEPTH_ZERO,null);
} catch (CoreException e) {
showErrorDialogWithLogging(e);
return;
}
}
public void closeEditor() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
boolean closed = getSite().getPage().closeEditor(BPMN2Editor.this, false);
if (!closed){
// If close editor fails, try again with explicit editorpart
// of the old file
IFile oldFile = ResourcesPlugin.getWorkspace().getRoot().getFile(getModelPath());
IEditorPart editorPart = ResourceUtil.findEditor(getSite().getPage(), oldFile);
closed = getSite().getPage().closeEditor(editorPart, false);
}
}
});
}
// Show error dialog and log the error
private void showErrorDialogWithLogging(Exception e) {
Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
ErrorUtils.showErrorWithLogging(status);
}
////////////////////////////////////////////////////////////////////////////////
// WorkspaceSynchronizer handlers called from delegate
////////////////////////////////////////////////////////////////////////////////
public boolean handleResourceChanged(Resource resource) {
return true;
}
public boolean handleResourceDeleted(Resource resource) {
closeEditor();
return true;
}
public boolean handleResourceMoved(Resource resource, URI newURI) {
URI oldURI = resource.getURI();
resource.setURI(newURI);
if (modelUri.equals(oldURI)) {
ModelHandlerLocator.remove(modelUri);
modelUri = newURI;
if (preferences!=null) {
preferences.getGlobalPreferences().removePropertyChangeListener(this);
preferences.dispose();
preferences = null;
}
targetRuntime = null;
modelHandler = ModelHandlerLocator.createModelHandler(modelUri, (Bpmn2ResourceImpl)resource);
ModelHandlerLocator.put(diagramUri, modelHandler);
setEditorTitle(modelUri.trimFileExtension().lastSegment());
}
else if (diagramUri.equals(oldURI)) {
ModelHandlerLocator.remove(diagramUri);
diagramUri = newURI;
ModelHandlerLocator.put(diagramUri, modelHandler);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Other handlers
////////////////////////////////////////////////////////////////////////////////
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// Graphiti understands multipage editors
super.selectionChanged(part,selection); // Graphiti's DiagramEditorInternal
// but apparently GEF doesn't
updateActions(getSelectionActions()); // usually done in GEF's GraphicalEditor
}
/* (non-Javadoc)
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().endsWith(Bpmn2Preferences.PREF_SHAPE_STYLE)) {
getEditingDomain().getCommandStack().execute(new RecordingCommand(getEditingDomain()) {
@Override
protected void doExecute() {
IPeService peService = Graphiti.getPeService();
TreeIterator<EObject> iter = getDiagramTypeProvider().getDiagram().eAllContents();
while (iter.hasNext()) {
EObject o = iter.next();
if (o instanceof PictogramElement) {
PictogramElement pe = (PictogramElement)o;
BaseElement be = BusinessObjectUtil.getFirstElementOfType(pe, BaseElement.class);
if (be!=null) {
TreeIterator<EObject> childIter = pe.eAllContents();
while (childIter.hasNext()) {
o = childIter.next();
if (o instanceof GraphicsAlgorithm) {
GraphicsAlgorithm ga = (GraphicsAlgorithm)o;
if (peService.getPropertyValue(ga, Bpmn2Preferences.PREF_SHAPE_STYLE)!=null) {
StyleUtil.applyStyle(ga, be);
}
}
}
}
}
}
}
});
}
}
}