/*******************************************************************************
* Copyright (c) 2009 R.Dvorak and others.
* 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:
* Radek Dvorak - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.debug.ui;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.m2m.internal.qvt.oml.common.util.LineNumberProvider;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtEditor;
import org.eclipse.m2m.qvt.oml.debug.core.vm.ValidBreakpointLocator;
import org.eclipse.ocl.utilities.ASTNode;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IEditorStatusLine;
class BreakpointLocationVerifier {
private static LineNumberProvider getLineNumberProvider(final IDocument doc) {
return new LineNumberProvider() {
public int getLineNumber(int offset) {
try {
return doc.getLineOfOffset(offset) + 1;
} catch (BadLocationException e) {
return -1;
}
}
public int getLineEnd(int lineNumber) {
try {
IRegion lineInfo = doc.getLineInformation(lineNumber);
return lineInfo.getOffset() + lineInfo.getLength();
} catch (BadLocationException e) {
return -1;
}
}
public int getLineCount() {
return doc.getNumberOfLines();
}
};
}
private static final int GET_AST_TIMEOUT = 10 * 1000;
private final ILineBreakpoint fBreakpoint;
private final QvtEditor fEditor;
private final String fInvalidLocationMessage;
BreakpointLocationVerifier(QvtEditor editor, ILineBreakpoint breakpoint, String invalidLocationMessage) {
if(editor == null || breakpoint == null || invalidLocationMessage == null) {
throw new IllegalArgumentException();
}
fEditor = editor;
fBreakpoint = breakpoint;
fInvalidLocationMessage = invalidLocationMessage;
}
IStatus run() {
IStatus status = checkBreakpointableElements();
if(!status.isOK()) {
if (fBreakpoint != null) {
try {
DebugPlugin.getDefault().getBreakpointManager().removeBreakpoint(fBreakpoint, true);
} catch (CoreException e) {
QVTODebugUIPlugin.log(e.getStatus());
}
}
}
return status;
}
private IStatus checkBreakpointableElements() {
int lineNumber;
try {
lineNumber = fBreakpoint.getLineNumber();
} catch (CoreException e) {
return e.getStatus();
}
IDocumentProvider docProvider = fEditor.getDocumentProvider();
if(docProvider == null) {
return canceled();
}
IDocument doc = docProvider.getDocument(fEditor.getEditorInput());
if(doc == null) {
return canceled();
}
CompiledUnit compilationUnit = fEditor.getValidCompiledModule(GET_AST_TIMEOUT);
if(compilationUnit == null) {
return QVTODebugUIPlugin.createErrorStatus("Failed to obtain AST"); //$NON-NLS-1$
}
List<ASTNode> elements = ValidBreakpointLocator
.getBreakpointableElementsForLine(compilationUnit,
getLineNumberProvider(doc), lineNumber);
if(elements.isEmpty()) {
report(NLS.bind(fInvalidLocationMessage, new Integer(lineNumber)));
return canceled();
}
return Status.OK_STATUS;
}
/**
* Reports any status to the current active workbench shell
* @param message the message to display
*/
protected void report(final String message) {
QVTODebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
public void run() {
IEditorStatusLine statusLine = (IEditorStatusLine) fEditor.getAdapter(IEditorStatusLine.class);
if (statusLine != null) {
statusLine.setMessage(true, message, null);
}
if (message != null && QVTODebugUIPlugin.getActiveWorkbenchShell() != null) {
Display.getCurrent().beep();
}
}
});
}
private IStatus canceled() {
return QVTODebugUIPlugin.createStatus(IStatus.CANCEL, fInvalidLocationMessage);
}
}