blob: 4d17dea2bf6dd630ad13203c00efc4ddb265a0a3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.internal.corext.refactoring.base;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.dltk.internal.corext.util.Messages;
import org.eclipse.dltk.internal.corext.util.Resources;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
/**
* DLTK specific change object.
*/
public abstract class DLTKChange extends Change {
private long fModificationStamp;
private boolean fReadOnly;
private static class ValidationState {
private IResource fResource;
private int fKind;
private boolean fDirty;
private boolean fReadOnly;
private long fModificationStamp;
private ITextFileBuffer fTextFileBuffer;
public static final int RESOURCE = 1;
public static final int DOCUMENT = 2;
public ValidationState(IResource resource) {
fResource = resource;
if (resource instanceof IFile) {
initializeFile((IFile) resource);
} else {
initializeResource(resource);
}
}
public void checkDirty(RefactoringStatus status, long stampToMatch,
IProgressMonitor pm) throws CoreException {
if (fDirty) {
if (fKind == DOCUMENT && fTextFileBuffer != null
&& stampToMatch == fModificationStamp) {
fTextFileBuffer.commit(pm, false);
} else {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_is_unsaved,
fResource.getFullPath().toString()));
}
}
}
public void checkDirty(RefactoringStatus status) {
if (fDirty) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_is_unsaved,
fResource.getFullPath().toString()));
}
}
public void checkReadOnly(RefactoringStatus status) {
if (fReadOnly) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_is_read_only,
fResource.getFullPath().toString()));
}
}
public void checkSameReadOnly(RefactoringStatus status,
boolean valueToMatch) {
if (fReadOnly != valueToMatch) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_same_read_only,
fResource.getFullPath().toString()));
}
}
public void checkModificationStamp(RefactoringStatus status,
long stampToMatch) {
if (fKind == DOCUMENT) {
if (stampToMatch != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP
&& fModificationStamp != stampToMatch) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_has_modifications,
fResource.getFullPath().toString()));
}
} else {
if (stampToMatch != IResource.NULL_STAMP
&& fModificationStamp != stampToMatch) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_has_modifications,
fResource.getFullPath().toString()));
}
}
}
private void initializeFile(IFile file) {
fTextFileBuffer = getBuffer(file);
if (fTextFileBuffer == null) {
initializeResource(file);
} else {
IDocument document = fTextFileBuffer.getDocument();
fDirty = fTextFileBuffer.isDirty();
fReadOnly = Resources.isReadOnly(file);
if (document instanceof IDocumentExtension4) {
fKind = DOCUMENT;
fModificationStamp = ((IDocumentExtension4) document)
.getModificationStamp();
} else {
fKind = RESOURCE;
fModificationStamp = file.getModificationStamp();
}
}
}
private void initializeResource(IResource resource) {
fKind = RESOURCE;
fDirty = false;
fReadOnly = Resources.isReadOnly(resource);
fModificationStamp = resource.getModificationStamp();
}
}
protected static final int NONE = 0;
protected static final int READ_ONLY = 1 << 0;
protected static final int DIRTY = 1 << 1;
private static final int SAVE = 1 << 2;
protected static final int SAVE_IF_DIRTY = SAVE | DIRTY;
protected DLTKChange() {
fModificationStamp = IResource.NULL_STAMP;
fReadOnly = false;
}
@Override
public void initializeValidationData(IProgressMonitor pm) {
IResource resource = getResource(getModifiedElement());
if (resource != null) {
fModificationStamp = getModificationStamp(resource);
fReadOnly = Resources.isReadOnly(resource);
}
}
// protected final RefactoringStatus isValid(IProgressMonitor pm, boolean
// checkReadOnly, boolean checkDirty) throws CoreException {
protected final RefactoringStatus isValid(IProgressMonitor pm, int flags)
throws CoreException {
pm.beginTask("", 2); //$NON-NLS-1$
try {
RefactoringStatus result = new RefactoringStatus();
Object modifiedElement = getModifiedElement();
checkExistence(result, modifiedElement);
if (result.hasFatalError())
return result;
if (flags == NONE)
return result;
IResource resource = getResource(modifiedElement);
if (resource != null) {
ValidationState state = new ValidationState(resource);
state.checkModificationStamp(result, fModificationStamp);
if (result.hasFatalError())
return result;
state.checkSameReadOnly(result, fReadOnly);
if (result.hasFatalError())
return result;
if ((flags & READ_ONLY) != 0) {
state.checkReadOnly(result);
if (result.hasFatalError())
return result;
}
if ((flags & DIRTY) != 0) {
if ((flags & SAVE) != 0) {
state.checkDirty(result, fModificationStamp,
new SubProgressMonitor(pm, 1));
} else {
state.checkDirty(result);
}
}
}
return result;
} finally {
pm.done();
}
}
protected final RefactoringStatus isValid(int flags) throws CoreException {
return isValid(new NullProgressMonitor(), flags);
}
protected static void checkIfModifiable(RefactoringStatus status,
Object element, int flags) {
checkIfModifiable(status, getResource(element), flags);
}
protected static void checkIfModifiable(RefactoringStatus result,
IResource resource, int flags) {
checkExistence(result, resource);
if (result.hasFatalError())
return;
if (flags == NONE)
return;
ValidationState state = new ValidationState(resource);
if ((flags & READ_ONLY) != 0) {
state.checkReadOnly(result);
if (result.hasFatalError())
return;
}
if ((flags & DIRTY) != 0) {
state.checkDirty(result);
}
}
protected static void checkExistence(RefactoringStatus status,
Object element) {
if (element == null) {
status.addFatalError(
RefactoringCoreMessages.DynamicValidationStateChange_workspace_changed);
} else if (element instanceof IResource
&& !((IResource) element).exists()) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_does_not_exist,
((IResource) element).getFullPath().toString()));
} else if (element instanceof IModelElement
&& !((IModelElement) element).exists()) {
status.addFatalError(Messages.format(
RefactoringCoreMessages.Change_does_not_exist,
((IModelElement) element).getElementName()));
}
}
private static IResource getResource(Object element) {
if (element instanceof IResource) {
return (IResource) element;
}
if (element instanceof ISourceModule) {
return ((ISourceModule) element).getPrimary().getResource();
}
if (element instanceof IModelElement) {
return ((IModelElement) element).getResource();
}
if (element instanceof IAdaptable) {
return ((IAdaptable) element).getAdapter(IResource.class);
}
return null;
}
@Override
public String toString() {
return getName();
}
public long getModificationStamp(IResource resource) {
if (!(resource instanceof IFile))
return resource.getModificationStamp();
IFile file = (IFile) resource;
ITextFileBuffer buffer = getBuffer(file);
if (buffer == null) {
return file.getModificationStamp();
}
IDocument document = buffer.getDocument();
if (document instanceof IDocumentExtension4) {
return ((IDocumentExtension4) document).getModificationStamp();
}
return file.getModificationStamp();
}
private static ITextFileBuffer getBuffer(IFile file) {
ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
return manager.getTextFileBuffer(file.getFullPath(),
LocationKind.NORMALIZE);
}
}