/*******************************************************************************
* Copyright (c) 2012-2017 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.projecttype.wizard;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.che.api.machine.shared.dto.CommandDto;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.command.CommandImpl;
import org.eclipse.che.ide.api.command.CommandImpl.ApplicableContext;
import org.eclipse.che.ide.api.command.CommandManager;
import org.eclipse.che.ide.api.project.MutableProjectConfig;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode;
import org.eclipse.che.ide.api.resources.Container;
import org.eclipse.che.ide.api.resources.Folder;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.wizard.AbstractWizard;
import org.eclipse.che.ide.resource.Path;
import javax.validation.constraints.NotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.CREATE;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.IMPORT;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.UPDATE;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar.PROJECT_NAME_KEY;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar.WIZARD_MODE_KEY;
import static org.eclipse.che.ide.api.resources.Resource.FOLDER;
import static org.eclipse.che.ide.api.resources.Resource.PROJECT;
/**
* Project wizard used for creating new a project or updating an existing one.
*
* @author Artem Zatsarynnyi
* @author Dmitry Shnurenko
* @author Vlad Zhukovskyi
* @author Valeriy Svydenko
*/
public class ProjectWizard extends AbstractWizard<MutableProjectConfig> {
private final static String PROJECT_PATH_MACRO_REGEX = "\\$\\{current.project.path\\}";
private final ProjectWizardMode mode;
private final AppContext appContext;
private final CommandManager commandManager;
@Inject
public ProjectWizard(@Assisted MutableProjectConfig dataObject,
@Assisted ProjectWizardMode mode,
AppContext appContext,
CommandManager commandManager) {
super(dataObject);
this.mode = mode;
this.appContext = appContext;
this.commandManager = commandManager;
context.put(WIZARD_MODE_KEY, mode.toString());
context.put(PROJECT_NAME_KEY, dataObject.getName());
}
@Override
public void complete(@NotNull final CompleteCallback callback) {
if (mode == CREATE) {
appContext.getWorkspaceRoot()
.newProject()
.withBody(dataObject)
.send()
.then(onComplete(callback))
.catchError(onFailure(callback));
} else if (mode == UPDATE) {
appContext.getWorkspaceRoot()
.getContainer(Path.valueOf(dataObject.getPath()))
.then(optContainer -> {
checkState(optContainer.isPresent(), "Failed to update non existed path");
final Container container = optContainer.get();
if (container.getResourceType() == PROJECT) {
((Project)container).update()
.withBody(dataObject)
.send()
.then(onComplete(callback))
.catchError(onFailure(callback));
} else if (container.getResourceType() == FOLDER) {
((Folder)container).toProject()
.withBody(dataObject)
.send()
.then(onComplete(callback))
.catchError(onFailure(callback));
}
});
} else if (mode == IMPORT) {
appContext.getWorkspaceRoot()
.newProject()
.withBody(dataObject)
.send()
.thenPromise(project -> project.update().withBody(dataObject).send())
.then(addCommands(callback))
.catchError(onFailure(callback));
}
}
private Operation<Project> addCommands(CompleteCallback callback) {
return project -> {
Promise<CommandImpl> chain = null;
for (final CommandDto command : dataObject.getCommands()) {
if (chain == null) {
chain = addCommand(project, command);
} else {
chain = chain.thenPromise(ignored -> addCommand(project, command));
}
}
if (chain == null) {
callback.onCompleted();
} else {
chain.then(ignored -> {
callback.onCompleted();
}).catchError(onFailure(callback));
}
};
}
private Promise<CommandImpl> addCommand(Project project, CommandDto commandDto) {
final String name = project.getName() + ": " + commandDto.getName();
final String absoluteProjectPath = appContext.getProjectsRoot().append(project.getPath()).toString();
final String commandLine = commandDto.getCommandLine().replaceAll(PROJECT_PATH_MACRO_REGEX, absoluteProjectPath);
final CommandImpl command = new CommandImpl(name,
commandLine,
commandDto.getType(),
commandDto.getAttributes(),
new ApplicableContext(project.getPath()));
return commandManager.createCommand(command);
}
private Operation<Project> onComplete(final CompleteCallback callback) {
return ignored -> callback.onCompleted();
}
private Operation<PromiseError> onFailure(final CompleteCallback callback) {
return error -> callback.onFailure(error.getCause());
}
}