Java tutorial
/** * ***************************************************************************** Copyright (c) 2017 * Red Hat, Inc. 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 * * <p>Contributors: Red Hat, Inc. - initial API and implementation * ***************************************************************************** */ package org.eclipse.che.ide.console; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.nullToEmpty; import com.google.gwt.user.client.Timer; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.che.api.promises.client.Function; import org.eclipse.che.api.promises.client.FunctionException; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.editor.EditorAgent; import org.eclipse.che.ide.api.editor.EditorPartPresenter; import org.eclipse.che.ide.api.editor.OpenEditorCallbackImpl; import org.eclipse.che.ide.api.editor.document.Document; import org.eclipse.che.ide.api.editor.text.LinearRange; import org.eclipse.che.ide.api.editor.text.TextPosition; import org.eclipse.che.ide.api.editor.texteditor.TextEditor; import org.eclipse.che.ide.api.resources.Container; import org.eclipse.che.ide.api.resources.File; import org.eclipse.che.ide.api.resources.Resource; import org.eclipse.che.ide.resource.Path; /** * Default customizer adds an anchor link to the lines that match a stack trace line pattern and * installs a handler function for the link. The handler parses the stack trace line, searches for * the candidate Java files to navigate to, opens the first file (of the found candidates) in editor * and reveals it to the required line according to the stack trace line information * * @author Victor Rubezhny */ public abstract class AbstractOutputCustomizer implements OutputCustomizer { protected AppContext appContext; protected EditorAgent editorAgent; public AbstractOutputCustomizer(AppContext appContext, EditorAgent editorAgent) { this.appContext = appContext; this.editorAgent = editorAgent; } /* * (non-Javadoc) * * @see org.eclipse.che.ide.extension.machine.client.outputspanel.console. * OutputCustomizer#canCustomize(java.lang.String) */ @Override public abstract boolean canCustomize(String text); /* * (non-Javadoc) * * @see org.eclipse.che.ide.extension.machine.client.outputspanel.console. * OutputCustomizer#customize(java.lang.String) */ @Override public abstract String customize(String text); /* * Returns the list of workspace files filtered by a relative path */ protected Promise<List<File>> collectChildren(Container root, Path relativeFilePath) { return root.getTree(-1).then(new Function<Resource[], List<File>>() { @Override public List<File> apply(Resource[] children) throws FunctionException { return Stream.of(children) .filter(child -> child.isFile() && endsWith(child.asFile().getLocation(), relativeFilePath)) .map(Resource::asFile).collect(Collectors.toList()); } }); } /* * Checks if a path's last segments are equal to the provided relative path */ protected boolean endsWith(Path path, Path relativePath) { checkNotNull(path); checkNotNull(relativePath); if (path.segmentCount() < relativePath.segmentCount()) return false; for (int i = relativePath.segmentCount() - 1, j = path.segmentCount() - 1; i >= 0; i--, j--) { if (!nullToEmpty(relativePath.segment(i)).equals(path.segment(j))) { return false; } } return true; } /** * Finds a file by its path, opens it in editor and sets the text selection and reveals according * to the specified line and column numbers * * @param file * @param lineNumber * @param columnNumber */ protected void openFileInEditorAndReveal(AppContext appContext, EditorAgent editorAgent, Path file, final int lineNumber, final int columnNumber) { appContext.getWorkspaceRoot().getFile(file).then(optional -> { if (optional.isPresent()) { editorAgent.openEditor(optional.get(), new OpenEditorCallbackImpl() { @Override public void onEditorOpened(EditorPartPresenter editor) { Timer t = new Timer() { @Override public void run() { EditorPartPresenter editorPart = editorAgent.getActiveEditor(); selectRange(editorPart, lineNumber, columnNumber); } }; t.schedule(500); } @Override public void onEditorActivated(EditorPartPresenter editor) { selectRange(editor, lineNumber, columnNumber); } }); } }); } /** * Selects and shows the specified line and column of text in editor * * @param editor * @param line * @param column */ protected void selectRange(EditorPartPresenter editor, int line, int column) { line--; column--; if (line < 0) line = 0; if (editor instanceof TextEditor) { Document document = ((TextEditor) editor).getDocument(); LinearRange selectionRange = document.getLinearRangeForLine(line); if (column >= 0) { selectionRange = LinearRange.createWithStart(selectionRange.getStartOffset() + column).andLength(0); } document.setSelectedRange(selectionRange, true); document.setCursorPosition(new TextPosition(line, column >= 0 ? column : 0)); } } }