/*******************************************************************************
* Copyright (c) 2012-2016 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.ext.java.client.editor;
import com.google.gwt.user.client.Timer;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
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.project.node.HasStorablePath;
import org.eclipse.che.ide.api.project.node.Node;
import org.eclipse.che.ide.api.project.tree.VirtualFile;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.project.node.JavaNodeManager;
import org.eclipse.che.ide.ext.java.client.projecttree.JavaSourceFolderUtil;
import org.eclipse.che.ide.ext.java.shared.OpenDeclarationDescriptor;
import org.eclipse.che.ide.jseditor.client.text.LinearRange;
import org.eclipse.che.ide.jseditor.client.texteditor.EmbeddedTextEditorPresenter;
import org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter;
import org.eclipse.che.ide.project.node.FileReferenceNode;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
import org.eclipse.che.ide.rest.Unmarshallable;
import org.eclipse.che.ide.util.loging.Log;
import java.util.Map;
/**
* @author Evgen Vidolob
*/
@Singleton
public class OpenDeclarationFinder {
private final EditorAgent editorAgent;
private final JavaNavigationService navigationService;
private DtoUnmarshallerFactory factory;
private AppContext context;
private final ProjectExplorerPresenter projectExplorer;
private final JavaNodeManager javaNodeManager;
@Inject
public OpenDeclarationFinder(EditorAgent editorAgent,
JavaNavigationService navigationService,
DtoUnmarshallerFactory factory,
AppContext context,
ProjectExplorerPresenter projectExplorer,
JavaNodeManager javaNodeManager) {
this.editorAgent = editorAgent;
this.factory = factory;
this.navigationService = navigationService;
this.context = context;
this.projectExplorer = projectExplorer;
this.javaNodeManager = javaNodeManager;
}
public void openDeclaration() {
EditorPartPresenter activeEditor = editorAgent.getActiveEditor();
if (activeEditor == null) {
return;
}
if (!(activeEditor instanceof EmbeddedTextEditorPresenter)) {
Log.error(getClass(), "Open Declaration support only EmbeddedTextEditorPresenter as editor");
return;
}
EmbeddedTextEditorPresenter editor = ((EmbeddedTextEditorPresenter)activeEditor);
int offset = editor.getCursorOffset();
final VirtualFile file = editor.getEditorInput().getFile();
Unmarshallable<OpenDeclarationDescriptor> unmarshaller =
factory.newUnmarshaller(OpenDeclarationDescriptor.class);
navigationService
.findDeclaration(file.getProject().getProjectConfig().getPath(), JavaSourceFolderUtil.getFQNForFile(file), offset,
new AsyncRequestCallback<OpenDeclarationDescriptor>(unmarshaller) {
@Override
protected void onSuccess(OpenDeclarationDescriptor result) {
if (result != null) {
handleDescriptor(result);
}
}
@Override
protected void onFailure(Throwable exception) {
Log.error(OpenDeclarationFinder.class, exception);
}
});
}
private void handleDescriptor(final OpenDeclarationDescriptor descriptor) {
Map<String, EditorPartPresenter> openedEditors = editorAgent.getOpenedEditors();
for (String s : openedEditors.keySet()) {
if (descriptor.getPath().equals(s)) {
EditorPartPresenter editorPartPresenter = openedEditors.get(s);
editorAgent.activateEditor(editorPartPresenter);
fileOpened(editorPartPresenter, descriptor.getOffset());
return;
}
}
if (descriptor.isBinary()) {
javaNodeManager.getClassNode(context.getCurrentProject().getProjectConfig(), descriptor.getLibId(), descriptor.getPath())
.then(new Operation<Node>() {
@Override
public void apply(Node node) throws OperationException {
if (node instanceof VirtualFile) {
openFile((VirtualFile)node, descriptor);
}
}
});
} else {
projectExplorer.getNodeByPath(new HasStorablePath.StorablePath(descriptor.getPath()))
.then(selectNode())
.then(openNode(descriptor));
}
}
protected Function<Node, Node> selectNode() {
return new Function<Node, Node>() {
@Override
public Node apply(Node node) throws FunctionException {
projectExplorer.select(node, false);
return node;
}
};
}
protected Function<Node, Node> openNode(final OpenDeclarationDescriptor descriptor) {
return new Function<Node, Node>() {
@Override
public Node apply(Node node) throws FunctionException {
if (node instanceof FileReferenceNode) {
openFile((VirtualFile)node, descriptor);
}
return node;
}
};
}
private void openFile(VirtualFile result, final OpenDeclarationDescriptor descriptor) {
final Map<String, EditorPartPresenter> openedEditors = editorAgent.getOpenedEditors();
Log.info(getClass(), result.getPath());
if (openedEditors.containsKey(result.getPath())) {
EditorPartPresenter editorPartPresenter = openedEditors.get(result.getPath());
editorAgent.activateEditor(editorPartPresenter);
fileOpened(editorPartPresenter, descriptor.getOffset());
} else {
editorAgent.openEditor(result, new EditorAgent.OpenEditorCallback() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
fileOpened(editor, descriptor.getOffset());
}
});
}
}
private void fileOpened(final EditorPartPresenter editor, final int offset) {
new Timer() { //in some reason we need here timeout otherwise it not work cursor don't set to correct position
@Override
public void run() {
if (editor instanceof EmbeddedTextEditorPresenter) {
((EmbeddedTextEditorPresenter)editor).getDocument().setSelectedRange(
LinearRange.createWithStart(offset).andLength(0), true);
}
}
}.schedule(100);
}
}