org.eclipse.che.ide.console.AbstractOutputCustomizer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.ide.console.AbstractOutputCustomizer.java

Source

/**
 * ***************************************************************************** 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));
        }
    }
}