/*******************************************************************************
* 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.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.api.resources.marker.Marker;
import org.eclipse.che.ide.api.resources.marker.MarkerChangedEvent;
import org.eclipse.che.ide.resource.Path;
/**
* The client side analog of file system files and directories. There are exactly three types of resources:
* files, folders and projects.
* <p/>
* Workspace root is representing by {@link Container}. In which only {@link Project} is allowed to be created.
* <p/>
* File resources are similar to files in that they hold data directly. Folder resources are analogous to
* directories in that they hold other resources but cannot directly hold data. Project resources group files
* and folders into reusable clusters.
* <p/>
* Features of resources:
* <ul>
* <li>{@code Resource} objects are handles to state maintained by a workspace. That is, resources objects
* do not actually contain data themselves but rather represent resource state and give it behaviour.</li>
* <li>Resources are identified by type and their {@code path}, which is similar to a file system path.
* The name of the resource is the last segment of its path. A resource's parent is located by removing
* the last segment (the resource's name) from the resource's full path.</li>
* </ul>
* <p/>
* To obtain already initialized resource in workspace you just need to inject {@link AppContext} into your
* component and call {@link AppContext#getProjects()} or {@link AppContext#getWorkspaceRoot()}.
* <p/>
* Note. This interface is not intended to be implemented by clients.
*
* @author Vlad Zhukovskyi
* @see Container
* @see File
* @see Folder
* @see Project
* @see AppContext#getProjects()
* @see AppContext#getWorkspaceRoot()
* @since 4.4.0
*/
@Beta
public interface Resource extends Comparable<Resource> {
/**
* Type constant that describes {@code File} resource.
*
* @see Resource#getResourceType()
* @see Resource#isFile()
* @see File
* @since 4.4.0
*/
int FILE = 0x1;
/**
* Type constant that describes {@code Folder} resource.
*
* @see Resource#getResourceType()
* @see Resource#isFolder()
* @see Folder
* @since 4.4.0
*/
int FOLDER = 0x2;
/**
* Type constant that describes {@code Project} resource.
*
* @see Resource#getResourceType()
* @see Resource#isProject()
* @see Project
* @since 4.4.0
*/
int PROJECT = 0x4;
/**
* Returns {@code true} if current represents a file.
*
* @return true if current resource is file based resource.
* @see Resource#getResourceType()
* @see Resource#FILE
* @since 4.4.0
*/
boolean isFile();
/**
* Casts current resource to the {@link File} if the last one's represents a file.
* <p>
* Example of usage:
* <pre>
* public void doSome() {
* Resource resource = ...;
* if (resource.isFile()) {
* File file = resource.asFile();
* }
* }
* </pre>
*
* @return instance of {@link File}
* @throws IllegalStateException
* in case if current resource is not a file
* @see Resource#getResourceType()
* @see Resource#FILE
* @since 5.1.0
*/
File asFile();
/**
* Returns {@code true} if current represents a folder.
*
* @return true if current resource is folder based resource.
* @see Resource#getResourceType()
* @see Resource#FOLDER
* @since 4.4.0
*/
boolean isFolder();
/**
* Casts current resource to the {@link Folder} if the last one's represents a folder.
* <p>
* Example of usage:
* <pre>
* public void doSome() {
* Resource resource = ...;
* if (resource.isFolder()) {
* Folder folder = resource.asFolder();
* }
* }
* </pre>
*
* @return instance of {@link Folder}
* @throws IllegalStateException
* in case if current resource is not a folder
* @see Resource#getResourceType()
* @see Resource#FOLDER
* @since 5.1.0
*/
Folder asFolder();
/**
* Returns {@code true} if current represents a project.
*
* @return true if current resource is project based resource.
* @see Resource#getResourceType()
* @see Resource#PROJECT
* @since 4.4.0
*/
boolean isProject();
/**
* Casts current resource to the {@link Project} if the last one's represents a project.
* <p>
* Example of usage:
* <pre>
* public void doSome() {
* Resource resource = ...;
* if (resource.isProject()) {
* Project project = resource.asProject();
* }
* }
* </pre>
*
* @return instance of {@link Project}
* @throws IllegalStateException
* in case if current resource is not a project
* @see Resource#getResourceType()
* @see Resource#PROJECT
* @since 5.1.0
*/
Project asProject();
/**
* Copies resource to given {@code destination} path. Copy operation performs asynchronously and result of current
* operation will be provided in {@code Promise} result. Destination path should have write access.
* <p/>
* Copy operation produces new {@link Resource} which is already cached.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when resource has successfully copied. This event provides information about copied
* resource and source resource.
* <p/>
* Example of usage:
* <pre>
* Resource resource = ... ;
* Path copyTo = ... ;
*
* resource.copy(copyTo).then(new Operation<Resource>() {
* public void apply(Resource copiedResource) throws OperationException {
* //do something with copiedResource
* }
* })
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Copied resource provided by {@link ResourceDelta#getResource()}.
* Contains flags {@link ResourceDelta#COPIED_FROM}.
* Source resource is accessible by calling {@link ResourceDelta#getFromPath()}.
*
* @param destination
* the destination path
* @return {@link Promise} with copied {@link Resource}
* @throws IllegalStateException
* if this resource could not be copied. Reasons include:
* <ul>
* <li>Resource already exists</li>
* <li>Resource with path '/path' isn't a project</li>
* </ul>
* @throws IllegalArgumentException
* if current resource can not be copied. Reasons include:
* <ul>
* <li>Workspace root is not allowed to be copied</li>
* </ul>
* @see ResourceChangedEvent
* @see Resource
* @since 4.4.0
*/
Promise<Resource> copy(Path destination);
/**
* Copies resource to given {@code destination} path. Copy operation performs asynchronously and result of current
* operation will be provided in {@code Promise} result. Destination path should have write access.
* <p/>
* Copy operation produces new {@link Resource} which is already cached.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when resource has successfully copied. This event provides information about copied
* resource and source resource.
* <p/>
* Passing {@code force} argument as true method will ignore existed resource on the server and overwrite them.
* <p/>
* Example of usage:
* <pre>
* Resource resource = ... ;
* Path copyTo = ... ;
*
* resource.copy(copyTo, true).then(new Operation<Resource>() {
* public void apply(Resource copiedResource) throws OperationException {
* //do something with copiedResource
* }
* })
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Copied resource provided by {@link ResourceDelta#getResource()}.
* Contains flags {@link ResourceDelta#COPIED_FROM}.
* Source resource is accessible by calling {@link ResourceDelta#getFromPath()}.
*
* @param destination
* the destination path
* @param force
* overwrite existed resource on the server
* @return {@link Promise} with copied {@link Resource}
* @throws IllegalStateException
* if this resource could not be copied. Reasons include:
* <ul>
* <li>Resource already exists</li>
* <li>Resource with path '/path' isn't a project</li>
* </ul>
* @throws IllegalArgumentException
* if current resource can not be copied. Reasons include:
* <ul>
* <li>Workspace root is not allowed to be copied</li>
* </ul>
* @see ResourceChangedEvent
* @see Resource
* @since 4.4.0
*/
Promise<Resource> copy(Path destination, boolean force);
/**
* Moves resource to given new {@code destination}. Move operation performs asynchronously and result of current
* operation will be displayed in {@code Promise} result.
* <p/>
* Move operation produces new {@link Resource} which is already cached.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when resource has successfully moved. This event provides information about moved
* resource.
* <p/>
* Before moving mechanism remembers deepest depth which was read and tries to restore it after move.
* <p/>
* Example of usage:
* <pre>
* Resource resource = ... ;
* Path moveTo = ... ;
*
* resource.move(moveTo).then(new Operation<Resource>() {
* public void apply(Resource movedResource) throws OperationException {
* //do something with movedResource
* }
* })
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#REMOVED}.
* Removed resource is provided by {@link ResourceDelta#getResource()}.
* <p/>
* Also fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Moved resource provided by {@link ResourceDelta#getResource()}.
* Contains flags {@link ResourceDelta#MOVED_FROM} and {@link ResourceDelta#MOVED_TO}.
* Source resource is accessible by calling {@link ResourceDelta#getFromPath()}.
* Moved resource (or new resource) is accessible by calling {@link ResourceDelta#getToPath()}.
*
* @param destination
* the destination path
* @return {@code Promise} with move moved {@link Resource}
* @throws IllegalStateException
* if this resource could not be moved. Reasons include:
* <ul>
* <li>Resource already exists</li>
* <li>Resource with path '/path' isn't a project</li>
* </ul>
* @throws IllegalArgumentException
* if current resource can not be moved. Reasons include:
* <ul>
* <li>Workspace root is not allowed to be moved</li>
* </ul>
* @see ResourceChangedEvent
* @see Resource
* @since 4.4.0
*/
Promise<Resource> move(Path destination);
/**
* Moves resource to given new {@code destination}. Move operation performs asynchronously and result of current
* operation will be displayed in {@code Promise} result.
* <p/>
* Move operation produces new {@link Resource} which is already cached.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when resource has successfully moved. This event provides information about moved
* resource.
* <p/>
* Before moving mechanism remembers deepest depth which was read and tries to restore it after move.
* <p/>
* Passing {@code force} argument as true method will ignore existed resource on the server and overwrite them.
* <p/>
* Example of usage:
* <pre>
* Resource resource = ... ;
* Path moveTo = ... ;
*
* resource.move(moveTo, true).then(new Operation<Resource>() {
* public void apply(Resource movedResource) throws OperationException {
* //do something with movedResource
* }
* })
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#REMOVED}.
* Removed resource is provided by {@link ResourceDelta#getResource()}.
* <p/>
* Also fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#ADDED}.
* Moved resource provided by {@link ResourceDelta#getResource()}.
* Contains flags {@link ResourceDelta#MOVED_FROM} and {@link ResourceDelta#MOVED_TO}.
* Source resource is accessible by calling {@link ResourceDelta#getFromPath()}.
* Moved resource (or new resource) is accessible by calling {@link ResourceDelta#getToPath()}.
*
* @param destination
* the destination path
* @return {@code Promise} with move moved {@link Resource}
* @throws IllegalStateException
* if this resource could not be moved. Reasons include:
* <ul>
* <li>Resource already exists</li>
* <li>Resource with path '/path' isn't a project</li>
* </ul>
* @throws IllegalArgumentException
* if current resource can not be moved. Reasons include:
* <ul>
* <li>Workspace root is not allowed to be moved</li>
* </ul>
* @see ResourceChangedEvent
* @see Resource
* @since 4.4.0
*/
Promise<Resource> move(Path destination, boolean force);
/**
* Deletes current resource.
* Delete operation performs asynchronously and result of current operation will be displayed in {@code Promise}
* result as {@code void}.
* <p/>
* Fires following events:
* {@link ResourceChangedEvent} when resource has successfully removed.
* <p/>
* Example of usage:
* <pre>
* Resource resource = ... ;
*
* resource.delete().then(new Operation<Void>() {
* public void apply(Void ignored) throws OperationException {
* //do something
* }
* })
* </pre>
* <p/>
* Fires {@link ResourceChangedEvent} with the following {@link ResourceDelta}:
* Delta kind: {@link ResourceDelta#REMOVED}.
* Removed resource provided by {@link ResourceDelta#getResource()}
*
* @return {@code Promise} with {@code void}
* @throws IllegalArgumentException
* if current resource can not be removed. Reasons include:
* <ul>
* <li>Workspace root is not allowed to be removed</li>
* </ul>
* @see ResourceChangedEvent
* @since 4.4.0
*/
Promise<Void> delete();
/**
* Returns the full, absolute path of this resource relative to the project's root.
* e.g. {@code "/project_name/path/to/resource"}.
*
* @return the absolute path of this resource
* @see Path
* @since 4.4.0
*/
Path getLocation();
/**
* Returns the name of the resource.
* The name of a resource is synonymous with the last segment of its full (or project-relative) path.
*
* @return the name of the resource
* @since 4.4.0
*/
String getName();
/**
* Returns the resource which is the parent of this resource or {@code null} if such parent
* doesn't exist. (This means that this resource is 'root' project)
*
* @return the resource's parent {@link Container}
* @see Container
* @since 5.1.0
*/
Container getParent();
/**
* Returns the {@code Project} which contains this resource.
* Returns itself for projects. A resource's project is the one named by the first segment of its full path.
* <p/>
* By design, each node should be bound to specified {@link Project}.
*
* @return the {@link Optional} with related project
* @see Project
* @since 4.4.0
* @deprecated use {@link #getProject()}
*/
@Deprecated
Optional<Project> getRelatedProject();
/**
* Returns the {@link Project} which is bound to this resource or {@code null}.
*
* Returns itself for projects.
*
* @return the bound instance of {@link Project} or null
* @since 5.1.0
*/
Project getProject();
/**
* Returns the type of this resource.
* Th returned value will be on of {@code FILE}, {@code FOLDER}, {@code PROJECT}.
* <p/>
* <ul>
* <li>All resources of type {@code FILE} implement {@code File}.</li>
* <li>All resources of type {@code FOLDER} implement {@code Folder}.</li>
* <li>All resources of type {@code PROJECT} implement {@code Project}.</li>
* </ul>
*
* @return the type of this resource
* @see #FILE
* @see #FOLDER
* @see #PROJECT
* @since 4.4.0
*/
int getResourceType();
/**
* Returns the URL of this resource. The URL allows to download locally current resource.
* <p/>
* For container based resource the URL link will allow download container as zip archive.
*
* @return the URL of the resource
* @throws IllegalArgumentException
* if URL is requested on workspace root. Reasons include:
* <ul>
* <li>Workspace root doesn't have export URL</li>
* </ul>
* @since 4.4.0
*/
String getURL();
/**
* Returns the marker handle with given {@code type} for the resource. The resource is not checked to see if
* it has such a marker. The returned marker need not exist.
*
* @param type
* the known marker type
* @return the {@link Optional} with specified registered marker
* @throws IllegalArgumentException
* in case if given marker type is invalid (null or empty). Reasons include:
* <ul>
* <li>Invalid marker type occurred</li>
* </ul>
* @see Marker#getType()
* @see #getMarkers()
* @since 4.4.0
*/
Optional<Marker> getMarker(String type);
/**
* Returns all markers of the specified type on this resource. If there is no marker bound to the resource, then
* empty array will be returned.
*
* @return the array of markers
* @see #getMarker(String)
* @since 4.4.0
*/
Marker[] getMarkers();
/**
* Bound given {@code marker} to current resource. if such marker is already bound to the resource it will be overwritten.
* <p/>
* Fires following events:
* {@link MarkerChangedEvent} with status {@link Marker#UPDATED} when existed marker has been replaced with new one.
* {@link MarkerChangedEvent} with status {@link Marker#CREATED} when marker has been added to the current resource.
*
* @param marker
* the resource marker
* @throws IllegalArgumentException
* in case if given marker is invalid. Reasons include:
* <ul>
* <li>Null marker occurred</li>
* </ul>
* @see MarkerChangedEvent
* @since 4.4.0
*/
void addMarker(Marker marker);
/**
* Delete specified marker with given {@code type}.
* <p/>
* Fires following event:
* {@link MarkerChangedEvent} with status {@link Marker#REMOVED} when given marker has been removed from current resource.
*
* @param type
* the marker type
* @return true if specified marker removed
* @throws IllegalArgumentException
* in case if given marker type is invalid (null or empty). Reasons include:
* <ul>
* <li>Invalid marker type occurred</li>
* </ul>
* @see Marker#getType()
* @see MarkerChangedEvent
* @since 4.4.0
*/
boolean deleteMarker(String type);
/**
* Delete all markers which is bound to current resource.
*
* @return true if all markers has been removed
* @since 4.4.0
*/
boolean deleteAllMarkers();
/**
* Returns the nearest parent resource which has given marker {@code type}.
*
* @param type
* the marker type
* @return the {@link Optional} with specified registered marker
* @throws IllegalArgumentException
* in case if given marker type is invalid (null or empty). Reasons include:
* <ul>
* <li>Invalid marker type occurred</li>
* </ul>
* @since 4.4.0
*/
Optional<Resource> getParentWithMarker(String type);
/** {@inheritDoc} */
@Override
boolean equals(Object other);
/** {@inheritDoc} */
@Override
int hashCode();
/**
* Base interface for resource modification request.
*
* @param <R>
* the resource type, should extends {@link Resource}
* @param <O>
* the body which is used to construct the request
* @see ProjectRequest
* @since 4.4.0
*/
@Beta
interface Request<R extends Resource, O> {
/**
* The body which is used to transform input data into request which is responsible for resource modification.
*
* @param object
* the request body
* @return instance of current {@link Request}
* @see #getBody()
* @since 4.4.0
*/
Request<R, O> withBody(O object);
/**
* Returns the body which is used to transform input data into request.
*
* @return the request body
* @see #withBody(Object)
* @since 4.4.0
*/
O getBody();
/**
* Sends the request to server and returns the {@link Promise} with new instance of {@link R} which belongs
* to provided request configuration.
* <p/>
* Uses to modify state of concrete resource.
*
* @return the {@link Promise} with new instance {@link R}
* @see Container#newProject()
* @see Container#importProject()
* @see Project#update()
* @since 4.4.0
*/
Promise<R> send();
}
}