/** * Copyright (c) 2015 committers of YAKINDU and others. * 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.base.xtext.utils.gmf.experimental; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import java.util.Map; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.xtext.resource.IResourceDescription; import org.eclipse.xtext.resource.IResourceServiceProvider; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.ui.editor.IDirtyResource; import org.eclipse.xtext.ui.editor.IDirtyStateManager; import org.eclipse.xtext.ui.shared.Access; import com.google.common.collect.Maps; public abstract class DirtyStateAwareDiagramDocumentEditor extends DiagramDocumentEditor { private IDirtyStateManager dirtyStateManager; private Map<URI, IDirtyResource> uri2dirtyResource; public DirtyStateAwareDiagramDocumentEditor(boolean hasFlyoutPalette) { super(hasFlyoutPalette); dirtyStateManager = Access.getIDirtyStateManager().get(); uri2dirtyResource = Maps.newHashMap(); } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { super.init(site, input); createDirtyResources(); } private void createDirtyResources() { List<Resource> resources = getResources(); for (Resource resource : resources) { if (!(resource instanceof XtextResource)) createDirtyResource(resource); } } private void createDirtyResource(Resource resource) { IResourceServiceProvider resourceServiceProvider = IResourceServiceProvider.Registry.INSTANCE .getResourceServiceProvider(resource.getURI()); if (resourceServiceProvider == null) { return; } final DirtyResourceAdapter dirtyResource = new DirtyResourceAdapter( resource, resourceServiceProvider); dirtyStateManager.manageDirtyState(dirtyResource); uri2dirtyResource.put(resource.getURI(), dirtyResource); if (EcoreUtil.getExistingAdapter(resource, DirtyResourceUpdater.class) == null) resource.eAdapters().add(new DirtyResourceUpdater(dirtyResource)); } @Override public void dispose() { removeDirtyResources(); super.dispose(); }; private void removeDirtyResources() { List<Resource> resources = getResources(); for (Resource resource : resources) { if (!(resource instanceof XtextResource)) removeDirtyResource(resource); } } private void removeDirtyResource(Resource resource) { IDirtyResource dirtyResource = uri2dirtyResource.get(resource.getURI()); dirtyStateManager.discardDirtyState(dirtyResource); uri2dirtyResource.remove(resource.getURI()); //TODO: remove adapter EcoreUtil.getExistingAdapter(resource, DirtyResourceUpdater.class) == null } private List<Resource> getResources() { TransactionalEditingDomain editingDomain = getEditingDomain(); EList<Resource> resources = editingDomain.getResourceSet() .getResources(); return resources; } private final class DirtyResourceUpdater extends EContentAdapter { private final DirtyResourceAdapter dirtyResource; private DirtyResourceUpdater(DirtyResourceAdapter dirtyResource) { this.dirtyResource = dirtyResource; } public void notifyChanged(Notification notification) { dirtyStateManager.announceDirtyStateChanged(dirtyResource); } @Override public boolean isAdapterForType(Object type) { return type == DirtyResourceUpdater.class; } } private static final class DirtyResourceAdapter implements IDirtyResource { private final Resource resource; private final IResourceServiceProvider serviceProvider; protected DirtyResourceAdapter(Resource resource, IResourceServiceProvider provider) { this.resource = resource; serviceProvider = provider; } public String getContents() { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { resource.save(outputStream, null); } catch (IOException e) { e.printStackTrace(); } return new String(outputStream.toByteArray()); } public String getActualContents() { return getContents(); } public IResourceDescription getDescription() { return serviceProvider.getResourceDescriptionManager() .getResourceDescription(resource); } public URI getURI() { return resource.getURI(); } } }