/*******************************************************************************
* 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.action;
import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.app.CurrentProject;
import org.eclipse.che.ide.api.event.ItemEvent;
import org.eclipse.che.ide.api.event.RefreshProjectTreeEvent;
import org.eclipse.che.ide.api.project.tree.AbstractTreeNode;
import org.eclipse.che.ide.api.project.tree.TreeNode;
import org.eclipse.che.ide.api.project.tree.TreeStructure;
import org.eclipse.che.ide.api.project.tree.generic.ItemNode;
import org.eclipse.che.ide.api.project.tree.generic.StorableNode;
import org.eclipse.che.ide.api.selection.Selection;
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.JavaUtils;
import org.eclipse.che.ide.ext.java.client.projecttree.JavaTreeStructure;
import org.eclipse.che.ide.ext.java.client.projecttree.nodes.AbstractSourceContainerNode;
import org.eclipse.che.ide.ext.java.client.projecttree.nodes.PackageNode;
import org.eclipse.che.ide.newresource.AbstractNewResourceAction;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import org.eclipse.che.ide.rest.Unmarshallable;
import org.eclipse.che.ide.ui.dialogs.InputCallback;
import org.eclipse.che.ide.ui.dialogs.input.InputDialog;
import org.eclipse.che.ide.ui.dialogs.input.InputValidator;
import org.eclipse.che.ide.util.loging.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.annotation.Nullable;
import static org.eclipse.che.ide.api.event.ItemEvent.ItemOperation.CREATED;
/**
* Action to create new Java package.
*
* @author Artem Zatsarynnyy
*/
@Singleton
public class NewPackageAction extends AbstractNewResourceAction {
private final InputValidator nameValidator = new NameValidator();
@Inject
public NewPackageAction(JavaResources javaResources, JavaLocalizationConstant localizationConstant) {
super(localizationConstant.actionNewPackageTitle(),
localizationConstant.actionNewPackageDescription(),
javaResources.packageIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
eventLogger.log(this);
InputDialog inputDialog = dialogFactory.createInputDialog("New " + title, "Name:", new InputCallback() {
@Override
public void accepted(String value) {
onAccepted(value);
}
}, null).withValidator(nameValidator);
inputDialog.show();
}
private void onAccepted(String value) {
final StorableNode parent = getNewResourceParent();
if (parent == null) {
throw new IllegalStateException("No selected parent.");
}
createPackage(parent, value, new AsyncCallback<ItemReference>() {
@Override
public void onSuccess(ItemReference result) {
final AbstractTreeNode nodeToRefresh = getNodeToRefresh((AbstractSourceContainerNode)parent);
eventBus.fireEvent(new RefreshProjectTreeEvent(nodeToRefresh));
fireNodeCreated(result.getPath());
}
@Override
public void onFailure(Throwable caught) {
dialogFactory.createMessageDialog("", caught.getMessage(), null).show();
}
});
}
private void fireNodeCreated(String path) {
final CurrentProject currentProject = appContext.getCurrentProject();
if (currentProject == null) {
throw new IllegalStateException("No opened project.");
}
currentProject.getCurrentTree().getNodeByPath(path, new AsyncCallback<TreeNode<?>>() {
@Override
public void onSuccess(TreeNode<?> result) {
eventBus.fireEvent(new ItemEvent((ItemNode)result, CREATED));
}
@Override
public void onFailure(Throwable caught) {
Log.error(NewPackageAction.class, caught);
}
});
}
private AbstractTreeNode getNodeToRefresh(AbstractSourceContainerNode parent) {
final CurrentProject currentProject = appContext.getCurrentProject();
if (currentProject == null) {
throw new IllegalStateException("No opened project.");
}
final TreeStructure currentTree = currentProject.getCurrentTree();
if (currentTree instanceof JavaTreeStructure && ((JavaTreeStructure)currentTree).getSettings().isCompactEmptyPackages()
&& parent instanceof PackageNode && parent.getChildren().isEmpty()) {
return (AbstractTreeNode)parent.getParent();
}
return parent;
}
@Override
public void updateProjectAction(ActionEvent e) {
boolean enabled = false;
Selection<?> selection = selectionAgent.getSelection();
if (selection != null) {
enabled = selection.getFirstElement() instanceof AbstractSourceContainerNode;
}
e.getPresentation().setEnabledAndVisible(enabled);
}
private void createPackage(StorableNode parent, String name, final AsyncCallback<ItemReference> callback) {
final String path = parent.getPath() + '/' + name.replace('.', '/');
final Unmarshallable<ItemReference> unmarshaller = dtoUnmarshallerFactory.newUnmarshaller(ItemReference.class);
projectServiceClient.createFolder(path, new AsyncRequestCallback<ItemReference>(unmarshaller) {
@Override
protected void onSuccess(ItemReference result) {
callback.onSuccess(result);
}
@Override
protected void onFailure(Throwable exception) {
callback.onFailure(exception);
}
});
}
private class NameValidator implements InputValidator {
@Nullable
@Override
public Violation validate(String value) {
try {
JavaUtils.checkPackageName(value);
} catch (final IllegalStateException e) {
return new Violation() {
@Nullable
@Override
public String getMessage() {
return e.getMessage();
}
};
}
return null;
}
}
}