/** * <copyright> * </copyright> * * */ package org.emftext.language.java.resource.java.ui; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.util.URI; 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.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; import org.eclipse.emf.edit.provider.IItemPropertySource; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.PropertyDescriptor; import org.eclipse.emf.edit.ui.provider.PropertySource; import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.IPropertySource; /** * <p> * A text editor for 'java' models. * </p> * <p> * <p> * </p> * <p> * This editor has id * <code>org.emftext.language.java.resource.java.ui.JavaEditor</code> * </p> * <p> * The editor's context menu has id * <code>org.emftext.language.java.resource.java.EditorContext</code>. * </p> * <p> * The editor's ruler context menu has id * <code>org.emftext.language.java.resource.java.EditorRuler</code>. * </p> * <p> * The editor's editing context has id * <code>org.emftext.language.java.resource.java.EditorScope</code>. * </p> * <p> * </p> * </p> */ public class JavaEditor extends CompilationUnitEditor implements IEditingDomainProvider, org.emftext.language.java.resource.java.IJavaResourceProvider { private org.emftext.language.java.resource.java.ui.JavaHighlighting highlighting; private org.emftext.language.java.resource.java.ui.JavaBackgroundParsingStrategy bgParsingStrategy = new org.emftext.language.java.resource.java.ui.JavaBackgroundParsingStrategy(); private Collection<org.emftext.language.java.resource.java.IJavaBackgroundParsingListener> bgParsingListeners = new ArrayList<org.emftext.language.java.resource.java.IJavaBackgroundParsingListener>(); private org.emftext.language.java.resource.java.ui.JavaColorManager colorManager = new org.emftext.language.java.resource.java.ui.JavaColorManager(); private org.emftext.language.java.resource.java.IJavaTextResource resource; private org.emftext.language.java.resource.java.ui.JavaPropertySheetPage propertySheetPage; private EditingDomain editingDomain; private JavaOutlinePage outlinePage; /** * A custom document listener that triggers background parsing if needed. */ private final class DocumentListener implements IDocumentListener { public void documentAboutToBeChanged(DocumentEvent event) { } public void documentChanged(DocumentEvent event) { bgParsingStrategy.parse(event, getResource(), JavaEditor.this); } } public Object getAdapter(@SuppressWarnings("rawtypes") Class required) { if (IContentOutlinePage.class.equals(required)) { return createOutlinePage(); // return createEMFTextOutlinePage(); } else if (required.equals(IPropertySheetPage.class)) { return getPropertySheetPage(); } return super.getAdapter(required); } private JavaOutlinePage createEMFTextOutlinePage() { if (outlinePage == null) { outlinePage = new JavaOutlinePage(this); // Connect highlighting class and outline page for event notification outlinePage.addSelectionChangedListener(highlighting); highlighting.addSelectionChangedListener(outlinePage); } return outlinePage; } public void createPartControl(Composite parent) { super.createPartControl(parent); // // // Code Folding ProjectionViewer viewer = (ProjectionViewer) getSourceViewer(); // // Occurrence initiation, need ITextResource and ISourceViewer. highlighting = new org.emftext.language.java.resource.java.ui.JavaHighlighting(getResource(), viewer, colorManager, this); } protected void doSetInput(IEditorInput editorInput) throws CoreException { super.doSetInput(editorInput); initializeResourceObject(editorInput); IDocument document = getDocumentProvider().getDocument(getEditorInput()); document.addDocumentListener(new DocumentListener()); } private void initializeResourceObject(IEditorInput editorInput) { if (editorInput instanceof FileEditorInput) { initializeResourceObjectFromFile((FileEditorInput) editorInput); } else if (editorInput instanceof IStorageEditorInput) { initializeResourceObjectFromStorage((IStorageEditorInput) editorInput); } } private void initializeResourceObjectFromFile(FileEditorInput input) { IFile inputFile = input.getFile(); org.emftext.language.java.resource.java.mopp.JavaNature.activate(inputFile.getProject()); String path = inputFile.getFullPath().toString(); URI uri = URI.createPlatformResourceURI(path, true); ResourceSet resourceSet = getResourceSet(); org.emftext.language.java.resource.java.IJavaTextResource loadedResource = (org.emftext.language.java.resource.java.IJavaTextResource) resourceSet.getResource(uri, false); if (loadedResource == null) { try { Resource demandLoadedResource = null; // here we do not use getResource(), because 'resource' might be null, which is ok // when initializing the resource object org.emftext.language.java.resource.java.IJavaTextResource currentResource = this.resource; if (currentResource != null && !currentResource.getURI().fileExtension().equals(uri.fileExtension())) { // do not attempt to load if file extension has changed in a 'save as' operation } else { demandLoadedResource = resourceSet.getResource(uri, true); } if (demandLoadedResource instanceof org.emftext.language.java.resource.java.IJavaTextResource) { setResource((org.emftext.language.java.resource.java.IJavaTextResource) demandLoadedResource); } else { // the resource was not loaded by an EMFText resource, but some other EMF resource org.emftext.language.java.resource.java.ui.JavaUIPlugin.showErrorDialog("Invalid resource.", "The file '" + uri.lastSegment() + "' of type '" + uri.fileExtension() + "' can not be handled by the JavaEditor."); // close this editor because it can not present the resource close(false); } } catch (Exception e) { org.emftext.language.java.resource.java.ui.JavaUIPlugin.logError("Exception while loading resource in " + this.getClass().getSimpleName() + ".", e); } } else { setResource(loadedResource); } } private void initializeResourceObjectFromStorage(IStorageEditorInput input) { URI uri = null; try { IStorage storage = input.getStorage(); InputStream inputStream = storage.getContents(); uri = URI.createURI(storage.getName(), true); ResourceSet resourceSet = getResourceSet(); org.emftext.language.java.resource.java.IJavaTextResource resource = (org.emftext.language.java.resource.java.IJavaTextResource) resourceSet.createResource(uri); resource.load(inputStream, null); setResource(resource); } catch (CoreException e) { org.emftext.language.java.resource.java.ui.JavaUIPlugin.logError("Exception while loading resource (" + uri + ") in " + getClass().getSimpleName() + ".", e); } catch (IOException e) { org.emftext.language.java.resource.java.ui.JavaUIPlugin.logError("Exception while loading resource (" + uri + ") in " + getClass().getSimpleName() + ".", e); } } protected void performSaveAs(IProgressMonitor progressMonitor) { FileEditorInput input = (FileEditorInput) getEditorInput(); String path = input.getFile().getFullPath().toString(); ResourceSet resourceSet = getResourceSet(); URI platformURI = URI.createPlatformResourceURI(path, true); Resource oldFile = resourceSet.getResource(platformURI, true); super.performSaveAs(progressMonitor); // load and resave - input has been changed to new path by super FileEditorInput newInput = (FileEditorInput) getEditorInput(); String newPath = newInput.getFile().getFullPath().toString(); URI newPlatformURI = URI.createPlatformResourceURI(newPath, true); Resource newFile = resourceSet.createResource(newPlatformURI); newFile.getContents().clear(); newFile.getContents().addAll(oldFile.getContents()); try { oldFile.unload(); if (newFile.getErrors().isEmpty()) { newFile.save(null); } } catch (Exception e) { e.printStackTrace(); } } public ResourceSet getResourceSet() { return getEditingDomain().getResourceSet(); } public org.emftext.language.java.resource.java.IJavaTextResource getResource() { return resource; } private void setResource(org.emftext.language.java.resource.java.IJavaTextResource resource) { assert resource != null; this.resource = resource; if (this.resource.getErrors().isEmpty()) { EcoreUtil.resolveAll(this.resource); } } public IPropertySheetPage getPropertySheetPage() { if (propertySheetPage == null) { propertySheetPage = new org.emftext.language.java.resource.java.ui.JavaPropertySheetPage(); // add a slightly modified adapter factory that does not return any editors for // properties. this way, a model can never be modified through the properties view. AdapterFactory adapterFactory = new org.emftext.language.java.resource.java.ui.JavaAdapterFactoryProvider().getAdapterFactory(); propertySheetPage.setPropertySourceProvider(new AdapterFactoryContentProvider(adapterFactory) { protected IPropertySource createPropertySource(Object object, IItemPropertySource itemPropertySource) { return new PropertySource(object, itemPropertySource) { protected IPropertyDescriptor createPropertyDescriptor(IItemPropertyDescriptor itemPropertyDescriptor) { return new PropertyDescriptor(object, itemPropertyDescriptor) { public CellEditor createPropertyEditor(Composite composite) { return null; } }; } }; } }); highlighting.addSelectionChangedListener(propertySheetPage); } return propertySheetPage; } public EditingDomain getEditingDomain() { if (editingDomain == null) { editingDomain = new org.emftext.language.java.resource.java.ui.JavaEditingDomainProvider().getEditingDomain(getEditorInput()); } return editingDomain; } public void notifyBackgroundParsingFinished() { for (org.emftext.language.java.resource.java.IJavaBackgroundParsingListener listener : bgParsingListeners) { listener.parsingCompleted(getResource()); } } }