/******************************************************************************* * Copyright (c) 2006-2009 g-Eclipse Consortium * 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 * * Initial development of the original code was made for the g-Eclipse project * funded by European Union project number: FP6-IST-034327 * http://www.geclipse.eu/ * * Contributors: * RUR (http://acet.rdg.ac.uk/) * - Ashish Thandavan - initial API and implementation * - David Johnson ******************************************************************************/ package eu.geclipse.workflow.ui.edit.parts; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.OperationHistoryFactory; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IFile; 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.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.StackLayout; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.Request; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.commands.Command; import org.eclipse.gef.editpolicies.FlowLayoutEditPolicy; import org.eclipse.gef.editpolicies.LayoutEditPolicy; import org.eclipse.gef.requests.CreateRequest; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles; import org.eclipse.gmf.runtime.draw2d.ui.figures.ConstrainedToolbarLayout; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure; import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import eu.geclipse.core.model.GridModel; import eu.geclipse.core.model.IGridRoot; import eu.geclipse.jsdl.JSDLJobDescription; import eu.geclipse.jsdl.ui.wizards.NewJobWizard; import eu.geclipse.workflow.model.IWorkflowJob; import eu.geclipse.workflow.ui.edit.commands.ClearJobDescPropertyCommand; import eu.geclipse.workflow.ui.edit.commands.UpdateJobPortsCommand; import eu.geclipse.workflow.ui.edit.policies.WorkflowJobCanonicalEditPolicy; import eu.geclipse.workflow.ui.edit.policies.WorkflowJobDragDropEditPolicy; import eu.geclipse.workflow.ui.edit.policies.WorkflowJobItemSemanticEditPolicy; import eu.geclipse.workflow.ui.internal.WorkflowDiagramEditorPlugin; import eu.geclipse.workflow.ui.internal.WorkflowJobFigure; /** * The class that connects the Figure and Model of the WorkflowJob */ public class WorkflowJobEditPart extends ShapeNodeEditPart { protected Collection<Resource> savedResources = new ArrayList<Resource>(); protected Collection<Resource> removedResources = new ArrayList<Resource>(); protected Collection<Resource> changedResources = new ArrayList<Resource>(); String msg; protected IResourceChangeListener resourceChangeListener = new IResourceChangeListener() { public void resourceChanged( final IResourceChangeEvent event ) { IResourceDelta delta = event.getDelta(); try { class ResourceDeltaVisitor implements IResourceDeltaVisitor { protected Collection<IResource> changedRes = new ArrayList<IResource>(); protected Collection<IResource> removedRes = new ArrayList<IResource>(); public boolean visit( final IResourceDelta visitDelta ) throws CoreException { if( visitDelta.getFlags() != IResourceDelta.MARKERS && visitDelta.getResource().getType() == IResource.FILE ) { // TODO implement IResourceDelta.ADDED if( ( visitDelta.getKind() & ( IResourceDelta.CHANGED | IResourceDelta.REMOVED ) ) != 0 ) { IResource resource = visitDelta.getResource(); if( resource != null ) { if( ( visitDelta.getKind() & IResourceDelta.REMOVED ) != 0 ) { this.removedRes.add( resource ); } else if( !WorkflowJobEditPart.this.savedResources.remove( resource ) ) { this.changedRes.add( resource ); } } } } return true; } public Collection<IResource> getChangedResources() { return this.changedRes; } public Collection<IResource> getRemovedResources() { return this.removedRes; } } ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(); delta.accept( visitor ); // if a JSDL within an open .workflow workflow has changed, scan through the // workflow and re-sync it EObject o = WorkflowJobEditPart.this.resolveSemanticElement(); if (o instanceof IWorkflowJob) { IWorkflowJob job = ( IWorkflowJob )o; Collection<IResource> changed = visitor.getChangedResources(); for (Iterator<IResource> i = changed.iterator(); i.hasNext();) { IResource res = i.next(); String loc = res.getLocation().toString(); String jobDesc = job.getJobDescription(); EObject wfContainer = job.eContainer(); String wfFileString = EcoreUtil.getURI( wfContainer ).toPlatformString( true ); IGridRoot gridModelRoot = GridModel.getRoot(); // Grid Model root IFileStore gridModelRootFileStore = gridModelRoot.getFileStore(); String gridModelRootFileStoreString = gridModelRootFileStore.toString(); URI uri = URIUtil.toURI(gridModelRootFileStoreString + wfFileString); IFile[] workflowIFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI( uri ); IResource res1 = workflowIFile[0].getParent().findMember( jobDesc ); String fileString = res1.getLocation().toString(); if (loc.equals( fileString )) { // Need to find a better way of doing this... // final Display display = Display.getDefault(); // msg = "Workflow job '" + job.getName() + "' will disconnect its existing links when updating data-staging"; // display.syncExec( new Runnable() { // public void run() { // MessageDialog.openInformation( display.getActiveShell(), "Warning", msg ); // } // }); java.net.URI jsdlPathUri = URIUtil.toURI( fileString ); IFile jsdlFile = ResourcesPlugin.getWorkspace() .getRoot() .findFilesForLocationURI( jsdlPathUri )[ 0 ]; JSDLJobDescription jsdl = new JSDLJobDescription( jsdlFile ); AbstractTransactionalCommand updatePortsCommand = new UpdateJobPortsCommand(WorkflowJobEditPart.this, jsdl); try { OperationHistoryFactory.getOperationHistory() .execute( updatePortsCommand, new NullProgressMonitor(), null ); } catch ( ExecutionException eE ) { // TODO add problem reporting } } } // if a JSDL within an open .workflow workflow has been removed, remove it from // the job part property Collection<IResource> removed = visitor.getRemovedResources(); for (Iterator<IResource> i = removed.iterator(); i.hasNext();) { IResource res = i.next(); String loc = res.getLocation().toString(); String jobDesc = job.getJobDescription(); String wfFileString = job.getWorkflow().eResource().getURI().toPlatformString( true ); IGridRoot gridModelRoot = GridModel.getRoot(); // Grid Model root IFileStore gridModelRootFileStore = gridModelRoot.getFileStore(); String gridModelRootFileStoreString = gridModelRootFileStore.toString(); URI uri = URIUtil.toURI(gridModelRootFileStoreString + wfFileString); IFile[] workflowIFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI( uri ); IResource res1 = workflowIFile[0].getParent().findMember( jobDesc ); IFile[] file = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation( res1.getLocation() ); if (loc.equals( file.toString() )) { AbstractTransactionalCommand clearJobDescCmd = new ClearJobDescPropertyCommand( job ); try { OperationHistoryFactory.getOperationHistory() .execute( clearJobDescCmd, new NullProgressMonitor(), null ); } catch( ExecutionException e ) { // TODO add problem reporting e.printStackTrace(); } } } } } catch (CoreException exception ) { //Activator.logException( exception ); // TODO add problem reporting } } }; /** * @generated */ public static final int VISUAL_ID = 1001; protected IFigure contentPane; protected IFigure primaryShape; /** * Constructor */ public WorkflowJobEditPart( final View view ) { super( view ); ResourcesPlugin.getWorkspace() .addResourceChangeListener( this.resourceChangeListener, IResourceChangeEvent.POST_CHANGE ); } /** * Creates the edit policies for this EditPart */ @Override protected void createDefaultEditPolicies() { installEditPolicy( EditPolicyRoles.CREATION_ROLE, new CreationEditPolicy() ); super.createDefaultEditPolicies(); installEditPolicy( EditPolicyRoles.SEMANTIC_ROLE, new WorkflowJobItemSemanticEditPolicy() ); installEditPolicy( EditPolicyRoles.DRAG_DROP_ROLE, new WorkflowJobDragDropEditPolicy() ); installEditPolicy( EditPolicyRoles.CANONICAL_ROLE, new WorkflowJobCanonicalEditPolicy() ); installEditPolicy( EditPolicy.LAYOUT_ROLE, createLayoutEditPolicy() ); // XXX need an SCR to runtime to have another abstract superclass that would // let children add reasonable editpolicies removeEditPolicy( EditPolicyRoles.CONNECTION_HANDLES_ROLE); } /** * @generated */ protected LayoutEditPolicy createLayoutEditPolicy() { FlowLayoutEditPolicy lep = new FlowLayoutEditPolicy() { @Override protected Command createAddCommand( EditPart child, EditPart after ) { return null; } @Override protected Command createMoveChildCommand( EditPart child, EditPart after ) { return null; } @Override protected Command getCreateCommand( CreateRequest request ) { return null; } }; return lep; } /** * Creates the shape of the node */ protected IFigure createNodeShape() { WorkflowJobFigure figure = new WorkflowJobFigure(); return this.primaryShape = figure; } /** * Returns the shape of this figure */ public WorkflowJobFigure getPrimaryShape() { return ( WorkflowJobFigure )this.primaryShape; } /** * Add children to this edit part */ protected boolean addFixedChild( final EditPart childEditPart ) { if( childEditPart instanceof WorkflowJobNameEditPart ) { ( ( WorkflowJobNameEditPart )childEditPart ).setLabel( getPrimaryShape().getFigureWorkflowJobNameFigure() ); return true; } return false; } /** * Remove a fixed child */ protected boolean removeFixedChild( final EditPart childEditPart ) { return false; } /** * Adds the child's visual */ @Override protected void addChildVisual( final EditPart childEditPart, final int index ) { if( addFixedChild( childEditPart ) ) { return; } super.addChildVisual( childEditPart, 1 ); // if ( addChild( childEditPart )) { // return; // } // super.addChildVisual( childEditPart, -1 ); } /* * This does the double-click action on workflow job edit parts * (non-Javadoc) * @see org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart#performRequest(org.eclipse.gef.Request) */ @Override public void performRequest( final Request request ) { // on double-click of this edit part if (request.getType().equals( RequestConstants.REQ_OPEN )) { IWorkflowJob job = ( IWorkflowJob )this.resolveSemanticElement(); String filename = job.getJobDescription(); if ( filename!=null ){ if ( (!"".equals( filename )) ) { //$NON-NLS-1$ // if something is present in job description property String wfFileString = job.getWorkflow().eResource().getURI().toPlatformString( true ); IGridRoot gridModelRoot = GridModel.getRoot(); // Grid Model root IFileStore gridModelRootFileStore = gridModelRoot.getFileStore(); String gridModelRootFileStoreString = gridModelRootFileStore.toString(); URI uri = URIUtil.toURI(gridModelRootFileStoreString + wfFileString); IFile[] workflowIFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI( uri ); IResource res = workflowIFile[0].getParent().findMember( filename ); IFile[] file = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation( res.getLocation() ); try { if( (file.length != 0) && file[ 0 ].exists() ) { IDE.openEditor( WorkflowDiagramEditorPlugin.getDefault() .getWorkbench() .getActiveWorkbenchWindow() .getActivePage(), file[ 0 ], true ); } else { // need to handle if file does not exist - indicates corrupted workflow file or missing JSDL // TODO add problem reporting } } catch( PartInitException partInitException ) { WorkflowDiagramEditorPlugin.logException( partInitException ); } } else { createNewJobWizard(); } } else { createNewJobWizard(); } } super.performRequest( request ); } private void createNewJobWizard() { // if there is no entry in job description property, fire up NewJobWizard NewJobWizard newJobWizard = new NewJobWizard(); // this bit find the root directory of the workflow TransactionalEditingDomain domain = this.getEditingDomain(); ResourceSet resourceSet = domain.getResourceSet(); Resource res = resourceSet.getResources().get( 0 ); org.eclipse.emf.common.util.URI wfRootUri = res.getURI(); String wfRootPath = wfRootUri.path(); String[] dirs = wfRootPath.split( "/" ); //$NON-NLS-1$ String projectName = dirs[2]; IFileStore wfRootFileStore = GridModel.getRoot().getFileStore().getChild( projectName ).getChild( "Workflows" ); //$NON-NLS-1$ newJobWizard.init( PlatformUI.getWorkbench(), new StructuredSelection(wfRootFileStore) ); WizardDialog wizard = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), newJobWizard); wizard.create(); wizard.open(); } /** * Removes the child's visual */ @Override protected void removeChildVisual( final EditPart childEditPart ) { if( removeFixedChild( childEditPart ) ) { return; } super.removeChildVisual( childEditPart ); } /** * @generated */ @Override protected IFigure getContentPaneFor( final IGraphicalEditPart editPart ) { return super.getContentPaneFor( editPart ); } /** * @generated */ protected NodeFigure createNodePlate() { DefaultSizeNodeFigure result = new DefaultSizeNodeFigure( getMapMode().DPtoLP( 100 ), getMapMode().DPtoLP( 50 ) ); return result; } /** * Creates figure for this edit part. * */ @Override protected NodeFigure createNodeFigure() { NodeFigure figure = createNodePlate(); figure.setLayoutManager( new StackLayout() ); IFigure shape = createNodeShape(); figure.add( shape ); this.contentPane = setupContentPane( shape ); return figure; } /** * Default implementation treats passed figure as content pane. * Respects layout one may have set for generated figure. * @param nodeShape instance of generated figure class * @generated */ protected IFigure setupContentPane( final IFigure nodeShape ) { if( nodeShape.getLayoutManager() == null ) { ConstrainedToolbarLayout layout = new ConstrainedToolbarLayout(); layout.setSpacing( getMapMode().DPtoLP( 5 ) ); nodeShape.setLayoutManager( layout ); } return nodeShape; // use nodeShape itself as contentPane } /** * Returns the content pane */ @Override public IFigure getContentPane() { if( this.contentPane != null ) { return this.contentPane; } return super.getContentPane(); } // @Override // public EditPart getPrimaryChildEditPart() { // return getChildBySemanticHint( WorkflowVisualIDRegistry.getType( WorkflowJobDescriptionEditPart.VISUAL_ID ) ); // } }