package com.technophobia.substeps.document.navigation;
import static com.technophobia.substeps.FeatureEditorPlugin.instance;
import static com.technophobia.substeps.document.navigation.SubstepsFileUtils.outputPaths;
import static com.technophobia.substeps.document.navigation.SubstepsFileUtils.searchForFile;
import java.io.File;
import java.net.URI;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import com.technophobia.substeps.FeatureEditorPlugin;
import com.technophobia.substeps.editor.SubstepsEditor;
import com.technophobia.substeps.model.ParentStep;
/**
* @author rpopple
*
*/
public class OpenSubstepsEditor {
private static final String SUBSTEPS_EDITOR_KEY = "com.technophobia.substeps.editor.substepsEditor";
public static void open(final IWorkbenchPage page, final IJavaProject project, final ParentStep parentStep) {
final IFile substepsIFile = substepIFile(project, parentStep.getParent().getSource());
final int lineNumber = parentStep.getSourceLineNumber();
instance().info(
"parentStep.getSourceLineNumber: " + lineNumber + " for line: " + parentStep.getParent().getLine());
final IEditorInput input = new FileEditorInput(substepsIFile);
try {
final IEditorPart substepsEditor = page.openEditor(input, SUBSTEPS_EDITOR_KEY);
selectLineInEditor(lineNumber, substepsEditor);
} catch (final PartInitException e) {
FeatureEditorPlugin.instance().error("exception opening substep", e);
}
}
private static URI findOutputUri(IJavaProject project, IClasspathEntry entry) {
assert (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE);
try {
// The default output and the specific out will be relative if they
// exist. As an example we might have:
// "/weddriver-substeps-example/target/classes"
final IPath defaultOutputPath = project.getOutputLocation();
final IPath specificOutputPath = entry.getOutputLocation();
final IPath outputPath = specificOutputPath != null ? specificOutputPath : defaultOutputPath;
// Project path is relative too - so for example we might have:
// "/webdriver-substeps-example"
final IPath projectPath = project.getProject().getFullPath();
// Find out how may segments we match on, starting from the
// beginning. So in the example given so far we have a single
// matching segment at the start.
final int matchSegs = outputPath.matchingFirstSegments(projectPath);
// Remove the matching segments, so in the given example we have:
// "/target/classes"
final IPath removeFirstSegments = outputPath.removeFirstSegments(matchSegs);
// Now we should be able to get hold of the output IFile directory.
final IFile outputFile = project.getProject().getFile(removeFirstSegments);
// Now that we have an output IFile directory we can get hold of the
// absolute URI.For example:
// "file:/home/auser/Substeps/Code/example-substeps-project/target/classes"
return outputFile.getLocationURI();
} catch (JavaModelException e) {
final String error = "Unable to find the URI for IClasspathEntry:" + entry;
instance().error(error, e);
throw new RuntimeException(e);
}
}
private static IFile substepIFile(final IJavaProject project, final File substepDefinitionFile) {
try {
final String substepOutputFile = substepDefinitionFile.getAbsolutePath();
for (final IClasspathEntry entry : project.getRawClasspath()) {
if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
// We have an absolute path. For example:
// "file:/home/auser/Substeps/Code/example-substeps-project/target/test-classes"
final URI outputUri = findOutputUri(project, entry);
if (substepOutputFile.startsWith(outputUri.getPath())) {
// Make a relative path by removing the outputUri
// location from substepDefinitionFile absolute path. So
// for example here we might have:
// "/substeps/self-test.substeps"
final String relativePath = substepOutputFile.substring(outputUri.getPath().length());
// Get the source folder for example we have here:
// "entry.getPath(): /webdriver-substeps-example/src/test/java"
// And from this we get the source folder:
// "entry.getPath().removeFirstSegments(1): /src/test/java"
final IFolder sourceIFolder = project.getProject().getFolder(
entry.getPath().removeFirstSegments(1));
final IFile substepsIFile = sourceIFolder.getFile(relativePath);
if (substepsIFile.exists()) {
return substepsIFile;
}
}
}
}
final List<IFile> matches = searchForFile(project.getProject(), substepDefinitionFile.getName(),
outputPaths(project));
return matches.isEmpty() ? null : matches.get(0);
} catch (final JavaModelException e) {
final String error = "Unable to find the substeps IFile for File:" + substepDefinitionFile;
instance().error(error, e);
throw new RuntimeException(e);
}
}
private static void selectLineInEditor(final int lineNumber, final IEditorPart newEditor) {
final ISelectionProvider newSelectionProvider = newEditor.getEditorSite().getSelectionProvider();
final SubstepsEditor newStepEditor = (SubstepsEditor) newEditor.getAdapter(SubstepsEditor.class);
final IDocument newDocument = newStepEditor.getCurrentDocument();
try {
// this is zero based
final IRegion lineInformation = newDocument.getLineInformation(lineNumber - 1);
final int newOffset = lineInformation.getOffset();
final int selectionLength = lineInformation.getLength();
newSelectionProvider.setSelection(new TextSelection(newDocument, newOffset, selectionLength));
} catch (final BadLocationException e) {
FeatureEditorPlugin.instance().error("BadLocationException@ " + lineNumber, e);
}
}
}