/******************************************************************************* * Copyright (c) 2006, 2007 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 ******************************************************************************/ package eu.geclipse.workflow.ui.part; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; 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.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.ui.URIEditorInput; import org.eclipse.emf.common.util.URI; 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.EContentAdapter; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.NotificationFilter; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.diagram.core.DiagramEditingDomainFactory; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.AbstractDocumentProvider; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.DiagramDocument; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocumentProvider; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocument; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.util.DiagramIOUtil; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.part.FileEditorInput; import eu.geclipse.workflow.ui.editor.WorkflowDiagramEditorUtil; import eu.geclipse.workflow.ui.internal.WorkflowDiagramEditorPlugin; /** * @generated */ public class WorkflowDocumentProvider extends AbstractDocumentProvider implements IDiagramDocumentProvider { /** * NOTE: The following four codes are hard-coded into this file from * org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.EditorStatusCodes * as the use of internal classes is discouraged and the GMF guys did not seem * to have a solution to this problem. */ public static final int OK = 0; public static final int ERROR = 1; /** * Status code indicating that an error occurred with a resource, such as * loading an image file. * * Set to 5 to be consistent with CommonUIStatusCodes. */ public static final int RESOURCE_FAILURE = 5; public static final int WARNING = 7; /** * NOTE: The above four codes are hard-coded into this file from * org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.EditorStatusCodes * as the use of internal classes is discouraged and the GMF guys did not seem * to have a solution to this problem. */ /** * @generated NOT */ @Override protected ElementInfo createElementInfo( Object element ) throws CoreException { if( false == element instanceof FileEditorInput && false == element instanceof URIEditorInput ) { throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, NLS.bind( Messages.getString( "WorkflowDocumentProvider_IncorrectInputError" ), //$NON-NLS-1$ new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput"} ), //$NON-NLS-1$ //$NON-NLS-2$ null ) ); } IEditorInput editorInput = ( IEditorInput )element; IDiagramDocument document = ( IDiagramDocument )createDocument( editorInput ); ResourceSetInfo info = new ResourceSetInfo( document, editorInput ); info.setModificationStamp( computeModificationStamp( info ) ); info.fStatus = null; return info; } /** * @generated NOT */ @Override protected IDocument createDocument( Object element ) throws CoreException { if( false == element instanceof FileEditorInput && false == element instanceof URIEditorInput ) { throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, NLS.bind( Messages.getString( "WorkflowDocumentProvider_IncorrectInputError" ), //$NON-NLS-1$ new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput"} ), //$NON-NLS-1$ //$NON-NLS-2$ null ) ); } IDocument document = createEmptyDocument(); setDocumentContent( document, ( IEditorInput )element ); setupDocument( element, document ); return document; } /** * Sets up the given document as it would be provided for the given element. The * content of the document is not changed. This default implementation is empty. * Subclasses may reimplement. * * @param element the blue-print element * @param document the document to set up * @generated */ protected void setupDocument( Object element, IDocument document ) { // for subclasses } /** * @generated */ private long computeModificationStamp( ResourceSetInfo info ) { int result = 0; for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null ) { if( file.getLocation() != null ) { result += file.getLocation().toFile().lastModified(); } else { result += file.getModificationStamp(); } } } return result; } /** * @generated */ @Override protected IDocument createEmptyDocument() { DiagramDocument document = new DiagramDocument(); document.setEditingDomain( createEditingDomain() ); return document; } /** * @generated */ private TransactionalEditingDomain createEditingDomain() { TransactionalEditingDomain editingDomain = DiagramEditingDomainFactory.getInstance() .createEditingDomain(); editingDomain.setID( "eu.geclipse.workflow.ui.EditingDomain" ); //$NON-NLS-1$ final NotificationFilter diagramResourceModifiedFilter = NotificationFilter.createNotifierFilter( editingDomain.getResourceSet() ) .and( NotificationFilter.createEventTypeFilter( Notification.ADD ) ) .and( NotificationFilter.createFeatureFilter( ResourceSet.class, ResourceSet.RESOURCE_SET__RESOURCES ) ); editingDomain.getResourceSet().eAdapters().add( new Adapter() { private Notifier myTarger; public Notifier getTarget() { return myTarger; } public boolean isAdapterForType( Object type ) { return false; } public void notifyChanged( Notification notification ) { if( diagramResourceModifiedFilter.matches( notification ) ) { Object value = notification.getNewValue(); if( value instanceof Resource ) { ( ( Resource )value ).setTrackingModification( true ); } } } public void setTarget( Notifier newTarget ) { myTarger = newTarget; } } ); return editingDomain; } /** * @generated NOT */ protected void setDocumentContent( IDocument document, IEditorInput element ) throws CoreException { IDiagramDocument diagramDocument = ( IDiagramDocument )document; TransactionalEditingDomain domain = diagramDocument.getEditingDomain(); if( element instanceof FileEditorInput ) { IStorage storage = ( ( FileEditorInput )element ).getStorage(); Diagram diagram = DiagramIOUtil.load( domain, storage, true, getProgressMonitor() ); document.setContent( diagram ); } else if( element instanceof URIEditorInput ) { URI uri = ( ( URIEditorInput )element ).getURI(); Resource resource = null; try { resource = domain.getResourceSet().getResource( uri.trimFragment(), false ); if( resource == null ) { resource = domain.getResourceSet() .createResource( uri.trimFragment() ); } if( !resource.isLoaded() ) { try { Map options = new HashMap( GMFResourceFactory.getDefaultLoadOptions() ); // @see 171060 // options.put(org.eclipse.emf.ecore.xmi.XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE); resource.load( options ); } catch( IOException e ) { resource.unload(); throw e; } } if( uri.fragment() != null ) { EObject rootElement = resource.getEObject( uri.fragment() ); if( rootElement instanceof Diagram ) { document.setContent( ( Diagram )rootElement ); return; } } else { for( Iterator it = resource.getContents().iterator(); it.hasNext(); ) { Object rootElement = it.next(); if( rootElement instanceof Diagram ) { document.setContent( ( Diagram )rootElement ); return; } } } throw new RuntimeException( Messages.getString( "WorkflowDocumentProvider_NoDiagramInResourceError" ) ); //$NON-NLS-1$ } catch( Exception e ) { CoreException thrownExcp = null; if( e instanceof CoreException ) { thrownExcp = ( CoreException )e; } else { String msg = e.getLocalizedMessage(); thrownExcp = new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, msg != null ? msg : Messages.getString("WorkflowDocumentProvider_DiagramLoadingError"), //$NON-NLS-1$ e ) ); } throw thrownExcp; } } else { throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, NLS.bind( Messages.getString("WorkflowDocumentProvider_IncorrectInputError"), //$NON-NLS-1$ new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput"} ), //$NON-NLS-1$ //$NON-NLS-2$ null ) ); } } /** * @generated */ @Override public long getModificationStamp( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { return computeModificationStamp( info ); } return super.getModificationStamp( element ); } /** * @generated */ @Override public boolean isDeleted( Object element ) { IDiagramDocument document = getDiagramDocument( element ); if( document != null ) { Resource diagramResource = document.getDiagram().eResource(); if( diagramResource != null ) { IFile file = WorkspaceSynchronizer.getFile( diagramResource ); return file == null || file.getLocation() == null || !file.getLocation().toFile().exists(); } } return super.isDeleted( element ); } /** * @generated */ public ResourceSetInfo getResourceSetInfo( Object editorInput ) { return ( ResourceSetInfo )super.getElementInfo( editorInput ); } /** * @generated */ @Override protected void disposeElementInfo( Object element, ElementInfo info ) { if( info instanceof ResourceSetInfo ) { ResourceSetInfo resourceSetInfo = ( ResourceSetInfo )info; resourceSetInfo.dispose(); } super.disposeElementInfo( element, info ); } /** * @generated */ @Override protected void doValidateState( Object element, Object computationContext ) throws CoreException { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { Collection files2Validate = new ArrayList(); for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null && file.isReadOnly() ) { files2Validate.add( file ); } } ResourcesPlugin.getWorkspace() .validateEdit( ( IFile[] )files2Validate.toArray( new IFile[ files2Validate.size() ] ), computationContext ); } super.doValidateState( element, computationContext ); } /** * @generated NOT */ @Override public boolean isReadOnly( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { if( info.isUpdateCache() ) { try { updateCache( element ); } catch( CoreException ex ) { WorkflowDiagramEditorPlugin.getInstance() .logError( Messages.getString("WorkflowDocumentProvider_isModifiable"), ex ); //$NON-NLS-1$ // Error message to log was initially taken from // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable } } return info.isReadOnly(); } return super.isReadOnly( element ); } /** * @generated NOT */ @Override public boolean isModifiable( Object element ) { if( !isStateValidated( element ) ) { if( element instanceof FileEditorInput || element instanceof URIEditorInput ) { return true; } } ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { if( info.isUpdateCache() ) { try { updateCache( element ); } catch( CoreException ex ) { WorkflowDiagramEditorPlugin.getInstance() .logError( Messages.getString("WorkflowDocumentProvider_isModifiable"), ex ); //$NON-NLS-1$ // Error message to log was initially taken from // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable } } return info.isModifiable(); } return super.isModifiable( element ); } /** * @generated */ protected void updateCache( Object element ) throws CoreException { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null && file.isReadOnly() ) { info.setReadOnly( true ); info.setModifiable( false ); return; } } info.setReadOnly( false ); info.setModifiable( true ); return; } } /** * @generated */ @Override protected void doUpdateStateCache( Object element ) throws CoreException { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { info.setUpdateCache( true ); } super.doUpdateStateCache( element ); } /** * @generated */ @Override public boolean isSynchronized( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { return info.isSynchronized(); } return super.isSynchronized( element ); } /** * @generated */ @Override protected ISchedulingRule getResetRule( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { Collection rules = new ArrayList(); for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null ) { rules.add( ResourcesPlugin.getWorkspace() .getRuleFactory() .modifyRule( file ) ); } } return new MultiRule( ( ISchedulingRule[] )rules.toArray( new ISchedulingRule[ rules.size() ] ) ); } return null; } /** * @generated */ @Override protected ISchedulingRule getSaveRule( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { Collection rules = new ArrayList(); for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null ) { rules.add( computeSchedulingRule( file ) ); } } return new MultiRule( ( ISchedulingRule[] )rules.toArray( new ISchedulingRule[ rules.size() ] ) ); } return null; } /** * @generated */ @Override protected ISchedulingRule getSynchronizeRule( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { Collection rules = new ArrayList(); for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null ) { rules.add( ResourcesPlugin.getWorkspace() .getRuleFactory() .refreshRule( file ) ); } } return new MultiRule( ( ISchedulingRule[] )rules.toArray( new ISchedulingRule[ rules.size() ] ) ); } return null; } /** * @generated */ @Override protected ISchedulingRule getValidateStateRule( Object element ) { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { Collection files = new ArrayList(); for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); IFile file = WorkspaceSynchronizer.getFile( nextResource ); if( file != null ) { files.add( file ); } } return ResourcesPlugin.getWorkspace() .getRuleFactory() .validateEditRule( ( IFile[] )files.toArray( new IFile[ files.size() ] ) ); } return null; } /** * @generated */ private ISchedulingRule computeSchedulingRule( IResource toCreateOrModify ) { if( toCreateOrModify.exists() ) return ResourcesPlugin.getWorkspace() .getRuleFactory() .modifyRule( toCreateOrModify ); IResource parent = toCreateOrModify; do { /* * XXX This is a workaround for * https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601 * IResourceRuleFactory.createRule should iterate the hierarchy * itself. */ toCreateOrModify = parent; parent = toCreateOrModify.getParent(); } while( parent != null && !parent.exists() ); return ResourcesPlugin.getWorkspace() .getRuleFactory() .createRule( toCreateOrModify ); } /** * @generated */ @Override protected void doSynchronize( Object element, IProgressMonitor monitor ) throws CoreException { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { for( Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); handleElementChanged( info, nextResource, monitor ); } return; } super.doSynchronize( element, monitor ); } /** * @generated NOT */ @Override protected void doSaveDocument( IProgressMonitor monitor, Object element, IDocument document, boolean overwrite ) throws CoreException { ResourceSetInfo info = getResourceSetInfo( element ); if( info != null ) { if( !overwrite && !info.isSynchronized() ) { throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, IStatus.OK, Messages.getString("WorkflowDocumentProvider_UnsynchronizedFileSaveError"), //$NON-NLS-1$ null ) ); } info.stopResourceListening(); fireElementStateChanging( element ); List resources = info.getResourceSet().getResources(); try { monitor.beginTask( Messages.getString("WorkflowDocumentProvider_SaveDiagramTask"), //$NON-NLS-1$ resources.size() + 1 ); //"Saving diagram" for( Iterator it = resources.iterator(); it.hasNext(); ) { Resource nextResource = ( Resource )it.next(); monitor.setTaskName( NLS.bind( Messages.getString("WorkflowDocumentProvider_SaveNextResourceTask"), //$NON-NLS-1$ nextResource.getURI() ) ); if( nextResource.isLoaded() && !info.getEditingDomain().isReadOnly( nextResource ) ) { try { nextResource.save( WorkflowDiagramEditorUtil.getSaveOptions() ); } catch( IOException e ) { fireElementStateChangeFailed( element ); throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, // EditorStatusCodes.RESOURCE_FAILURE, RESOURCE_FAILURE, e.getLocalizedMessage(), null ) ); } } monitor.worked( 1 ); } monitor.done(); } catch( RuntimeException x ) { fireElementStateChangeFailed( element ); throw x; } finally { info.startResourceListening(); } } else { URI newResoruceURI; List affectedFiles = null; if( element instanceof FileEditorInput ) { IFile newFile = ( ( FileEditorInput )element ).getFile(); affectedFiles = Collections.singletonList( newFile ); newResoruceURI = URI.createPlatformResourceURI( newFile.getFullPath() .toString(), true ); } else if( element instanceof URIEditorInput ) { newResoruceURI = ( ( URIEditorInput )element ).getURI(); } else { fireElementStateChangeFailed( element ); throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, NLS.bind( Messages.getString("WorkflowDocumentProvider_IncorrectInputError"), //$NON-NLS-1$ new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", //$NON-NLS-1$ "org.eclipse.emf.common.ui.URIEditorInput"} ), //$NON-NLS-1$ null ) ); } if( false == document instanceof IDiagramDocument ) { fireElementStateChangeFailed( element ); throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, "Incorrect document used: " + document + " instead of org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument", //$NON-NLS-1$ //$NON-NLS-2$ null ) ); } IDiagramDocument diagramDocument = ( IDiagramDocument )document; final Resource newResource = diagramDocument.getEditingDomain() .getResourceSet() .createResource( newResoruceURI ); final Diagram diagramCopy = ( Diagram )EcoreUtil.copy( diagramDocument.getDiagram() ); try { new AbstractTransactionalCommand( diagramDocument.getEditingDomain(), NLS.bind( Messages.getString("WorkflowDocumentProvider_SaveAsOperation"), //$NON-NLS-1$ diagramCopy.getName() ), affectedFiles ) { @Override protected CommandResult doExecuteWithResult( IProgressMonitor monitor, IAdaptable info ) throws ExecutionException { newResource.getContents().add( diagramCopy ); return CommandResult.newOKCommandResult(); } }.execute( monitor, null ); newResource.save( WorkflowDiagramEditorUtil.getSaveOptions() ); } catch( ExecutionException e ) { fireElementStateChangeFailed( element ); throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, e.getLocalizedMessage(), null ) ); } catch( IOException e ) { fireElementStateChangeFailed( element ); throw new CoreException( new Status( IStatus.ERROR, WorkflowDiagramEditorPlugin.ID, 0, e.getLocalizedMessage(), null ) ); } newResource.unload(); } } /** * @generated NOT */ protected void handleElementChanged( ResourceSetInfo info, Resource changedResource, IProgressMonitor monitor ) { IFile file = WorkspaceSynchronizer.getFile( changedResource ); if( file != null ) { try { file.refreshLocal( IResource.DEPTH_INFINITE, monitor ); } catch( CoreException ex ) { WorkflowDiagramEditorPlugin.getInstance() .logError( Messages.getString("WorkflowDocumentProvider_handleElementContentChanged"), //$NON-NLS-1$ ex ); // Error message to log was initially taken from // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.FileDocumentProvider_handleElementContentChanged } } changedResource.unload(); fireElementContentAboutToBeReplaced( info.getEditorInput() ); removeUnchangedElementListeners( info.getEditorInput(), info ); info.fStatus = null; try { setDocumentContent( info.fDocument, info.getEditorInput() ); } catch( CoreException e ) { info.fStatus = e.getStatus(); } if( !info.fCanBeSaved ) { info.setModificationStamp( computeModificationStamp( info ) ); } addUnchangedElementListeners( info.getEditorInput(), info ); fireElementContentReplaced( info.getEditorInput() ); } /** * @generated */ protected void handleElementMoved( IEditorInput input, URI uri ) { if( input instanceof FileEditorInput ) { IFile newFile = ResourcesPlugin.getWorkspace() .getRoot() .getFile( new Path( URI.decode( uri.path() ) ).removeFirstSegments( 1 ) ); fireElementMoved( input, newFile == null ? null : new FileEditorInput( newFile ) ); return; } // TODO: append suffix to the URI! (use diagram as a parameter) fireElementMoved( input, new URIEditorInput( uri ) ); } /** * @generated */ public IEditorInput createInputWithEditingDomain( IEditorInput editorInput, TransactionalEditingDomain domain ) { return editorInput; } /** * @generated */ public IDiagramDocument getDiagramDocument( Object element ) { IDocument doc = getDocument( element ); if( doc instanceof IDiagramDocument ) { return ( IDiagramDocument )doc; } return null; } /** * @generated */ @Override protected IRunnableContext getOperationRunner( IProgressMonitor monitor ) { return null; } /** * @generated */ protected class ResourceSetInfo extends ElementInfo { /** * @generated */ private long myModificationStamp = IResource.NULL_STAMP; /** * @generated */ private WorkspaceSynchronizer mySynchronizer; /** * @generated */ private Collection myUnSynchronizedResources = new ArrayList(); /** * @generated */ private IDiagramDocument myDocument; /** * @generated */ private IEditorInput myEditorInput; /** * @generated */ private boolean myUpdateCache = true; /** * @generated */ private boolean myModifiable = false; /** * @generated */ private boolean myReadOnly = true; /** * @generated */ private ResourceSetModificationListener myResourceSetListener; /** * @generated */ public ResourceSetInfo( IDiagramDocument document, IEditorInput editorInput ) { super( document ); myDocument = document; myEditorInput = editorInput; startResourceListening(); myResourceSetListener = new ResourceSetModificationListener( this ); getResourceSet().eAdapters().add( myResourceSetListener ); } /** * @generated */ public long getModificationStamp() { return myModificationStamp; } /** * @generated */ public void setModificationStamp( long modificationStamp ) { myModificationStamp = modificationStamp; } /** * @generated */ public TransactionalEditingDomain getEditingDomain() { return myDocument.getEditingDomain(); } /** * @generated */ public ResourceSet getResourceSet() { return getEditingDomain().getResourceSet(); } /** * @generated */ public IEditorInput getEditorInput() { return myEditorInput; } /** * @generated */ public void dispose() { stopResourceListening(); getResourceSet().eAdapters().remove( myResourceSetListener ); for( Iterator it = getResourceSet().getResources().iterator(); it.hasNext(); ) { Resource resource = ( Resource )it.next(); resource.unload(); } } /** * @generated */ public boolean isSynchronized() { return myUnSynchronizedResources.size() == 0; } /** * @generated */ public void setUnSynchronized( Resource resource ) { myUnSynchronizedResources.add( resource ); } /** * @generated */ public void setSynchronized( Resource resource ) { myUnSynchronizedResources.remove( resource ); } /** * @generated */ public final void stopResourceListening() { mySynchronizer.dispose(); mySynchronizer = null; } /** * @generated */ public final void startResourceListening() { mySynchronizer = new WorkspaceSynchronizer( getEditingDomain(), new SynchronizerDelegate() ); } /** * @generated */ public boolean isUpdateCache() { return myUpdateCache; } /** * @generated */ public void setUpdateCache( boolean update ) { myUpdateCache = update; } /** * @generated */ public boolean isModifiable() { return myModifiable; } /** * @generated */ public void setModifiable( boolean modifiable ) { myModifiable = modifiable; } /** * @generated */ public boolean isReadOnly() { return myReadOnly; } /** * @generated */ public void setReadOnly( boolean readOnly ) { myReadOnly = readOnly; } /** * @generated */ private class SynchronizerDelegate implements WorkspaceSynchronizer.Delegate { /** * @generated */ public void dispose() { } /** * @generated */ public boolean handleResourceChanged( final Resource resource ) { synchronized( ResourceSetInfo.this ) { if( ResourceSetInfo.this.fCanBeSaved ) { ResourceSetInfo.this.setUnSynchronized( resource ); return true; } } Display.getDefault().asyncExec( new Runnable() { public void run() { handleElementChanged( ResourceSetInfo.this, resource, null ); } } ); return true; } /** * @generated */ public boolean handleResourceDeleted( Resource resource ) { synchronized( ResourceSetInfo.this ) { if( ResourceSetInfo.this.fCanBeSaved ) { ResourceSetInfo.this.setUnSynchronized( resource ); return true; } } Display.getDefault().asyncExec( new Runnable() { public void run() { fireElementDeleted( ResourceSetInfo.this.getEditorInput() ); } } ); return true; } /** * @generated */ public boolean handleResourceMoved( Resource resource, final URI newURI ) { synchronized( ResourceSetInfo.this ) { if( ResourceSetInfo.this.fCanBeSaved ) { ResourceSetInfo.this.setUnSynchronized( resource ); return true; } } if( myDocument.getDiagram().eResource() == resource ) { Display.getDefault().asyncExec( new Runnable() { public void run() { handleElementMoved( ResourceSetInfo.this.getEditorInput(), newURI ); } } ); } else { handleResourceDeleted( resource ); } return true; } } } /** * @generated */ private class ResourceSetModificationListener extends EContentAdapter { /** * @generated */ private NotificationFilter myModifiedFilter; /** * @generated */ private ResourceSetInfo myInfo; /** * @generated */ public ResourceSetModificationListener( ResourceSetInfo info ) { myInfo = info; myModifiedFilter = NotificationFilter.createEventTypeFilter( Notification.SET ) .or( NotificationFilter.createEventTypeFilter( Notification.UNSET ) ) .and( NotificationFilter.createFeatureFilter( Resource.class, Resource.RESOURCE__IS_MODIFIED ) ); } /** * @generated */ @Override public void notifyChanged( Notification notification ) { if( notification.getNotifier() instanceof ResourceSet ) { super.notifyChanged( notification ); } if( !notification.isTouch() && myModifiedFilter.matches( notification ) ) { if( notification.getNotifier() instanceof Resource ) { Resource resource = ( Resource )notification.getNotifier(); if( resource.isLoaded() ) { boolean modified = false; for( Iterator it = myInfo.getResourceSet() .getResources() .iterator(); it.hasNext() && !modified; ) { Resource nextResource = ( Resource )it.next(); if( nextResource.isLoaded() ) { modified = nextResource.isModified(); } } boolean dirtyStateChanged = false; synchronized( myInfo ) { if( modified != myInfo.fCanBeSaved ) { myInfo.fCanBeSaved = modified; dirtyStateChanged = true; } if( !resource.isModified() ) { myInfo.setSynchronized( resource ); } } if( dirtyStateChanged ) { fireElementDirtyStateChanged( myInfo.getEditorInput(), modified ); if( !modified ) { myInfo.setModificationStamp( computeModificationStamp( myInfo ) ); } } } } } } } }