/*******************************************************************************
* 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.api.resources;
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import org.eclipse.che.api.core.model.project.type.ProjectType;
import org.eclipse.che.api.project.shared.dto.SourceEstimation;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.resources.Project.ProjectRequest;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.util.NameUtils;
/**
* Interface for resource which may contain other resources (termed its members).
* <p/>
* If {@code location} of current container is equals to {@link Path#ROOT} then it means that current container
* represent the workspace root. To obtain the workspace root {@link AppContext} should be injected into third-
* party component and method {@link AppContext#getWorkspaceRoot()} should be called. Only {@link Project}s are
* allowed to be created in workspace root.
* <p/>
* Note. This interface is not intended to be implemented by clients.
*
* @author Vlad Zhukovskyi
* @see Project
* @see Folder
* @see AppContext
* @see AppContext#getWorkspaceRoot()
* @since 4.4.0
*/
@Beta
public interface Container extends Resource {
/**
* Returns the {@code Promise} with handle to the file resource identified by the given path in this container.
* <p/>
* The supplied path should represent relative path to file in this container.
*
* @param relativePath
* the path of the member file
* @return the {@code Promise} with the handle of the member file
* @throws IllegalStateException
* if during resource search failed has been occurred. Reasons include:
* <ul>
* <li>Resource with path '/project_path' doesn't exists</li>
* <li>Resource with path '/project_path' isn't a project</li>
* <li>Not a file</li>
* </ul>
* @see #getContainer(Path)
* @since 4.4.0
*/
Promise<Optional<File>> getFile(Path relativePath);
/**
* Returns the {@code Promise} with handle to the file resource identified by the given path in this container.
* <p/>
* The supplied path should represent relative path to file in this container.
*
* @param relativePath
* the path of the member file
* @return the {@code Promise} with the handle of the member file
* @throws IllegalStateException
* if during resource search failed has been occurred. Reasons include:
* <ul>
* <li>Resource with path '/project_path' doesn't exists</li>
* <li>Resource with path '/project_path' isn't a project</li>
* <li>Not a file</li>
* </ul>
* @see #getContainer(Path)
* @since 4.4.0
*/
Promise<Optional<File>> getFile(String relativePath);
/**
* Returns the {@code Promise} with handle to the container identified by the given path in this container.
* <p/>
* The supplied path should represent relative path to folder.
*
* @param relativePath
* the path of the member container
* @return the {@code Promise} with the handle of the member container
* @throws IllegalStateException
* if during resource search failed has been occurred. Reasons include:
* <ul>
* <li>Resource with path '/project_path' doesn't exists</li>
* <li>Resource with path '/project_path' isn't a project</li>
* <li>Not a container</li>
* </ul>
* @see #getFile(Path)
* @since 4.4.0
*/
Promise<Optional<Container>> getContainer(Path relativePath);
/**
* Returns the {@code Promise} with handle to the container identified by the given path in this container.
* <p/>
* The supplied path should represent relative path to folder.
*
* @param relativePath
* the path of the member container
* @return the {@code Promise} with the handle of the member container
* @throws IllegalStateException
* if during resource search failed has been occurred. Reasons include:
* <ul>
* <li>Resource with path '/project_path' doesn't exists</li>
* <li>Resource with path '/project_path' isn't a project</li>
* <li>Not a container</li>
* </ul>
* @see #getFile(Path)
* @since 4.4.0
*/
Promise<Optional<Container>> getContainer(String relativePath);
/**
* Returns the {@code Promise} with array of existing member resources (projects, folders and files) in this resource,
* in particular order. Order is organized by alphabetic resource name ignoring case.
* <p/>
* Supplied parameter {@code force} instructs that stored children should be updated.
* <p/>
* Note, that if the result array is empty, then method thinks that children may not be loaded from the server and send
* a request ot the server to load the children.
* <p/>
* Method guarantees that resources will be sorted by their {@link #getLocation()} in ascending order.
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Cached and loaded resource provided by {@link ResourceDelta#getResource()}.
* <p/>
* Or
* <p/>
* Delta kind: {@link ResourceDelta#UPDATED}. When resource was cached previously.
* Updated resource provided by {@link ResourceDelta#getResource()}.
*
* @return the {@code Promise} with array of members of this resource
* @see #getChildren()
* @since 4.4.0
*/
Promise<Resource[]> getChildren();
/**
* Returns the {@code Promise} with array of existing member resources (projects, folders and files) in this resource,
* in particular order. Order is organized by alphabetic resource name ignoring case.
* <p/>
* Supplied parameter {@code force} instructs that stored children should be updated.
* <p/>
* Note, that if supplied argument {@code force} is set to {@code false} and result array is empty, then method thinks
* that children may not be loaded from the server and send a request ot the server to load the children.
* <p/>
* Method guarantees that resources will be sorted by their {@link #getLocation()} in ascending order.
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Cached and loaded resource provided by {@link ResourceDelta#getResource()}.
* <p/>
* Or
* <p/>
* Delta kind: {@link ResourceDelta#UPDATED}. When resource was cached previously.
* Updated resource provided by {@link ResourceDelta#getResource()}.
* <p/>
* May fire {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#REMOVED}.
* Removed resource provided by {@link ResourceDelta#getResource()}.
* In case if {@code force} is set in {@code true}.
*
* @return the {@code Promise} with array of members of this resource
* @see #getChildren()
* @since 4.4.0
*/
Promise<Resource[]> getChildren(boolean force);
/**
* Creates the new {@link Project} in current container.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when project has successfully created.
* <p/>
* Calling this method doesn't create a project immediately. To complete the request method {@link ProjectRequest#send()} should be
* called. {@link ProjectRequest} has ability to reconfigure project during update/create operations.
* <p/>
* Calling {@link ProjectRequest#send()} produces new {@link Project} resource.
* <p/>
* The supplied argument {@code name} should be a valid and pass validation within {@link NameUtils#checkProjectName(String)}.
* The supplied argument {@code type} should be a valid and registered project type.
* <p/>
* <p/>
* Example of usage for creating a new project:
* <pre>
* ProjectConfig config = ... ;
* Container workspace = ... ;
*
* Promise<Project> newProjectPromise = workspace.newProject()
* .withBody(config)
* .send();
*
* newProjectPromise.then(new Operation<Project>() {
* public void apply(Project newProject) throws OperationException {
* //do something with new project
* }
* });
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Created resource (instance of {@link Project}) provided by {@link ResourceDelta#getResource()}
*
* @return the create project request
* @throws IllegalArgumentException
* if arguments is not a valid. Reasons include:
* <ul>
* <li>Invalid project name</li>
* <li>Invalid project type</li>
* </ul>
* @throws IllegalStateException
* if creation was failed. Reasons include:
* <ul>
* <li>Resource already exists</li>
* </ul>
* @see NameUtils#checkProjectName(String)
* @see ProjectRequest
* @see ProjectRequest#send()
* @since 4.4.0
*/
ProjectRequest newProject();
/**
* Creates the new {@link Project} in current container with specified source storage (in other words, imports a remote project).
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when project has successfully created.
* <p/>
* Calling this method doesn't import a project immediately. To complete the request method {@link ProjectRequest#send()} should be
* called.
* <p/>
* Calling {@link ProjectRequest#send()} produces new {@link Project} resource.
* <p/>
* The supplied argument {@code name} should be a valid and pass validation within {@link NameUtils#checkProjectName(String)}.
* <p/>
* <p/>
* Example of usage for creating a new project:
* <pre>
* ProjectConfig config = ... ;
* Container workspace = ... ;
*
* Promise<Project> newProjectPromise = workspace.importProject()
* .withBody(config)
* .send();
*
* newProjectPromise.then(new Operation<Project>() {
* public void apply(Project newProject) throws OperationException {
* //do something with new project
* }
* });
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Created resource (instance of {@link Project}) provided by {@link ResourceDelta#getResource()}
*
* @return the create project request
* @throws IllegalArgumentException
* if arguments is not a valid. Reasons include:
* <ul>
* <li>Invalid project name</li>
* </ul>
* @throws IllegalStateException
* if creation was failed. Reasons include:
* <ul>
* <li>Resource already exists</li>
* </ul>
* @see NameUtils#checkProjectName(String)
* @see ProjectRequest
* @see ProjectRequest#send()
* @since 4.4.0
*/
ProjectRequest importProject();
/**
* Creates the new {@link Folder} in current container.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when folder has successfully created.
* <p/>
* Method produces new {@link Folder}.
* <p/>
* The supplied argument {@code name} should be a valid and pass validation within {@link NameUtils#checkFolderName(String)}.
* <p/>
* Note. That folders can not be created in workspace root (obtained by {@link AppContext#getWorkspaceRoot()}).
* Creating folder in this container will be failed.
* <p/>
* Example of usage:
* <pre>
* Container workspace = ... ;
*
* workspace.newFolder("name").then(new Operation<Folder>() {
* public void apply(Folder newFolder) throws OperationException {
* //do something with new folder
* }
* });
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Created resource (instance of {@link Folder}) provided by {@link ResourceDelta#getResource()}
*
* @param name
* the name of the folder
* @return the {@link Promise} with created {@link Folder}
* @throws IllegalArgumentException
* if arguments is not a valid. Reasons include:
* <ul>
* <li>Invalid folder name</li>
* <li>Failed to create folder in workspace root</li>
* </ul>
* @throws IllegalStateException
* if creation was failed. Reasons include:
* <ul>
* <li>Resource already exists</li>
* </ul>
* @see NameUtils#checkFolderName(String)
* @since 4.4.0
*/
Promise<Folder> newFolder(String name);
/**
* Creates the new {@link File} in current container.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when file has successfully created.
* <p/>
* Method produces new {@link File}.
* <p/>
* The supplied argument {@code name} should be a valid and pass validation within {@link NameUtils#checkFileName(String)} (String)}.
* <p/>
* Note. That files can not be created in workspace root (obtained by {@link AppContext#getWorkspaceRoot()}).
* Creating folder in this container will be failed.
* <p/>
* The file content may be a {@code null} or empty.
* <p/>
* Example of usage:
* <pre>
* Container workspace = ... ;
*
* workspace.newFile("name", "content").then(new Operation<File>() {
* public void apply(File newFile) throws OperationException {
* //do something with new file
* }
* });
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Created resource (instance of {@link File}) provided by {@link ResourceDelta#getResource()}
*
* @param name
* the name of the file
* @param content
* the file content
* @return the {@link Promise} with created {@link File}
* @throws IllegalArgumentException
* if arguments is not a valid. Reasons include:
* <ul>
* <li>Invalid file name</li>
* <li>Failed to create file in workspace root</li>
* </ul>
* @throws IllegalStateException
* if creation was failed. Reasons include:
* <ul>
* <li>Resource already exists</li>
* </ul>
* @see NameUtils#checkFileName(String)
* @since 4.4.0
*/
Promise<File> newFile(String name, String content);
/**
* Synchronizes the cached container and its children with the local file system.
* <p/>
* For refreshing entire workspace root this method should be called on the container, which obtained
* from {@link AppContext#getWorkspaceRoot()}.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when the synchronized resource has changed.
* <p/>
* Method doesn't guarantees the sorted order of the returned resources.
*
* @return the array of resource which where affected by synchronize operation
* @since 4.4.0
*/
Promise<Resource[]> synchronize();
/**
* Synchronizes the given {@code deltas} with already cached resources.
* Method is useful for third-party components which performs changes with resources outside of client side resource management.
* <p/>
* Method should be called on the workspace root {@link AppContext#getWorkspaceRoot()}.
*
* @param deltas
* the deltas which should be resolved
* @return the {@link Promise} with resolved deltas
* @throws IllegalStateException
* in case if method has been called outside of workspace root. Reasons include:
* <ul>
* <li>External deltas should be applied on the workspace root</li>
* </ul>
* @see ExternalResourceDelta
* @see ResourceDelta
* @since 4.4.0
*/
Promise<ResourceDelta[]> synchronize(ResourceDelta... deltas);
/**
* Searches the all possible files which matches given file or content mask.
* <p/>
* Supplied file mask may supports wildcard:
* <ul>
* <li>{@code *} - which matches any character sequence (including the empty one)</li>
* <li>{@code ?} - which matches any single character</li>
* </ul>
* <p/>
* Method doesn't guarantees the sorted order of the returned resources.
*
* @param fileMask
* the file name mask
* @param contentMask
* the content entity mask
* @return the {@link Promise} with array of found results
* @since 4.4.0
*/
Promise<Resource[]> search(String fileMask, String contentMask);
/**
* Returns the plain list of file tree with given {@code depth}.
* <p/>
* Input {@code depth} should be within the range from -1 to {@link Integer#MAX_VALUE}.
* <p/>
* In case if {@code depth} equals to 0, then empty resource is returned.
* In case if {@code depth} equals to -1, then whole file tree is loaded and returned.
* <p/>
* Method doesn't guarantee that resources will be sorted by their {@link #getLocation()} in any order.
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Cached and loaded resource provided by {@link ResourceDelta#getResource()}.
* <p/>
* Or
* <p/>
* Delta kind: {@link ResourceDelta#UPDATED}. When resource was cached previously.
* Updated resource provided by {@link ResourceDelta#getResource()}.
*
* @param depth
* the depth
* @return plain array of loaded resources
* @throws IllegalArgumentException
* in case if invalid depth passed as argument. i.e. depth equals -2, -3 and so on. Reasons include:
* <ul>
* <li>Invalid depth</li>
* </ul>
* @since 4.4.0
*/
Promise<Resource[]> getTree(int depth);
/**
* Estimates if the current container supposed to be a project within certain {@code projectType}.
*
* @param projectType
* the project type to estimate for
* @return the {@link SourceEstimation} with estimated attributes
* @throws IllegalArgumentException
* in case if project type is {@code null} or empty. Reasons include:
* <ul>
* <li>Null project type</li>
* <li>Empty project type</li>
* </ul>
* @see SourceEstimation
* @see ProjectType#getId()
* @since 4.4.0
*/
Promise<SourceEstimation> estimate(String projectType);
}