blob: 9bedd02c85ea0eebbb48e37f4493866b162530cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2012 Intel Corporation.
* 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:
* Vitaly Tishkov, Intel - Initial API and Implementation
*
*******************************************************************************/
package org.eclipse.bpel.ui;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.bpel.common.extension.model.ExtensionMap;
import org.eclipse.bpel.common.ui.editmodel.IEditModelListener;
import org.eclipse.bpel.common.ui.editmodel.ResourceInfo;
import org.eclipse.bpel.model.Activity;
import org.eclipse.bpel.model.CorrelationSet;
import org.eclipse.bpel.model.BPELExtensibleElement;
import org.eclipse.bpel.model.Import;
import org.eclipse.bpel.model.MessageExchange;
import org.eclipse.bpel.model.PartnerLink;
import org.eclipse.bpel.model.Process;
import org.eclipse.bpel.model.Variable;
import org.eclipse.bpel.model.resource.BPELResourceSetImpl;
import org.eclipse.bpel.model.util.BPELUtils;
import org.eclipse.bpel.ui.adapters.AdapterNotification;
import org.eclipse.bpel.ui.adapters.IMarkerHolder;
import org.eclipse.bpel.ui.editparts.ProcessTrayEditPart;
import org.eclipse.bpel.ui.editparts.util.OutlineTreePartFactory;
import org.eclipse.bpel.ui.properties.BPELPropertySection;
import org.eclipse.bpel.ui.uiextensionmodel.StartNode;
import org.eclipse.bpel.ui.util.BPELEditModelClient;
import org.eclipse.bpel.ui.util.BPELEditorUtil;
import org.eclipse.bpel.ui.util.BPELReader;
import org.eclipse.bpel.ui.util.BPELUtil;
import org.eclipse.bpel.ui.util.ModelHelper;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
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.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.parts.ScrollableThumbnail;
import org.eclipse.draw2d.parts.Thumbnail;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.parts.ContentOutlinePage;
import org.eclipse.gef.ui.parts.TreeViewer;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor;
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyViewer;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ISection;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabContents;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class BPELMultipageEditorPart extends MultiPageEditorPart
implements IEditModelListener,
IGotoMarker/*, CommandStackListener*/ {
class OutlinePage extends ContentOutlinePage {
private PageBook pageBook;
private Control outline;
private Canvas overview;
private IAction showOutlineAction, showOverviewAction;
static final int ID_OUTLINE = 0;
static final int ID_OVERVIEW = 1;
private Thumbnail thumbnail;
public OutlinePage(EditPartViewer viewer) {
super(viewer);
}
// increase visibility.
@Override
public EditPartViewer getViewer() {
return super.getViewer();
}
private void configureOutlineViewer() {
getViewer().setEditDomain(getEditDomain());
getViewer().setEditPartFactory(new OutlineTreePartFactory());
BPELMultipageEditorPart.this.fDesignViewer.registerViewer(getViewer());
//FIXME should we add the same for src tab?
ContextMenuProvider provider = new ProcessContextMenuProvider(getDesignEditor(), BPELMultipageEditorPart.this.fDesignViewer.getActionRegistry());
getViewer().setContextMenu(provider);
getSite().registerContextMenu("org.eclipse.bpel.outline.contextmenu", //$NON-NLS-1$
provider,
getSite().getSelectionProvider());
getViewer().setKeyHandler(BPELMultipageEditorPart.this.fDesignViewer.getKeyHandler());
// TODO: Drag and drop support goes here
// getViewer().addDropTargetListener(new BPELTemplateTransferDropTargetListener(getViewer()));
IToolBarManager tbm = getSite().getActionBars().getToolBarManager();
this.showOutlineAction = new Action() {
@Override
public void run() {
showPage(ID_OUTLINE);
}
@Override
public String getToolTipText() {
return Messages.OutlinePage_showOutlineView;
}
};
this.showOutlineAction.setImageDescriptor(BPELUIPlugin.INSTANCE.getImageDescriptor(IBPELUIConstants.ICON_OUTLINE_16));
tbm.add(this.showOutlineAction);
this.showOverviewAction = new Action() {
@Override
public void run() {
showPage(ID_OVERVIEW);
}
@Override
public String getToolTipText() {
return Messages.OutlinePage_showOverviewView;
}
};
this.showOverviewAction.setImageDescriptor(BPELUIPlugin.INSTANCE.getImageDescriptor(IBPELUIConstants.ICON_OVERVIEW_16));
tbm.add(this.showOverviewAction);
showPage(ID_OUTLINE);
}
@Override
public Control getControl() {
return this.pageBook;
}
@Override
public void createControl(Composite parent) {
this.pageBook = new PageBook(parent, SWT.NONE);
this.outline = getViewer().createControl(this.pageBook);
this.overview = new Canvas(this.pageBook, SWT.NONE);
this.pageBook.showPage(this.outline);
configureOutlineViewer();
// TODO: Add to the adapting selection provider
//getSelectionSynchronizer().addViewer(getViewer());
getViewer().setContents(getProcess());
}
private void initializeOverview() {
LightweightSystem lws = new LightweightSystem(this.overview);
RootEditPart rep = BPELMultipageEditorPart.this.fDesignViewer.getGraphicalViewer().getRootEditPart();
if (rep instanceof GraphicalBPELRootEditPart) {
GraphicalBPELRootEditPart root = (GraphicalBPELRootEditPart)rep;
this.thumbnail = new ScrollableThumbnail((Viewport)root.getFigure());
this.thumbnail.setSource(root.getLayer(LayerConstants.PRINTABLE_LAYERS));
lws.setContents(this.thumbnail);
}
}
private void showPage(int id) {
if (id == ID_OUTLINE) {
this.showOutlineAction.setChecked(true);
this.showOverviewAction.setChecked(false);
this.pageBook.showPage(this.outline);
if (this.thumbnail != null)
this.thumbnail.setVisible(false);
} else if (id == ID_OVERVIEW) {
initializeOverview();
this.showOutlineAction.setChecked(false);
this.showOverviewAction.setChecked(true);
this.pageBook.showPage(this.overview);
this.thumbnail.setVisible(true);
}
}
@Override
public void dispose() {
super.dispose();
}
@Override
public void init(IPageSite pageSite) {
super.init(pageSite);
//should ActionRegistry be here too?
ActionRegistry registry = BPELMultipageEditorPart.this.fDesignViewer.getActionRegistry();
IActionBars bars = pageSite.getActionBars();
String id = ActionFactory.UNDO.getId();
bars.setGlobalActionHandler(id, registry.getAction(id));
id = ActionFactory.REDO.getId();
bars.setGlobalActionHandler(id, registry.getAction(id));
id = ActionFactory.DELETE.getId();
bars.setGlobalActionHandler(id, registry.getAction(id));
id = ActionFactory.REVERT.getId();
bars.setGlobalActionHandler(id, registry.getAction(id));
bars.updateActionBars();
}
}
protected class TextEditorSelectionListener implements ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
if (getActivePage() != DESIGN_PAGE_INDEX) {
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
List<Object> selections = new ArrayList<Object>();
for (Iterator<Object> i = ((IStructuredSelection) selection).iterator(); i.hasNext();) {
Object domNode = i.next();
if (domNode instanceof Element) {
Object facade = BPELEditorUtil.getInstance().findModelObjectForElement(BPELMultipageEditorPart.this.process, (Element)domNode);
if (facade != null) {
selections.add(facade);
}
}
}
if (!selections.isEmpty()) {
StructuredSelection bpelSelection = new StructuredSelection(selections);
BPELMultipageEditorPart.this.fDesignViewer.getAdaptingSelectionProvider().setSelection(bpelSelection);
}
}
}
}
}
protected class DesignViewerSelectionListener implements ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
//force selection update if only source page is not active
if (getActivePage() != SOURCE_PAGE_INDEX) {
try {
ISelection sel = BPELMultipageEditorPart.this.fDesignViewer.getSelection();
Object selectedNode = ((IStructuredSelection)sel).getFirstElement();
Element selectedNodeElement = null;
if (selectedNode instanceof StartNode) {
selectedNodeElement = ((StartNode)selectedNode).getProcess().getElement();
} else if (selectedNode instanceof BPELExtensibleElement) {
selectedNodeElement = ((BPELExtensibleElement)selectedNode).getElement();
}
if (selectedNodeElement != null) {
if (selectedNodeElement instanceof IDOMNode && ((IDOMNode)selectedNodeElement).getModel().isModelStateChanging()) {
return;
}
StructuredSelection nodeSelection = new StructuredSelection(selectedNodeElement);
getTextEditor().getSelectionProvider().setSelection(nodeSelection);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private Process process;
private DefaultEditDomain editDomain;
protected ModelListenerAdapter modelListenerAdapter;
private Resource extensionsResource;
private ExtensionMap extensionMap;
protected StructuredTextEditor fTextEditor = null;
protected BPELEditor fDesignViewer = null;
protected int currentPage = -1;
protected TextEditorSelectionListener textEditorSelectionListener;
protected DesignViewerSelectionListener designViewerSelectionListener;
// reacts to changes on the BPEL file (e.g. move, rename)
private IFileChangeListener fileChangeListener;
// refactoring listeners
protected IResourceChangeListener postBuildRefactoringListener;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
protected IResourceChangeListener preBuildRefactoringListener;
BPELModelReconcileAdapter bpelModelReconcileAdapter;
private OutlinePage outlinePage;
protected BPELTabbedPropertySheetPage currentPropertySheetPage;
protected ActionRegistry actionRegistry;
private static int DESIGN_PAGE_INDEX = 0;
private static int SOURCE_PAGE_INDEX = 1;
private final Map<Long, EObject>fMarkers2EObject = new HashMap<Long, EObject>();
private final Notification fMarkersStale = new NotificationImpl(
AdapterNotification.NOTIFICATION_MARKERS_STALE, null, null);
public BPELMultipageEditorPart() {
super();
setEditDomain(new BPELEditDomain(this));
}
/**
* Connects the design viewer with the viewer selection manager. Should be
* done after createSourcePage() is done because we need to get the
* ViewerSelectionManager from the TextEditor. setModel is also done here
* because getModel() needs to reference the TextEditor.
*/
protected void connectDesignPage() {
/*
* Connect selection from the Design page to the selection provider of
* the Source page so that selection in the Design page will drive
* selection in the Source page.
*/
this.designViewerSelectionListener = new DesignViewerSelectionListener();
this.fDesignViewer.getAdaptingSelectionProvider().addSelectionChangedListener(this.designViewerSelectionListener);
/*
* Connect selection from the Source page to the selection provider of
* the Design page so that selection in the Source page will drive
* selection in the Design page.
*/
this.textEditorSelectionListener = new TextEditorSelectionListener();
ISelectionProvider provider = getTextEditor().getSelectionProvider();
if (provider instanceof IPostSelectionProvider) {
((IPostSelectionProvider) provider).addPostSelectionChangedListener(this.textEditorSelectionListener);
} else {
provider.addSelectionChangedListener(this.textEditorSelectionListener);
}
}
/**
* Creates the design page of the multi-page editor.
*/
protected void createDesignPage() {
this.fDesignViewer = new BPELEditor(getEditDomain(), this);
// Bug #209341 - starting patch
if( getFileInput() == null ) {
MessageDialog.openError(
getSite().getShell(),
Messages.Editor_load_error_title, // Bugzilla 330513
Messages.Editor_load_error
);
return;
}
// End of patch
try
{
loadModel();
addPage(0, this.fDesignViewer, getEditorInput());
//FIXME I18N
setPageText(0, "Design");
} catch (PartInitException e) {
ErrorDialog.openError(
getSite().getShell(),
Messages.Editor_design_page_error, // Bugzilla 330513
null,
e.getStatus()); //$NON-NLS-1$
} catch (CoreException e) {
// TODO: what to do here?
}
}
// https://jira.jboss.org/browse/JBIDE-6917
@Override
protected IEditorSite createSite(IEditorPart page) {
IEditorSite site = null;
if (page == fTextEditor) {
site = new org.eclipse.ui.part.MultiPageEditorSite(this, page) {
public String getId() {
// Sets this ID so nested editor is configured for BPEL source
return BPELResourceSetImpl.BPEL_CONTENT_TYPE;
}
};
}
else {
site = super.createSite(page);
}
return site;
}
/**
* Creates the source page of the multi-page editor.
*/
protected void createSourcePage() throws PartInitException {
this.fTextEditor = new StructuredTextEditor();
try
{
addPage(0, this.fTextEditor, getEditorInput());
//FIXME I18N
setPageText(0, "Source");
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(), "Error creating Source page", null, e.getStatus()); //$NON-NLS-1$
}
}
/**
* Creates the pages of this multi-page editor.
*/
@Override
protected void createPages() {
try {
// source page must be created before design page
createSourcePage();
createDesignPage();
firePropertyChange(PROP_TITLE);
connectDesignPage();
initializeFileChangeListener();
initializeRefactoringListener();
} catch (PartInitException e) {
//Logger.logException(e);
throw new RuntimeException(e);
}
if (BPELUIPlugin.INSTANCE.getDefaultPage().equals(IBPELUIConstants.SOURCE_PAGE)) {
setActivePage(SOURCE_PAGE_INDEX);
} else {
setActivePage(DESIGN_PAGE_INDEX);
}
//updateTitle();
}
@Override
public void dispose() {
/*if (outlinePage != null && outlinePage.getViewer() != null) {
outlinePage.getViewer().setContents(null);
}*/
if (this.currentPage == SOURCE_PAGE_INDEX) {
BPELUIPlugin.INSTANCE.setDefaultPage(IBPELUIConstants.SOURCE_PAGE);
} else {
BPELUIPlugin.INSTANCE.setDefaultPage(IBPELUIConstants.DESIGN_PAGE);
}
this.outlinePage = null;
this.process = null;
if (this.fileChangeListener != null) {
BPELUIPlugin.INSTANCE.getResourceChangeListener().removeListener(this.fileChangeListener);
}
if (this.postBuildRefactoringListener != null) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.removeResourceChangeListener(this.postBuildRefactoringListener);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
// https://jira.jboss.org/browse/JBIDE-6365
if (this.preBuildRefactoringListener != null) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.removeResourceChangeListener(this.preBuildRefactoringListener);
}
IStructuredModel model = this.fTextEditor.getModel();
if (model != null) {
model.releaseFromEdit();
this.fDesignViewer.dispose();
this.fTextEditor.dispose();
}
super.dispose();
}
public void doRevertToSaved(IProgressMonitor monitor) {
// Do the work within an operation because this is a long running activity that modifies the workbench.
// WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
// protected void execute(IProgressMonitor monitor) throws CoreException {
// try {
// getCommandFramework().abortCurrentChange();
// getCommandStack().flush();
//
// // de-select anything selected on the canvas! Otherwise removing things
// // will trigger a bunch of behaviour when the selected object(s) are
// // removed..
// adaptingSelectionProvider.setSelection(StructuredSelection.EMPTY);
//
// process = null;
// extensionMap = null;
// extensionsResource = null;
// lastSelectedEditPart = null;
// // unload all resources (otherwise they stay around taking up space..?)
// for (Iterator it = getResourceSet().getResources().iterator(); it.hasNext(); ) {
// Resource res = (Resource)it.next();
// res.unload();
// }
// loadModel();
// getGraphicalViewer().setContents(process);
// getTrayViewer().setContents(process);
// if (outlinePage != null && outlinePage.getViewer() != null) {
// // hack!
// if (Platform.getWS().equals(Platform.WS_GTK)) {
// Tree tree = (Tree) outlinePage.getViewer().getControl();
// if (tree != null) {
// tree.setRedraw(false);
// TreeItem[] items = tree.getItems();
// for (int i = 0; i < items.length; i++) {
// items[i].dispose();
// }
// tree.setRedraw(true);
// }
// }
// outlinePage.getViewer().setContents(process);
// }
// selectModelObject(getProcess());
// }
// catch (Exception e) {
// BPELUIPlugin.log(e);
// }
// }
// };
//
// try {
// // This runs the options, and shows progress.
// // (It appears to be a bad thing to fork this onto another thread.)
// new ProgressMonitorDialog(getSite().getShell()).run(false, false, operation);
//
// // Refresh the necessary state.
// firePropertyChange(IEditorPart.PROP_DIRTY);
// } catch (Exception e) {
// BPELUIPlugin.log(e);
// }
}
/**
* @see org.eclipse.ui.IEditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void doSave(IProgressMonitor progressMonitor) {
// We use fTextEditor to save, because fDesignViewer.doSave() removes comments on save
// Save bpel only
this.fDesignViewer.getCommandFramework().applyCurrentChange();
this.fTextEditor.doSave(progressMonitor);
// Reset sync stamp and modified flag after save
this.fDesignViewer.getEditModelClient().getPrimaryResourceInfo().resetSynchronizeStamp();
this.fDesignViewer.getEditModelClient().getPrimaryResourceInfo().getResource().setModified(false);
// Save extensions
this.fDesignViewer.doSave(progressMonitor);
getCommandStack().markSaveLocation();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.ISaveablePart#doSaveAs()
*/
@Override
public void doSaveAs() {
//saveAs is not allowed; do nothing
}
protected BPELTabbedPropertySheetPage createBPELTabbedPropertySheetPage() {
//FIXME should the BPELTabbedPropertySheetPage has BPELMultiPageEditorPart as the 2nd argument?
return new BPELTabbedPropertySheetPage(new ITabbedPropertySheetPageContributor() {
public String getContributorId() {
// same as the palette one
//return fDesignViewer.getPaletteAdditionsContributorId();
return IBPELUIConstants.BPEL_EDITOR_ID;
}
}, this.fDesignViewer);
}
protected ActionRegistry getActionRegistry() {
if (this.actionRegistry == null)
this.actionRegistry = new ActionRegistry();
return this.actionRegistry;
}
@Override
public Object getAdapter(Class type) {
if (type == Process.class) {
return this.process;
}
if (type == BPELEditModelClient.class) {
return this.process;
}
//FIXME should we kill it?
if (type == ModelListenerAdapter.class) {
return this.modelListenerAdapter;
}
//FIXME should we kill it?
if (type == Resource.class) {
return this.extensionsResource;
}
//FIXME should we kill it?
if (type == ExtensionMap.class) {
return this.extensionMap;
}
//FIXME should we kill it?
if (type == CommandStack.class) {
return getCommandStack();
}
if (type == IContentOutlinePage.class) {
if (this.outlinePage == null) {
this.outlinePage = new OutlinePage(new TreeViewer());
}
return this.outlinePage;
}
if (type == IPropertySheetPage.class) {
// We can't cache this object because the properties framework needs a new instance
// every time it calls this method.
this.currentPropertySheetPage = createBPELTabbedPropertySheetPage();
return this.currentPropertySheetPage;
}
if (type == ActionRegistry.class) {
return getActionRegistry();
}
return super.getAdapter(type);
}
public CommandStack getCommandStack() {
return getEditDomain().getCommandStack();
}
protected int getDefaultPageTypeIndex() {
int pageIndex = DESIGN_PAGE_INDEX;
if (BPELUIPlugin.INSTANCE.getDefaultPage().equals(IBPELUIConstants.SOURCE_PAGE)) {
pageIndex = SOURCE_PAGE_INDEX;
}
return pageIndex;
}
/**
* Returns the design viewer
* @return the design viewer
*/
protected BPELEditor getDesignEditor() {
return this.fDesignViewer;
}
/**
* Returns the edit domain.
* @return the edit domain
*/
protected DefaultEditDomain getEditDomain() {
return this.editDomain;
}
// Bug #209341 - patch
// By Vincent Zurczak - EBM WebSourcing
private IFile openFile;
private static String filePrefix = new SimpleDateFormat( "yyyyMMF_" ).format( new GregorianCalendar().getTime());
/**
*
* @return
*/
protected IFile getFileInput() {
if( this.openFile == null ) {
try {
// Case where the file is in the workspace
if( getEditorInput() instanceof IFileEditorInput )
this.openFile = ((IFileEditorInput) getEditorInput()).getFile();
// Outside the workspace
// Since everything relies on IFiles, we create a temporary file in the workspace
// linking to the file outside the workspace
else if( getEditorInput() instanceof FileStoreEditorInput ) {
File f = new File(((FileStoreEditorInput) getEditorInput()).getURI());
IPath path = new Path( f.getAbsolutePath());
// Create a temporary project
IProgressMonitor monitor = new NullProgressMonitor();
IProject tempProject = ResourcesPlugin.getWorkspace().getRoot().getProject( ".temp" );
if( ! tempProject.exists())
tempProject.create( monitor );
if( ! tempProject.isOpen())
tempProject.open( monitor );
// Remove old temporary files
// The file prefix is designed so that natural comparison order is enough
for( IResource res : tempProject.members()) {
if( res.getName().substring( 0, 7 ).compareTo( filePrefix ) < 0 ) {
try {
res.delete( false, monitor );
} catch( Exception e ) {
e.printStackTrace();
}
}
}
// Create a temporary file
this.openFile = tempProject.getFile( filePrefix + path.lastSegment());
this.openFile.createLink( path, IResource.NONE, monitor );
}
} catch( CoreException e ) {
e.printStackTrace();
}
}
return this.openFile;
}
// End of patch
public Process getProcess() {
return this.process;
}
/**
* Returns the design viewer
* @return the design viewer
*/
protected StructuredTextEditor getSourceViewer() {
return this.fTextEditor;
}
StructuredTextEditor getTextEditor() {
return this.fTextEditor;
}
public void gotoMarker(IMarker marker) {
// One such mechanism is to use the href of the model object
// generated by the validator or whatever ...
String href = null;
try {
href = (String) marker.getAttribute( "address.model" );
} catch (CoreException ex) {
BPELUIPlugin.log(ex);
}
// lookup by object href in the model.
EObject modelObject = null;
if (href != null) {
try {
modelObject = this.fDesignViewer.getResource().getEObject( href );
} catch (Throwable t) {
BPELUIPlugin.log(t);
}
}
gotoText(marker);
if (modelObject == null) {
return;
}
gotoMarker ( marker, modelObject );
}
private void gotoText(IMarker marker) {
Integer charStart = null;
Integer charEnd = null;
try {
charStart = (Integer) marker.getAttribute( "charStart" );
charEnd = (Integer) marker.getAttribute( "charEnd" );
} catch (CoreException ex) {
BPELUIPlugin.log(ex);
}
charStart = charStart == null ? 0 : charStart;
charEnd = charEnd == null ? charStart : charEnd;
try {
this.fTextEditor.setHighlightRange(charStart, charEnd - charStart, true);
} catch (Throwable t) {
BPELUIPlugin.log(t);
}
}
void gotoMarker ( IMarker marker, EObject modelObject ) {
// TODO: is this bogus now that we have AdaptingSelectionProvider?
// The closest parent which has an edit part in the graph view.
//
// The following do not have viewers in the graph view:
// 1) Variables, PartnerLinks, Correlation Sets, Message Exchanges
// If it's any of those, then we have to reveal the closest container
// and then select the model object and show the properties.
GraphicalViewer graphViewer = this.fDesignViewer.getGraphicalViewer();
EObject refObj = null;
EditPart editPart = null;
if ( modelObject instanceof Variable ||
modelObject instanceof PartnerLink ||
modelObject instanceof CorrelationSet ||
modelObject instanceof MessageExchange) {
refObj = ModelHelper.getContainingScope(modelObject);
editPart = (EditPart)graphViewer.getEditPartRegistry().get(refObj);
if (editPart != null) {
graphViewer.reveal(editPart);
}
this.fDesignViewer.selectModelObject(modelObject);
} else if (modelObject instanceof Activity) {
// activity objects are on the graphical viewer
refObj = modelObject;
editPart = (EditPart)graphViewer.getEditPartRegistry().get(refObj);
if (editPart != null) {
graphViewer.reveal(editPart);
}
this.fDesignViewer.selectModelObject(modelObject);
} else {
refObj = modelObject;
while (refObj != null && !(refObj instanceof Activity) ) {
refObj = refObj.eContainer();
}
// select process by default.
if (refObj == null) {
refObj = BPELUtils.getProcess( modelObject ) ;
}
modelObject = refObj;
editPart = (EditPart)graphViewer.getEditPartRegistry().get(modelObject);
if (editPart != null) {
graphViewer.reveal(editPart);
}
this.fDesignViewer.selectModelObject(modelObject);
}
// If possible, try to display the marker in a property section.
BPELTabbedPropertySheetPage propertySheetPage = this.currentPropertySheetPage;
if (propertySheetPage == null) {
return;
// if currentPropertySheetPage is null it means that the properties
// page hasn't shown yet. Since we only want to show it if we have
// markers for it we create a new BPELTabbedPropertySheetPage. This
// new one should only be used to select which tab and section to show.
// TODO: this doesn't work
//propertySheetPage = createBPELTabbedPropertySheetPage();
}
TabbedPropertyViewer viewer = propertySheetPage.getTabbedPropertyViewer();
int j = 0;
while (true) { // while we don't get an exception...
TabDescriptor descriptor = null;
try {
descriptor = (TabDescriptor)viewer.getElementAt(j++);
} catch (IndexOutOfBoundsException iobe) {
break;
}
if (descriptor == null) {
break; // no more descriptors
}
TabContents tab = descriptor.createTab();
ISection[] sections = tab.getSections();
for (int i = 0; i < sections.length; i++) {
if (BPELPropertySection.class.isInstance( sections[i]) == false) {
continue;
}
BPELPropertySection section = (BPELPropertySection)sections[i];
// HACK: we have to fake the initialization of this section in order to
// make isValidMarker work. This section should not be used as a normal section.
section.createControls(new Composite(getSite().getShell(), 0), propertySheetPage);
section.setInput(this, new StructuredSelection(modelObject));
if (section.isValidMarker (marker) ) {
// the first section that handles this kind of marker wins
showPropertiesView();
// get real viewer, Tab and ISection objects since we are probably using fake ones
viewer = this.currentPropertySheetPage.getTabbedPropertyViewer();
viewer.setSelection(new StructuredSelection(descriptor));
tab = this.currentPropertySheetPage.getCurrentTab();
section = (BPELPropertySection)tab.getSectionAtIndex(i);
section.gotoMarker(marker);
return; // ignore other sections and tabs
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
* org.eclipse.ui.IEditorInput)
*/
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
try {
super.init(site, input);
// getCommandStack().addCommandStackListener(this);
} catch (Exception e) {
e.printStackTrace();
}
setPartName(input.getName());
}
protected void initializeFileChangeListener() {
this.fileChangeListener = new IFileChangeListener() {
public void deleted(IFile file) {
IFile current = ((IFileEditorInput)getEditorInput()).getFile();
if (current.equals(file)) {
// Close the editor.
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
getSite().getPage().closeEditor(BPELMultipageEditorPart.this, false);
}
});
}
}
public void moved(IFile source, final IFile destination) {
// IFile current = ((IFileEditorInput) getEditorInput()).getFile();
// if (!current.equals(source)) {
// return;
// }
// // update editors input
// final IFileEditorInput input = new FileEditorInput(destination);
// Display display = getDetailsEditor().getSite().getShell().getDisplay();
// display.syncExec(new Runnable() {
// public void run() {
// getBPELDetailsEditor().setInput(input);
// setInput(input);
// }
// });
// // update resources
// IPath path = destination.getFullPath();
// URI uri = URI.createPlatformResourceURI(path.toString());
// processResource.setURI(uri);
// // JM: Comment out. We don't want to re-name the process just because
// // the file name has changed
//// display.syncExec(new Runnable() {
//// public void run() {
//// BPELUtil.updateNameAndNamespace(destination, process);
//// }
//// });
// path = path.removeFileExtension().addFileExtension(IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS);
// URI extensionsUri = URI.createPlatformResourceURI(path.toString());
// extensionsResource = resourceSet.createResource(extensionsUri);
// extensionsResource.setURI(extensionsUri);
// try {
// // JM: Comment out for now. We should re-test this
//// processResource.save(Collections.EMPTY_MAP);
//// destination.refreshLocal(IResource.DEPTH_ZERO, null);
// } catch (Exception e) {
// BPELUIPlugin.log(e);
// }
}
};
BPELUIPlugin.INSTANCE.getResourceChangeListener().addListener(this.fileChangeListener);
}
/**
* Installs the refactoring listener
*/
protected void initializeRefactoringListener() {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
this.postBuildRefactoringListener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
IFile newFile = ((FileEditorInput)getEditorInput()).getFile();
final IResourceDelta bpelFileDelta = event.getDelta().findMember(newFile.getFullPath());
// we only care about the change if it is a move or a rename
if (bpelFileDelta != null && (bpelFileDelta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
getSite().getShell().getDisplay().syncExec(new Runnable() {
public void run() {
doRevertToSaved(null);
}
});
}
}
};
workspace.addResourceChangeListener(this.postBuildRefactoringListener, IResourceChangeEvent.POST_BUILD);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
// https://jira.jboss.org/browse/JBIDE-6365
this.preBuildRefactoringListener = new RefactoringListener();
workspace.addResourceChangeListener(this.preBuildRefactoringListener, IResourceChangeEvent.PRE_BUILD);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
*/
@Override
public boolean isSaveAsAllowed() {
return false;
}
protected void loadModel() throws CoreException {
Document structuredDocument = null;
try {
IDocument doc = this.fTextEditor.getDocumentProvider().getDocument(getEditorInput());
if (doc instanceof IStructuredDocument) {
IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(doc);
if (model == null) {
model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) doc);
}
if (model != null) {
structuredDocument = ((IDOMModel) model).getDocument();
}
}
} catch (Exception e) {
e.printStackTrace();
}
HashMap<String, Document> loadOptions = null;
if (structuredDocument != null) {
loadOptions = new HashMap<String, Document> (1);
loadOptions.put("DOMDocument", structuredDocument);
}
//FIXME WSDLEditor has gef command stack; in order to have gef command stack we need to add design page first
// Bug # 209341 - starting patch
// By Vincent Zurczak
IFile file = null;
BPELEditModelClient editModelClient = new BPELEditModelClient(this);
// Bugzilla 330513
// first load the primary resource (the *.bpel file)
boolean keepGoing = false;
Shell shell = getEditorSite().getShell();
try {
file = getFileInput();
editModelClient.loadPrimaryResource(file,loadOptions);
}
catch (RuntimeException ex) {
String msg = NLS.bind(Messages.EditModelClient_bpel_load_error,
new String[]{file.toString()}
);
keepGoing = MessageDialog.openQuestion(
shell,
Messages.EditModelClient_load_error_title,
msg);
if (!keepGoing)
throw ex;
}
// next load the extensions resource (the *.bpelex file)
try {
editModelClient.loadExtensionsResource();
}
catch (RuntimeException ex) {
file = editModelClient.getExtensionsFile();
String msg = NLS.bind(Messages.EditModelClient_bpelex_load_error,
new String[]{file.toString()}
);
keepGoing = MessageDialog.openQuestion(
shell,
Messages.EditModelClient_load_error_title,
msg);
if (!keepGoing)
throw ex;
try {
file.delete(true, null);
editModelClient.loadExtensionsResource();
} catch (CoreException ce) {
MessageDialog.openError(shell, Messages.EditModelClient_delete_error_title, Messages.EditModelClient_delete_error_message);
throw ce;
}
}
// finally load the artifacts resource (the *.wsdl file)
try {
editModelClient.loadArtifactsResource();
}
catch (RuntimeException ex) {
file = editModelClient.getArtifactsFile();
String msg = NLS.bind(Messages.EditModelClient_wsdl_load_error,
new String[]{file.toString()}
);
keepGoing = MessageDialog.openQuestion(
shell,
Messages.EditModelClient_load_error_title,
msg);
if (!keepGoing)
throw ex;
try {
file.delete(true, null);
editModelClient.loadArtifactsResource();
} catch (CoreException ce) {
MessageDialog.openError(shell, Messages.EditModelClient_delete_error_title, Messages.EditModelClient_delete_error_message);
throw ce;
}
}
this.fDesignViewer.setEditModelClient(editModelClient);
getEditDomain().setCommandStack(editModelClient.getCommandStack());
Resource bpelResource = editModelClient.getPrimaryResourceInfo().getResource();
BPELReader reader = new BPELReader();
reader.read(bpelResource, getFileInput(), this.fDesignViewer.getResourceSet());
// End of patch
this.process = reader.getProcess();
this.bpelModelReconcileAdapter = new BPELModelReconcileAdapter (structuredDocument, this.process, bpelResource, this.fDesignViewer);
if (getEditDomain() != null) {
((BPELEditDomain)getEditDomain()).setProcess(getProcess());
}
this.extensionsResource = reader.getExtensionsResource();
this.extensionMap = reader.getExtensionMap();
this.modelListenerAdapter = new ModelListenerAdapter();
this.modelListenerAdapter.setExtensionMap(this.extensionMap);
// Bugzilla 330519
updateMarkersHard();
}
public void modelDeleted(ResourceInfo resourceInfo) {
if (!isDirty()) {
getSite().getPage().closeEditor(this, false);
}
}
public void modelDirtyStateChanged(ResourceInfo resourceInfo) {
firePropertyChange(PROP_DIRTY);
}
public void modelLocationChanged(ResourceInfo resourceInfo, IFile movedToFile) {
// TODO!
//updateInputFile(movedToFile.getFullPath());
}
public void modelReloaded(ResourceInfo resourceInfo) {
Resource bpelResource = this.fDesignViewer.getEditModelClient().getPrimaryResourceInfo().getResource();
IFile file = getFileInput();
BPELReader reader = new BPELReader();
reader.read(bpelResource, file, this.fDesignViewer.getResourceSet());
this.process = reader.getProcess();
if (getEditDomain() != null) {
((BPELEditDomain)getEditDomain()).setProcess(getProcess());
}
this.extensionMap = reader.getExtensionMap();
this.modelListenerAdapter.setExtensionMap(this.fDesignViewer.getExtensionMap());
this.fDesignViewer.getGraphicalViewer().setContents(getProcess());
// The ProcessTrayEditPart tries to remove its selection listener on deactivate.
// In this case, it will fail because the edit part can't find the editor because
// the process no longer belongs to a resource. Help it out and remove the
// listener manually.
ProcessTrayEditPart processTrayEditPart = (ProcessTrayEditPart)this.fDesignViewer.getTrayViewer().getContents();
this.fDesignViewer.getGraphicalViewer().removeSelectionChangedListener(processTrayEditPart.getSelectionChangedListener());
this.fDesignViewer.getTrayViewer().setContents(getProcess());
//Bugzilla 294501 - When markers are added on the BPEL file, the meta-model
//objects are notified about the marker change. But the display of the markers
//on the diagram fails because of several invalid thread access exceptions.
//Thus, encapsulating the marker update into a separate thread
//Note: supposedly only happens on Galileo (== Eclipse 3.5)
Display.getDefault().asyncExec( new Runnable() {
public void run() {
updateMarkersHard();
}
});
}
/**
* Erase and reload markers for the given model object.
* This will create the necessary adapters so that marker
* notifications are delegated to the correct activity displayed
* in the graphical viewer.
*
* @param modelObject
* @see Bugzilla 330519
*/
public void updateMarkers(EObject modelObject) {
List<Long> removed = new ArrayList<Long>();
for (Entry<Long, EObject> e : fMarkers2EObject.entrySet()){
if (e.getValue() == modelObject)
removed.add(e.getKey());
}
for (Long key : removed) {
fMarkers2EObject.remove(key);
}
modelObject.eNotify(fMarkersStale);
for (TreeIterator<EObject> iter=EcoreUtil.getAllContents((EObject)modelObject, true); iter.hasNext(); ){
EObject obj = iter.next();
BPELUtil.adapt(obj, IMarkerHolder.class);
}
IMarker[] markers = null;
IFile file = getFileInput();
Resource resource = getProcess().eResource();
try {
markers = file.findMarkers(null, true, IResource.DEPTH_ZERO);
} catch (Exception ex) {
BPELUIPlugin.log(ex);
return;
}
for (IMarker m : markers) {
String href = null;
EObject target = null;
try {
href = (String) m.getAttribute( "address.model" ); //$NON-NLS-1$
if (href == null) {
continue;
}
target = resource.getEObject(href);
} catch (CoreException ex) {
continue;
}
if (target == modelObject) {
this.fMarkers2EObject.put(m.getId(), target);
EObject obj = target;
while (obj!=null) {
BPELUtil.adapt(obj, IMarkerHolder.class);
obj = obj.eContainer();
}
target.eNotify( new NotificationImpl (AdapterNotification.NOTIFICATION_MARKER_ADDED , null, m ));
}
}
}
protected void updateMarkersHard () {
for(EObject obj : this.fMarkers2EObject.values()) {
obj.eNotify(this.fMarkersStale);
}
this.fMarkers2EObject.clear();
IMarker[] markers = null;
IFile file = getFileInput();
Resource resource = getProcess().eResource();
try {
markers = file.findMarkers(null, true, IResource.DEPTH_ZERO);
} catch (CoreException ex) {
BPELUIPlugin.log(ex);
return;
}
for (IMarker m : markers) {
String href = null;
EObject target = null;
try {
href = (String) m.getAttribute( "address.model" ); //$NON-NLS-1$
if (href == null) {
continue;
}
target = resource.getEObject(href);
} catch (Exception ex) {
continue;
}
if (target == null) {
continue;
}
this.fMarkers2EObject.put(m.getId(), target);
EObject obj = target;
while (obj!=null) {
BPELUtil.adapt(obj, IMarkerHolder.class);
obj = obj.eContainer();
}
target.eNotify( new NotificationImpl (AdapterNotification.NOTIFICATION_MARKER_ADDED , null, m ));
}
}
@Override
protected void pageChange(int newPageIndex) {
this.currentPage = newPageIndex;
super.pageChange(newPageIndex);
}
/**
* Sets the EditDomain for this EditorPart.
* @param ed the domain
*/
protected void setEditDomain(DefaultEditDomain ed) {
this.editDomain = ed;
}
protected void showPropertiesView() {
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
try {
page.showView(IBPELUIConstants.PROPERTY_VIEW_ID);
} catch (PartInitException e) {
BPELUIPlugin.log(e);
}
}
/**
* The editor part name should be the same as the one appearing in the logical view.
*/
protected void updateTitle() {
setPartName(getProcess().getName());
}
public void modelMarkersChanged ( ResourceInfo resourceInfo , IMarkerDelta [] markerDelta ) {
Resource resource = resourceInfo.getResource();
for ( IMarkerDelta delta : markerDelta ) {
String href = (String) delta.getAttribute( "address.model" ); //$NON-NLS-1$
if (href == null) {
continue;
}
EObject target = null;
switch (delta.getKind()) {
case IResourceDelta.ADDED :
target = resource.getEObject(href);
if (target != null) {
this.fMarkers2EObject.put(delta.getId(),target);
target.eNotify( new NotificationImpl(AdapterNotification.NOTIFICATION_MARKER_ADDED,null,delta.getMarker() ));
}
break;
case IResourceDelta.CHANGED :
target = this.fMarkers2EObject.remove(delta.getId());
if (target != null) {
target.eNotify( new NotificationImpl(AdapterNotification.NOTIFICATION_MARKER_CHANGED,delta.getMarker(),null));
}
break;
case IResourceDelta.REMOVED :
target = this.fMarkers2EObject.remove(delta.getId());
if (target != null) {
target.eNotify( new NotificationImpl(AdapterNotification.NOTIFICATION_MARKER_DELETED,delta.getMarker(),null));
}
break;
}
}
}
@Override
public boolean isDirty() {
return this.fTextEditor.isDirty() || this.editDomain.getCommandStack().isDirty();
}
@Override
public IEditorPart getActiveEditor() {
return super.getActiveEditor();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
// https://jira.jboss.org/browse/JBIDE-6365
// TODO: this is just a quick hack to get past the problem of import files being moved/renamed.
// The proper way to do this is to implement the eclipse refactoring framework for bpel files.
public class RefactoringListener implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
IResourceDeltaVisitor dv = new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) throws CoreException {
IPath newPath = delta.getMovedToPath();
if (delta.getKind()==IResourceDelta.REMOVED && newPath!=null) {
// a file was moved or renamed - check if it's an imported file
List<Import> imports = process.getImports();
for (Import imp : imports)
{
IPath path = new Path(imp.getLocation());
IPath folder = ((IFileEditorInput)getEditorInput()).getFile().getFullPath().removeLastSegments(1);
if (!path.isAbsolute()) {
// need absolute path
path = folder.append(path);
}
if (path.equals(delta.getResource().getFullPath())) {
IPath relPath = newPath.makeRelativeTo(folder);
imp.setLocation(relPath.toString());
Display.getDefault().asyncExec( new Runnable() {
public void run() {
doSave(null);
}
});
}
}
}
return true;
}
};
try {
event.getDelta().accept(dv);
} catch (CoreException e) {
BPELUIPlugin.log(e);
}
}
}
}