blob: 0e82ab1f5907f2f886d361c91457ae884da40c57 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.client.ui.editor;
import com.google.common.collect.Sets;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.mylyn.docs.intent.client.ui.IntentEditorActivator;
import org.eclipse.mylyn.docs.intent.client.ui.editor.annotation.IntentAnnotationModelManager;
import org.eclipse.mylyn.docs.intent.client.ui.editor.annotation.image.AbstractIntentImageAnnotation;
import org.eclipse.mylyn.docs.intent.client.ui.editor.annotation.image.IntentImageAnnotationDisposer;
import org.eclipse.mylyn.docs.intent.client.ui.editor.scanner.IntentPartitionScanner;
import org.eclipse.mylyn.docs.intent.client.ui.logger.IntentUiLogger;
import org.eclipse.mylyn.docs.intent.client.ui.repositoryconnection.EditorElementListAdapter;
import org.eclipse.mylyn.docs.intent.collab.common.logger.IIntentLogger.LogType;
import org.eclipse.mylyn.docs.intent.collab.common.logger.IntentLogger;
import org.eclipse.mylyn.docs.intent.collab.common.query.IntentDocumentQuery;
import org.eclipse.mylyn.docs.intent.collab.handlers.ReadWriteRepositoryObjectHandler;
import org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient;
import org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryObjectHandler;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.IntentCommand;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.ReadOnlyException;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.SaveException;
import org.eclipse.mylyn.docs.intent.collab.handlers.impl.ReadOnlyRepositoryObjectHandlerImpl;
import org.eclipse.mylyn.docs.intent.collab.handlers.impl.ReadWriteRepositoryObjectHandlerImpl;
import org.eclipse.mylyn.docs.intent.collab.handlers.impl.notification.elementList.ElementListAdapter;
import org.eclipse.mylyn.docs.intent.collab.handlers.impl.notification.elementList.ElementListNotificator;
import org.eclipse.mylyn.docs.intent.collab.handlers.impl.notification.typeListener.TypeNotificator;
import org.eclipse.mylyn.docs.intent.collab.handlers.notification.Notificator;
import org.eclipse.mylyn.docs.intent.collab.handlers.notification.RepositoryChangeNotification;
import org.eclipse.mylyn.docs.intent.collab.repository.Repository;
import org.eclipse.mylyn.docs.intent.compare.IntentASTMerger;
import org.eclipse.mylyn.docs.intent.compare.MergingException;
import org.eclipse.mylyn.docs.intent.core.compiler.CompilationStatus;
import org.eclipse.mylyn.docs.intent.core.compiler.CompilationStatusManager;
import org.eclipse.mylyn.docs.intent.core.compiler.CompilationStatusSeverity;
import org.eclipse.mylyn.docs.intent.core.compiler.CompilerPackage;
import org.eclipse.mylyn.docs.intent.core.document.IntentDocument;
import org.eclipse.mylyn.docs.intent.core.document.IntentGenericElement;
import org.eclipse.mylyn.docs.intent.core.document.IntentStructuredElement;
import org.eclipse.mylyn.docs.intent.core.document.UnitInstruction;
import org.eclipse.mylyn.docs.intent.core.modelingunit.ExternalContentReference;
import org.eclipse.mylyn.docs.intent.core.query.IntentHelper;
import org.eclipse.mylyn.docs.intent.markup.markup.Image;
import org.eclipse.mylyn.docs.intent.parser.IntentParser;
import org.eclipse.mylyn.docs.intent.parser.modelingunit.ParseException;
import org.eclipse.mylyn.docs.intent.serializer.ParsedElementPosition;
import org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner;
import org.eclipse.ui.texteditor.AbstractDocumentProvider;
/**
* DocumentProvider for the IntentDocument documents.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
* @author <a href="mailto:william.piers@obeo.fr">William Piers</a>
*/
// Suppress Warnings added for using WorkspaceOperationRunner
@SuppressWarnings("restriction")
public class IntentDocumentProvider extends AbstractDocumentProvider implements RepositoryClient {
/**
* The repository to use for creating and closing GET and POST connections.
*/
private Repository repository;
/**
* The repository object handler managing the notifications related to the handled elements and allowing
* to save the elements on the repository.
*/
private RepositoryObjectHandler listenedElementsHandler;
/**
* Root for the handled document.
*/
private EObject documentRoot;
/** The operation runner. */
private WorkspaceOperationRunner fOperationRunner;
/**
* The editor associated to this document provider.
*/
private IntentEditor associatedEditor;
/**
* The AnnotatioModelManager.
*/
private IntentAnnotationModelManager annotationModelManager;
/**
* Represents the last createdDocument.
*/
private IntentEditorDocument createdDocument;
/**
* Represents the partitioner used to identify the partitions of the document.
*/
private IDocumentPartitioner partitioner;
/**
* A flag indicating whether the current document has syntax errors or not.
*/
private boolean hasSyntaxErrors;
/**
* An internal {@link Job} used to save the document in non-UI thread.
*/
private SaveIntentDocumentJob saveJob;
/**
* IntentDocumentProvider constructor.
*
* @param editor
* the editor associated to this document Provider
*/
public IntentDocumentProvider(IntentEditor editor) {
this.associatedEditor = editor;
this.annotationModelManager = new IntentAnnotationModelManager();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#canSaveDocument(java.lang.Object)
*/
@Override
public boolean canSaveDocument(Object element) {
return hasSyntaxErrors || super.canSaveDocument(element);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#createAnnotationModel(java.lang.Object)
*/
@Override
protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
// We use an AnnotationModelManager to handle the create annotationModel
Assert.isNotNull(annotationModelManager);
// Step 1: create annotations for all compilation statuses
for (CompilationStatus status : IntentHelper.getAllStatus((IntentGenericElement)documentRoot)) {
// We use the annotationModelManager to create annotations
ParsedElementPosition posit = createdDocument.getIntentPosition(status.getTarget());
if (posit == null) {
posit = new ParsedElementPosition(0, 0);
}
if (!status.getSeverity().equals(CompilationStatusSeverity.INFO)) {
annotationModelManager.addAnnotationFromStatus(
this.listenedElementsHandler.getRepositoryAdapter(), status,
new Position(posit.getOffset(), posit.getDeclarationLength()));
}
}
// Step 2: create annotations for all ExternalContentReferences
for (ExternalContentReference reference : IntentHelper.getAllContainedElements(
ExternalContentReference.class, (IntentGenericElement)documentRoot)) {
annotationModelManager.updateAnnotationFromElementToRender(reference,
createdDocument.getIntentPosition(reference));
}
// Step 3: create annotations for all images links
for (Image imageLink : IntentHelper.getAllContainedElements(Image.class,
(IntentGenericElement)documentRoot)) {
annotationModelManager.updateAnnotationFromElementToRender(imageLink,
createdDocument.getIntentPosition(imageLink));
}
annotationModelManager.getAnnotationModel().addAnnotationModelListener(
new IntentImageAnnotationDisposer());
return annotationModelManager.getAnnotationModel();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getAnnotationModel(java.lang.Object)
*/
@Override
public IAnnotationModel getAnnotationModel(Object element) {
return annotationModelManager.getAnnotationModel();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#createDocument(java.lang.Object)
*/
@Override
protected IDocument createDocument(Object element) throws CoreException {
if (!(element instanceof IntentEditorInput)) {
IStatus status = new Status(IStatus.ERROR, IntentEditorActivator.PLUGIN_ID,
"Cannot open an Intent editor on a document of type "
+ element.getClass().getCanonicalName() + " (must be IntentEditorInput) ");
throw new CoreException(status);
}
if (((IntentEditorInput)element).getRepository() == null) {
IStatus status = new Status(IStatus.ERROR, IntentEditorActivator.PLUGIN_ID,
"Cannot open Intent editor : document is not available.");
throw new CoreException(status);
}
setRepository(((IntentEditorInput)element).getRepository());
// We obtain the root of the document
documentRoot = ((IntentEditorInput)element).getIntentElement();
// TODO check for notifications issues:
// the following command was added to avoid infinite loop caused by the fact that the serialization
// occurs during the repository first compilation.
((IntentEditorInput)element).getRepositoryAdapter().execute(new IntentCommand() {
public void execute() {
createdDocument = new IntentEditorDocument(documentRoot, associatedEditor);
}
});
if (createdDocument != null) {
partitioner = new FastPartitioner(new IntentPartitionScanner(),
IntentPartitionScanner.LEGAL_CONTENT_TYPES);
partitioner.connect(createdDocument);
createdDocument.setDocumentPartitioner(partitioner);
subscribeRepository(((IntentEditorInput)element).getRepositoryAdapter());
}
return createdDocument;
}
/**
* Registers listeners in the repository used by the given editor input.
*
* @param repositoryAdapter
* the repository adapter previously created by the editorInput
*/
private void subscribeRepository(RepositoryAdapter repositoryAdapter) {
// Step 1 : creation of the Handler in the correct mode
final RepositoryObjectHandler elementHandler = createElementHandler(repositoryAdapter, false);
addRepositoryObjectHandler(elementHandler);
// Step 2 : creation of a Notificator listening changes on this element and compilation
// errors.
final Set<EObject> listenedObjects = new LinkedHashSet<EObject>();
listenedObjects.add(new IntentDocumentQuery(repositoryAdapter).getOrCreateIntentDocument());
final ElementListAdapter adapter = new EditorElementListAdapter();
Notificator listenedElementsNotificator = new ElementListNotificator(listenedObjects, adapter,
repositoryAdapter);
Notificator compilationStatusNotificator = new TypeNotificator(
Sets.newLinkedHashSet(CompilerPackage.eINSTANCE.getCompilationStatusManager()
.getEAllStructuralFeatures()));
elementHandler.addNotificator(listenedElementsNotificator);
elementHandler.addNotificator(compilationStatusNotificator);
}
/**
* Creates the element handler matching the given mode.
*
* @param repositoryAdapter
* the repository adapter
* @param readOnlyMode
* the access mode
* @return the handler
*/
private static RepositoryObjectHandler createElementHandler(RepositoryAdapter repositoryAdapter,
boolean readOnlyMode) {
boolean isReadOnly = readOnlyMode;
RepositoryObjectHandler elementHandler = null;
if (!isReadOnly) {
try {
elementHandler = new ReadWriteRepositoryObjectHandlerImpl(repositoryAdapter);
} catch (ReadOnlyException e) {
IntentLogger
.getInstance()
.log(LogType.WARNING,
"The Intent Editor has insufficient rights (read-only) to save modifications on the repository. A read-only context will be used instead.");
isReadOnly = true;
}
}
if (isReadOnly) {
elementHandler = new ReadOnlyRepositoryObjectHandlerImpl();
elementHandler.setRepositoryAdapter(repositoryAdapter);
}
return elementHandler;
}
/**
* Refreshes the outline View.
*
* @param newAST
* the newAST to base the outline on
*/
public void refreshOutline(EObject newAST) {
associatedEditor.refreshOutlineView(newAST);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(org.eclipse.core.runtime.IProgressMonitor,
* java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
*/
@Override
protected void doSaveDocument(IProgressMonitor monitor, Object element, final IDocument document,
boolean overwrite) throws CoreException {
if (document instanceof IntentEditorDocument) {
// Disabling edition on the document until it gets saved
((IntentEditorDocument)document).setIsBeingSaved(true);
this.associatedEditor.updateReadOnlyMode();
if (saveJob != null) {
saveJob.cancel();
}
// Launch a save job (in non-UI thread)
saveJob = new SaveIntentDocumentJob((IntentEditorDocument)document);
saveJob.schedule();
}
}
/**
* Merges the document content according to the given AST.
*
* @param document
* the document
* @param localAST
* the AST
*/
private void merge(final IntentEditorDocument document, final EObject localAST) {
// Then we try to merge the parsed AST with the old one
final IntentASTMerger merger = new IntentASTMerger();
boolean mustUndo = false;
try {
final EObject remoteAST = (EObject)document.getAST();
try {
if (localAST != null && remoteAST != null && localAST.eClass().equals(remoteAST.eClass())) {
merger.mergeFromLocalToRepository(localAST, remoteAST);
} else {
this.createSyntaxErrorAnnotation("Unrecognized content: unable to merge "
+ localAST.eClass().getName() + " with " + remoteAST.eClass().getName() + ".", 0,
document.getLength());
}
} catch (MergingException e) {
mustUndo = true;
IntentUiLogger.logError(e);
}
} catch (NullPointerException npe) { // FIXME catch NPE ??
mustUndo = true;
IntentUiLogger.logError(npe);
}
if (mustUndo) {
try {
((ReadWriteRepositoryObjectHandler)listenedElementsHandler).undo();
} catch (ReadOnlyException e) {
IntentUiLogger.logError(e);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#isModifiable(java.lang.Object)
*/
@Override
public boolean isModifiable(Object element) {
boolean isModifiable = true;
if (element instanceof IntentEditorDocument) {
isModifiable = !((IntentEditorDocument)element).isBeingSaved();
} else if (this.createdDocument != null) {
isModifiable = !this.createdDocument.isBeingSaved();
}
return isModifiable;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#isReadOnly(java.lang.Object)
*/
@Override
public boolean isReadOnly(Object element) {
boolean isReadOnly = true;
if (element instanceof IntentEditorDocument) {
isReadOnly = ((IntentEditorDocument)element).isBeingSaved();
} else if (this.createdDocument != null) {
isReadOnly = this.createdDocument.isBeingSaved();
}
return isReadOnly;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getOperationRunner(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
if (fOperationRunner == null) {
fOperationRunner = new WorkspaceOperationRunner();
}
fOperationRunner.setProgressMonitor(monitor);
return fOperationRunner;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient#handleChangeNotification(org.eclipse.mylyn.docs.intent.collab.handlers.notification.RepositoryChangeNotification)
*/
public void handleChangeNotification(RepositoryChangeNotification notification) {
// If the received notification indicates the deletion of the root of the associated document
if (handleRootHasBeenDeleted(notification)) {
return;
}
// For each object modified indicated by this notification
for (EObject modifiedObject : notification.getImpactedElements()) {
// For all documents that have been opened on this object
if (modifiedObject.equals(new IntentDocumentQuery(listenedElementsHandler.getRepositoryAdapter())
.getOrCreateIntentDocument())) {
handleContentHasChanged(modifiedObject);
} else {
// update annotations (if the compilation status manager has changed)
handleCompilationStatusHasChanged(modifiedObject);
// refreshing images
for (ExternalContentReference reference : IntentHelper.getAllContainedElements(
ExternalContentReference.class, (IntentGenericElement)documentRoot)) {
annotationModelManager.updateAnnotationFromElementToRender(reference,
createdDocument.getIntentPosition(reference));
}
for (Image imageLink : IntentHelper.getAllContainedElements(Image.class,
(IntentGenericElement)documentRoot)) {
annotationModelManager.updateAnnotationFromElementToRender(
imageLink,
createdDocument.getIntentPosition(imageLink.eContainer().eContainer()
.eContainer()));
}
}
}
}
/**
* Update the annotation model by translating each compilationStatus associated to the given element as an
* Annotation.
*
* @param modifiedElement
* the element to use for updating the AnnotationModel (children will also be updated)
* @param relatedDocument
* the document to use for obtaining informations about element positions
*/
private void updateAnnotationModelFromCompilationStatusAndChildren(IntentGenericElement modifiedElement,
IntentEditorDocument relatedDocument) {
// Update the root
updateAnnotationModelFromCompilationStatus(modifiedElement, relatedDocument);
// And all children
TreeIterator<EObject> eAllContents = modifiedElement.eAllContents();
while (eAllContents.hasNext()) {
EObject next = eAllContents.next();
if (next instanceof IntentGenericElement) {
updateAnnotationModelFromCompilationStatus((IntentGenericElement)next, relatedDocument);
}
}
}
/**
* Update the annotation model by translating each compilationStatus associated to the given element as an
* Annotation.
*
* @param modifiedElement
* the element to use for updating the AnnotationModel
* @param relatedDocument
* the document to use for obtaining informations about element positions
*/
private void updateAnnotationModelFromCompilationStatus(IntentGenericElement modifiedElement,
IntentEditorDocument relatedDocument) {
// Step 1 : removing all the invalid compilation status relative to the modifiedElement
annotationModelManager.removeInvalidCompilerAnnotations(
this.listenedElementsHandler.getRepositoryAdapter(), modifiedElement);
// Step 2 : updating the concerned documents
for (CompilationStatus statusToAdd : modifiedElement.getCompilationStatus()) {
// Step 2.1 : we determine the position of the annotation to create by
// using the informations hold by the IntentDocument.
ParsedElementPosition parsedElementPosition = relatedDocument.getIntentPosition(statusToAdd
.getTarget());
if (parsedElementPosition == null) {
parsedElementPosition = new ParsedElementPosition(0, 0);
}
Position position = new Position(parsedElementPosition.getOffset(),
parsedElementPosition.getDeclarationLength());
if (!statusToAdd.getSeverity().equals(CompilationStatusSeverity.INFO)) {
// Step 2.2 : Adding this annotation to the model (will update overview and vertical rulers of
// the editor)
annotationModelManager.addAnnotationFromStatus(
this.listenedElementsHandler.getRepositoryAdapter(), statusToAdd, position);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient#addRepositoryObjectHandler(org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryObjectHandler)
*/
public void addRepositoryObjectHandler(RepositoryObjectHandler handler) {
handler.addClient(this);
listenedElementsHandler = handler;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient#removeRepositoryObjectHandler(org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryObjectHandler)
*/
public void removeRepositoryObjectHandler(RepositoryObjectHandler handler) {
handler.removeClient(this);
listenedElementsHandler = null;
}
/**
* Returns the RepositoryObjectHandler associated to this document provider.
*
* @return the listenedElementsHandler associated to this document provider
*/
public RepositoryObjectHandler getListenedElementsHandler() {
return listenedElementsHandler;
}
/**
* Sets the repository to use for saving and closing getConnexion.
*
* @param repository
* the repository to use for saving and closing getConnexion
*/
public void setRepository(Repository repository) {
this.repository = repository;
this.repository.register(this);
}
/**
* Returns the repository to use for saving and closing getConnexion.
*
* @return the repository to use for saving and closing getConnexion
*/
public Repository getRepository() {
return repository;
}
/**
* Unregister from the repository, the connection and the handler used by this document provider.
*/
public void close() {
if (this.repository != null) {
// TODO ??? at this time cause project explorer desynchronization. Repository is saved anyway
// // If the editor is editable, we undo all the unsaved modifications
// if (this.associatedEditor.isEditable()) {
// try {
// this.listenedElementsHandler.getRepositoryAdapter().undo();
// } catch (ReadOnlyException e) {
// // The readOnly property has already been tested by calling isEditable.
// }
// }
this.repository.unregister(this);
}
if (this.listenedElementsHandler != null) {
this.listenedElementsHandler.getRepositoryAdapter().closeContext();
this.listenedElementsHandler.removeClient(this);
this.listenedElementsHandler.stop();
}
/*
* Dispose images create through IntentImageAnnotations
*/
Iterator<?> annotationIterator = annotationModelManager.getAnnotationModel().getAnnotationIterator();
while (annotationIterator.hasNext()) {
Object annotation = annotationIterator.next();
if (annotation instanceof AbstractIntentImageAnnotation) {
IntentImageAnnotationDisposer.disposeImage((AbstractIntentImageAnnotation)annotation);
}
}
}
/**
* Creates a syntax error annotation at the given offset, of the given length.
*
* @param message
* the message associated to this syntax error
* @param offset
* offset of the syntax error annotation
* @param length
* length of the syntax error annotation.
*/
public void createSyntaxErrorAnnotation(String message, int offset, int length) {
this.annotationModelManager.createSyntaxErrorAnnotation(message, offset, length);
}
/**
* Removes all the syntax error annotations from the managed annotation model.
*/
public void removeSyntaxErrors() {
this.annotationModelManager.removeSyntaxErrorsAnnotations();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient#dispose()
*/
public void dispose() {
listenedElementsHandler.removeClient(this);
listenedElementsHandler = null;
}
/**
* Handles the fact that a root has been deleted.
*
* @param notification
* the root deletion notification
* @return true if a root has been deleted
*/
private boolean handleRootHasBeenDeleted(RepositoryChangeNotification notification) {
if (notification.getImpactedElements().size() < 1) {
createdDocument.unsynchronize();
return true;
}
return false;
}
/**
* Handles the fact that a compilation status has changed.
*
* @param modifiedObject
* the compilation status manager
*/
private void handleCompilationStatusHasChanged(EObject modifiedObject) {
if (modifiedObject instanceof CompilationStatusManager) {
updateAnnotationModelFromCompilationStatusAndChildren((IntentGenericElement)documentRoot,
createdDocument);
}
}
/**
* Handles the fact that the content has changed.
*
* @param modifiedObject
* the modified object
*/
private void handleContentHasChanged(EObject modifiedObject) {
if (modifiedObject instanceof IntentStructuredElement || modifiedObject instanceof UnitInstruction) {
EObject newDocumentRoot = modifiedObject;
if (!(documentRoot instanceof IntentDocument)) {
// Get the new version of the documentRoot
URI oldDocumentRootURI = EcoreUtil.getURI(documentRoot);
String oldDocumentRootFragment = null;
if (oldDocumentRootURI != null) {
oldDocumentRootFragment = oldDocumentRootURI.fragment();
}
if (oldDocumentRootFragment != null) {
try {
newDocumentRoot = modifiedObject.eResource().getEObject(oldDocumentRootFragment);
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
// Silent catch : the modifiedObject will be used as new root
}
}
}
documentRoot = newDocumentRoot;
createdDocument.setAST(newDocumentRoot);
createdDocument.reloadFromAST();
// In any case, we launch the syntax coloring
partitioner.computePartitioning(0, 1);
// Finally, we refresh the outline
refreshOutline(documentRoot);
}
}
/**
* Internal job used to save the editor in non-UI thread.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
private final class SaveIntentDocumentJob extends Job {
/**
* Job name.
*/
private static final String SAVE_INTENT_DOCUMENT_JOB_NAME = "Save Intent editor";
/**
* The {@link IntentEditorDocument} to save.
*/
private IntentEditorDocument document;
/**
* Default constructor.
*
* @param document
* the {@link IntentEditorDocument} to save
*/
public SaveIntentDocumentJob(IntentEditorDocument document) {
super(SAVE_INTENT_DOCUMENT_JOB_NAME);
this.document = document;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
final EObject localAST;
try {
hasSyntaxErrors = false;
removeSyntaxErrors();
String rootCompleteLevel = null;
if (documentRoot instanceof IntentStructuredElement) {
rootCompleteLevel = ((IntentStructuredElement)documentRoot).getCompleteLevel();
}
localAST = new IntentParser().parse(document.get(), rootCompleteLevel);
associatedEditor.refreshTitle(localAST);
final RepositoryAdapter repositoryAdapter = listenedElementsHandler.getRepositoryAdapter();
repositoryAdapter.execute(new IntentCommand() {
public void execute() {
try {
merge((IntentEditorDocument)document, localAST);
((IntentEditorDocument)document).reloadFromAST(true);
repositoryAdapter.save();
} catch (ReadOnlyException e) {
IntentUiLogger.logError(e);
} catch (SaveException e) {
IntentUiLogger.logError(e);
}
}
});
} catch (ParseException e) {
createSyntaxErrorAnnotation(e.getMessage(), e.getErrorOffset(), e.getErrorLength());
hasSyntaxErrors = true;
}
((IntentEditorDocument)document).setIsBeingSaved(false);
associatedEditor.updateReadOnlyMode();
return Status.OK_STATUS;
}
}
}