/*******************************************************************************
* Copyright (c) 2012-2015 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.newsourcefile;
import org.eclipse.che.api.project.gwt.client.ProjectServiceClient;
import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.app.CurrentProject;
import org.eclipse.che.ide.api.event.FileEvent;
import org.eclipse.che.ide.api.event.ItemEvent;
import org.eclipse.che.ide.api.project.tree.TreeNode;
import org.eclipse.che.ide.api.project.tree.VirtualFile;
import org.eclipse.che.ide.api.project.tree.generic.FolderNode;
import org.eclipse.che.ide.api.project.tree.generic.ItemNode;
import org.eclipse.che.ide.api.selection.SelectionAgent;
import org.eclipse.che.ide.collections.Array;
import org.eclipse.che.ide.collections.Collections;
import org.eclipse.che.ide.ext.java.client.projecttree.nodes.PackageNode;
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.ui.dialogs.DialogFactory;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import static org.eclipse.che.ide.api.event.FileEvent.FileOperation.OPEN;
import static org.eclipse.che.ide.api.event.ItemEvent.ItemOperation.CREATED;
import static org.eclipse.che.ide.ext.java.client.JavaUtils.checkCompilationUnitName;
import static org.eclipse.che.ide.ext.java.client.JavaUtils.checkPackageName;
import static org.eclipse.che.ide.ext.java.client.JavaUtils.isValidCompilationUnitName;
import static org.eclipse.che.ide.ext.java.client.JavaUtils.isValidPackageName;
import static org.eclipse.che.ide.ext.java.client.newsourcefile.JavaSourceFileType.ANNOTATION;
import static org.eclipse.che.ide.ext.java.client.newsourcefile.JavaSourceFileType.CLASS;
import static org.eclipse.che.ide.ext.java.client.newsourcefile.JavaSourceFileType.ENUM;
import static org.eclipse.che.ide.ext.java.client.newsourcefile.JavaSourceFileType.INTERFACE;
/**
* Presenter for creating Java source file.
*
* @author Artem Zatsarynnyy
*/
@Singleton
public class NewJavaSourceFilePresenter implements NewJavaSourceFileView.ActionDelegate {
private static final String DEFAULT_CONTENT = " {\n}\n";
private final NewJavaSourceFileView view;
private final SelectionAgent selectionAgent;
private final ProjectServiceClient projectServiceClient;
private final DtoUnmarshallerFactory dtoUnmarshallerFactory;
private final EventBus eventBus;
private final DialogFactory dialogFactory;
private final Array<JavaSourceFileType> sourceFileTypes;
private final AppContext appContext;
@Inject
public NewJavaSourceFilePresenter(NewJavaSourceFileView view, SelectionAgent selectionAgent, ProjectServiceClient projectServiceClient,
DtoUnmarshallerFactory dtoUnmarshallerFactory, EventBus eventBus, DialogFactory dialogFactory,
AppContext appContext) {
this.appContext = appContext;
sourceFileTypes = Collections.createArray(CLASS, INTERFACE, ENUM, ANNOTATION);
this.view = view;
this.selectionAgent = selectionAgent;
this.projectServiceClient = projectServiceClient;
this.dtoUnmarshallerFactory = dtoUnmarshallerFactory;
this.eventBus = eventBus;
this.dialogFactory = dialogFactory;
this.view.setDelegate(this);
}
public void showDialog() {
view.setTypes(sourceFileTypes);
view.showDialog();
}
@Override
public void onCancelClicked() {
view.close();
}
@Override
public void onNameChanged() {
try {
final String fileNameWithExtension = getFileNameWithExtension(view.getName());
if (!fileNameWithExtension.trim().isEmpty()) {
checkCompilationUnitName(fileNameWithExtension);
}
final String packageName = getPackageFragment(view.getName());
if (!packageName.trim().isEmpty()) {
checkPackageName(packageName);
}
view.hideErrorHint();
} catch (IllegalStateException e) {
view.showErrorHint(e.getMessage());
}
}
@Override
public void onOkClicked() {
final String fileNameWithExtension = getFileNameWithExtension(view.getName());
final String fileNameWithoutExtension = fileNameWithExtension.substring(0, fileNameWithExtension.lastIndexOf(".java"));
final String packageFragment = getPackageFragment(view.getName());
if (!packageFragment.isEmpty() && !isValidPackageName(packageFragment)) {
return;
}
if (isValidCompilationUnitName(fileNameWithExtension)) {
view.close();
final FolderNode parent = (FolderNode)selectionAgent.getSelection().getFirstElement();
switch (view.getSelectedType()) {
case CLASS:
createClass(fileNameWithoutExtension, parent, packageFragment);
break;
case INTERFACE:
createInterface(fileNameWithoutExtension, parent, packageFragment);
break;
case ENUM:
createEnum(fileNameWithoutExtension, parent, packageFragment);
break;
case ANNOTATION:
createAnnotation(fileNameWithoutExtension, parent, packageFragment);
break;
}
}
}
private String getFileNameWithExtension(String name) {
if (name.endsWith(".java")) {
name = name.substring(0, name.lastIndexOf(".java"));
}
final int lastDotPos = name.lastIndexOf('.');
name = name.substring(lastDotPos + 1);
return name + ".java";
}
private String getPackageFragment(String name) {
if (name.endsWith(".java")) {
name = name.substring(0, name.lastIndexOf(".java"));
}
final int lastDotPos = name.lastIndexOf('.');
if (lastDotPos >= 0) {
return name.substring(0, lastDotPos);
}
return "";
}
private void createClass(String name, FolderNode parent, String packageFragment) {
String content = getPackageQualifier(parent, packageFragment) +
"public class " + name + DEFAULT_CONTENT;
createSourceFile(name, parent, packageFragment, content);
}
private void createInterface(String name, FolderNode parent, String packageFragment) {
String content = getPackageQualifier(parent, packageFragment) +
"public interface " + name + DEFAULT_CONTENT;
createSourceFile(name, parent, packageFragment, content);
}
private void createEnum(String name, FolderNode parent, String packageFragment) {
String content = getPackageQualifier(parent, packageFragment) +
"public enum " + name + DEFAULT_CONTENT;
createSourceFile(name, parent, packageFragment, content);
}
private void createAnnotation(String name, FolderNode parent, String packageFragment) {
String content = getPackageQualifier(parent, packageFragment) +
"public @interface " + name + DEFAULT_CONTENT;
createSourceFile(name, parent, packageFragment, content);
}
private String getPackageQualifier(FolderNode parent, String packageFragment) {
String packageFQN = "";
if (parent instanceof PackageNode) {
packageFQN = ((PackageNode)parent).getQualifiedName();
}
if (!packageFragment.isEmpty()) {
packageFQN = packageFQN.isEmpty() ? packageFragment : packageFQN + '.' + packageFragment;
}
if (!packageFQN.isEmpty()) {
return "package " + packageFQN + ";\n\n";
}
return "\n";
}
private void createSourceFile(final String nameWithoutExtension, FolderNode parent, String packageFragment, final String content) {
final String parentPath = parent.getPath() + (packageFragment.isEmpty() ? "" : '/' + packageFragment.replace('.', '/'));
ensureFolderExists(parentPath, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
createAndOpenFile(nameWithoutExtension, parentPath, content);
}
@Override
public void onFailure(Throwable caught) {
dialogFactory.createMessageDialog("", caught.getMessage(), null).show();
}
});
}
/** Creates folder by the specified path if it doesn't exists. */
private void ensureFolderExists(String path, final AsyncCallback<Void> callback) {
projectServiceClient.createFolder(path, new AsyncRequestCallback<ItemReference>() {
@Override
protected void onSuccess(ItemReference result) {
callback.onSuccess(null);
}
@Override
protected void onFailure(Throwable exception) {
if (exception.getMessage().contains("already exists")) {
callback.onSuccess(null);
} else {
callback.onFailure(exception);
}
}
});
}
private void createAndOpenFile(String nameWithoutExtension, String parentPath, String content) {
final CurrentProject currentProject = appContext.getCurrentProject();
if (currentProject == null) {
throw new IllegalStateException("No opened project.");
}
final String fileName = nameWithoutExtension + ".java";
final Unmarshallable<ItemReference> unmarshaller = dtoUnmarshallerFactory.newUnmarshaller(ItemReference.class);
projectServiceClient.createFile(parentPath, fileName, content, null, new AsyncRequestCallback<ItemReference>(unmarshaller) {
@Override
protected void onSuccess(ItemReference result) {
currentProject.getCurrentTree().getNodeByPath(result.getPath(), new AsyncCallback<TreeNode<?>>() {
@Override
public void onSuccess(TreeNode<?> result) {
if (result != null) {
eventBus.fireEvent(new ItemEvent((ItemNode)result, CREATED));
eventBus.fireEvent(new FileEvent((VirtualFile)result, OPEN));
}
}
@Override
public void onFailure(Throwable caught) {
dialogFactory.createMessageDialog("", caught.getMessage(), null).show();
}
});
}
@Override
protected void onFailure(Throwable exception) {
dialogFactory.createMessageDialog("", exception.getMessage(), null).show();
}
});
}
}