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