blob: 737cc76ed1aa7a7d3ca095ab3b9efe90faa7c7d2 [file] [log] [blame]
package org.eclipse.jdt.internal.ui.javaeditor;
/*
* Licensed Materials - Property of IBM,
* WebSphere Studio Workbench
* (c) Copyright IBM Corp 1999, 2000
*/
import java.util.Iterator;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.util.Assert;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
import org.eclipse.jdt.core.BufferChangedEvent;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IBufferChangedListener;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.IWorkingCopyManager;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jdt.internal.core.JavaModelStatus;
import org.eclipse.jdt.internal.ui.JavaPlugin;
public class CompilationUnitDocumentProvider extends FileDocumentProvider implements IWorkingCopyManager {
/**
* Synchronizes the buffer of a working copy with the document representing the buffer content.
* It would be more appropriate if the document could also serve as the working copy's buffer.
* Listens to buffer changes and translates those into document changes. Also listens to document
* changes and translates those into buffer changes, respectively.
*/
protected static class BufferSynchronizer implements IDocumentListener, IBufferChangedListener {
protected IDocument fDocument;
protected IBuffer fBuffer;
public BufferSynchronizer(IDocument document, ICompilationUnit unit) {
Assert.isNotNull(document);
Assert.isNotNull(unit);
fDocument= document;
try {
fBuffer= unit.getBuffer();
} catch (JavaModelException x) {
Assert.isNotNull(fBuffer);
}
}
public void install() {
fDocument.addDocumentListener(this);
fBuffer.addBufferChangedListener(this);
}
public void uninstall() {
fDocument.removeDocumentListener(this);
fBuffer.removeBufferChangedListener(this);
}
/**
* @see IDocumentListener#documentChanged
*/
public void documentChanged(DocumentEvent event) {
fBuffer.removeBufferChangedListener(this);
fBuffer.replace(event.getOffset(), event.getLength(), event.getText());
fBuffer.addBufferChangedListener(this);
}
/**
* @see IDocumentListener#documentAboutToBeChanged
*/
public void documentAboutToBeChanged(DocumentEvent event) {
}
/**
* @see IBufferChangedListener#bufferChanged
*/
public void bufferChanged(BufferChangedEvent event) {
fDocument.removeDocumentListener(this);
try {
if (event.getLength() > 0 || event.getText() != null)
fDocument.replace(event.getOffset(), event.getLength(), event.getText());
} catch (BadLocationException x) {
Assert.isTrue(false, "Buffer and Document are out of sync");
} finally {
fDocument.addDocumentListener(this);
}
}
};
protected class _FileSynchronizer extends FileSynchronizer {
public _FileSynchronizer(IFileEditorInput fileEditorInput) {
super(fileEditorInput);
}
};
/**
* Bundle of all required informations to allow working copy management.
*/
protected class CompilationUnitInfo extends FileInfo {
ICompilationUnit fCopy;
BufferSynchronizer fBufferSynchronizer;
CompilationUnitInfo(IDocument document, IAnnotationModel model, _FileSynchronizer fileSynchronizer, ICompilationUnit copy, BufferSynchronizer bufferSynchronizer) {
super(document, model, fileSynchronizer);
fCopy= copy;
fBufferSynchronizer= bufferSynchronizer;
}
};
protected class CompilationUnitMarkerAnnotationModel extends ResourceMarkerAnnotationModel {
public CompilationUnitMarkerAnnotationModel(IResource resource) {
super(resource);
}
protected MarkerAnnotation createMarkerAnnotation(IMarker marker) {
return new JavaMarkerAnnotation(marker);
}
};
/**
* Constructor
*/
public CompilationUnitDocumentProvider() {
}
protected ICompilationUnit createCompilationUnit(IFile file) {
Object element= JavaCore.create(file);
if (element instanceof ICompilationUnit)
return (ICompilationUnit) element;
return null;
}
/**
* @see AbstractDocumentProvider#createElementInfo(Object)
*/
protected ElementInfo createElementInfo(Object element) throws CoreException {
if ( !(element instanceof IFileEditorInput))
throw new CoreException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE_TYPE));
IFileEditorInput input= (IFileEditorInput) element;
ICompilationUnit original= createCompilationUnit(input.getFile());
if (original == null)
throw new CoreException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
try {
ICompilationUnit c= (ICompilationUnit) original.getWorkingCopy();
IDocument d= createCompilationUnitDocument(c);
IAnnotationModel m= createAnnotationModel(element);
_FileSynchronizer f= new _FileSynchronizer(input);
f.install();
BufferSynchronizer b= new BufferSynchronizer(d, c);
b.install();
return new CompilationUnitInfo(d, m, f, c, b);
} catch (JavaModelException x) {
throw new CoreException(x.getStatus());
}
}
/**
* @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
*/
protected void disposeElementInfo(Object element, ElementInfo info) {
CompilationUnitInfo cuInfo= (CompilationUnitInfo) info;
if (cuInfo.fBufferSynchronizer != null)
cuInfo.fBufferSynchronizer.uninstall();
cuInfo.fCopy.destroy();
super.disposeElementInfo(element, info);
}
/**
* @see AbstractDocumentProvider#aboutToChange(Object)
*/
public void aboutToChange(Object element) {
CompilationUnitInfo info= (CompilationUnitInfo) getElementInfo(element);
if (info != null) {
if (info.fBufferSynchronizer != null)
info.fBufferSynchronizer.uninstall();
}
super.aboutToChange(element);
}
/**
* @see AbstractDocumentProvider#changed(Object)
*/
public void changed(Object element) {
CompilationUnitInfo info= (CompilationUnitInfo) getElementInfo(element);
if (info != null && info.fBufferSynchronizer != null)
info.fBufferSynchronizer.install();
super.changed(element);
}
/**
* @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument)
*/
protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document) throws CoreException {
CompilationUnitInfo info= (CompilationUnitInfo) getElementInfo(element);
if (info != null) {
try {
// update structure, assumes lock on info.fCopy
info.fCopy.reconcile();
// commit working copy
// HackFinder.fixme("cannot commit the same working copy twice");
info.fCopy.commit(false, monitor);
AbstractMarkerAnnotationModel model= (AbstractMarkerAnnotationModel) info.fModel;
model.updateMarkers(info.fDocument);
} catch (JavaModelException x) {
throw new CoreException(x.getStatus());
}
} else {
super.doSaveDocument(monitor, element, document);
}
}
/**
* @see AbstractDocumentProvider#createAnnotationModel
*/
protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
if ( !(element instanceof IFileEditorInput))
throw new CoreException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE_TYPE));
IFileEditorInput input= (IFileEditorInput) element;
return new CompilationUnitMarkerAnnotationModel(input.getFile());
}
/**
* @see AbstractDocumentProvider#createDocument
*/
protected IDocument createDocument(Object element) throws CoreException {
Assert.isTrue(false);
return null;
}
/**
* Replaces createDocument of the super class.
*/
protected IDocument createCompilationUnitDocument(ICompilationUnit unit) throws CoreException {
String contents= "";
try {
contents= unit.getSource();
} catch (JavaModelException x) {
throw new CoreException(x.getStatus());
}
Document document= new Document(contents);
JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
IDocumentPartitioner partitioner= tools.createDocumentPartitioner();
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
return document;
}
/**
* @see AbstractDocumentProvider#resetDocument(Object)
*/
public void resetDocument(Object element) throws CoreException {
if (element == null)
return;
CompilationUnitInfo info= (CompilationUnitInfo) getElementInfo(element);
if (info != null && info.fCanBeSaved) {
try {
ICompilationUnit original= (ICompilationUnit) info.fCopy.getOriginalElement();
fireElementContentAboutToBeReplaced(element);
info.fDocument.set(original.getSource());
info.fCanBeSaved= false;
info.fDocument.addDocumentListener(info);
fireElementContentReplaced(element);
} catch (JavaModelException x) {
throw new CoreException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE, x));
}
} else {
super.resetDocument(element);
}
}
/**
* @see IWorkingCopyManager#connect(IEditorInput)
*/
public void connect(IEditorInput input) throws CoreException {
super.connect(input);
}
/**
* @see IWorkingCopyManager#disconnect(IEditorInput)
*/
public void disconnect(IEditorInput input) {
super.disconnect(input);
}
/**
* @see IWorkingCopyManager#getWorkingCopy(Object)
*/
public ICompilationUnit getWorkingCopy(IEditorInput input) {
CompilationUnitInfo info= (CompilationUnitInfo) getElementInfo(input);
return info == null ? null : info.fCopy;
}
/**
* @see IWorkingCopyManager#shutdown
*/
public void shutdown() {
Iterator e= getConnectedElements();
while (e.hasNext())
disconnect(e.next());
}
}