/*******************************************************************************
* 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 ) );
}
}
}
}
}
}
}
}