| /******************************************************************************* |
| * Copyright (c) 2011, 2012 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 |
| *******************************************************************************/ |
| package org.eclipse.bpmn2.modeler.ui.editor; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.bpmn2.modeler.core.utils.FixDuplicateIdsDialog; |
| import org.eclipse.bpmn2.modeler.core.utils.ModelUtil; |
| import org.eclipse.bpmn2.modeler.core.utils.Tuple; |
| import org.eclipse.bpmn2.modeler.core.validation.BPMN2ProjectValidator; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.ISchedulingRule; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.common.util.WrappedException; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.graphiti.mm.pictograms.Diagram; |
| import org.eclipse.graphiti.ui.editor.DefaultPersistencyBehavior; |
| import org.eclipse.graphiti.ui.editor.DiagramBehavior; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.operation.IThreadListener; |
| import org.eclipse.swt.widgets.Display; |
| |
| public class BPMN2PersistencyBehavior extends DefaultPersistencyBehavior { |
| |
| BPMN2Editor editor; |
| |
| public BPMN2PersistencyBehavior(DiagramBehavior diagramBehavior) { |
| super(diagramBehavior); |
| editor = (BPMN2Editor)diagramBehavior.getDiagramContainer(); |
| } |
| |
| @Override |
| public Diagram loadDiagram(URI diagramUri) { |
| Diagram diagram = super.loadDiagram(diagramUri); |
| // Resource resource = editor.getResource(); |
| // List<Tuple<EObject,EObject>> dups = ModelUtil.findDuplicateIds(resource); |
| // if (dups.size()>0) { |
| // FixDuplicateIdsDialog dlg = new FixDuplicateIdsDialog(dups); |
| // dlg.open(); |
| // } |
| return diagram; |
| } |
| |
| @Override |
| public void saveDiagram(IProgressMonitor monitor) { |
| Resource resource = editor.getResource(); |
| // this is no longer needed since BaseElementValidator does the job |
| // during Live validation (below) |
| // List<Tuple<EObject,EObject>> dups = ModelUtil.findDuplicateIds(resource); |
| // if (dups.size()>0) { |
| // FixDuplicateIdsDialog dlg = new FixDuplicateIdsDialog(dups); |
| // dlg.open(); |
| // } |
| |
| // Perform a Live validation first: if there are any ERRORs, the model should be |
| // considered to be corrupt (because of such things as invalid IDs, duplicate IDs, etc.) |
| // and saving it in its current state MAY render the file unreadable. |
| IStatus status = BPMN2ProjectValidator.validateLive(ModelUtil.getDefinitions(resource)); |
| if (status.getSeverity() >= Status.ERROR) { |
| String statusList = ""; |
| for (IStatus s : collectStatus(status)) { |
| statusList += " " + s.getMessage() + "\n"; |
| } |
| MessageDialog.openError(editor.getEditorSite().getShell(), "Save Error", |
| "The file can not be saved because the current state of the model is invalid.\nPlease resolve the following issues before saving:\n\n"+ |
| statusList); |
| monitor.setCanceled(true); |
| return; |
| } |
| |
| super.saveDiagram(monitor); |
| } |
| |
| List<IStatus> collectStatus(IStatus status) { |
| if (status.getChildren().length==0) |
| return Collections.singletonList(status); |
| |
| List<IStatus> result = new ArrayList<IStatus>(); |
| for (IStatus child : status.getChildren()) { |
| for (IStatus s : collectStatus(child)) { |
| if (!result.contains(s)) |
| result.add(s); |
| } |
| } |
| return result; |
| } |
| |
| protected IRunnableWithProgress createOperation(final Set<Resource> savedResources, |
| final Map<Resource, Map<?, ?>> saveOptions) { |
| // Do the work within an operation because this is a long running |
| // activity that modifies the workbench. |
| final IRunnableWithProgress operation = new SaveOperation(saveOptions, savedResources); |
| return operation; |
| } |
| |
| /** |
| * The workspace operation used to do the actual save. |
| */ |
| protected final class SaveOperation implements IRunnableWithProgress, IThreadListener { |
| private final Map<Resource, Map<?, ?>> saveOptions; |
| private final Set<Resource> savedResources; |
| |
| private SaveOperation(Map<Resource, Map<?, ?>> saveOptions, Set<Resource> savedResources) { |
| this.saveOptions = saveOptions; |
| this.savedResources = savedResources; |
| } |
| |
| // This is the method that gets invoked when the operation runs. |
| public void run(final IProgressMonitor monitor) { |
| // Save the resources to the file system. |
| try { |
| savedResources.addAll(save(diagramBehavior.getEditingDomain(), saveOptions, monitor)); |
| } catch (final WrappedException e) { |
| String emsg = e.getMessage().replaceAll("\tat .*", "").replaceFirst(".*Exception: ","").trim(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| final String msg = emsg.replace("\r\n\r\n", "").replace("\n\n", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| Display.getDefault().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| MessageDialog.openError(Display.getDefault().getActiveShell(), Messages.BPMN2PersistencyBehavior_Cannot_Save_Title, msg); |
| monitor.setCanceled(true); |
| } |
| }); |
| throw e; |
| } |
| } |
| |
| /* |
| * Transfer the rule from the calling thread to the callee. This should |
| * be invoked before executing the callee and after the callee has |
| * executed, thus transferring the rule back to the calling thread. See |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=391046 |
| */ |
| @Override |
| public void threadChange(Thread thread) { |
| ISchedulingRule rule = Job.getJobManager().currentRule(); |
| if (rule != null) { |
| Job.getJobManager().transferRule(rule, thread); |
| } |
| } |
| } |
| |
| } |