/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sling.api.resource;

import java.io.Closeable;
import java.util.Iterator;
import java.util.Map;

import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import javax.servlet.http.HttpServletRequest;

import org.apache.sling.api.adapter.Adaptable;
import org.apache.sling.api.resource.mapping.ResourceMapper;
import org.osgi.annotation.versioning.ProviderType;

/**
 * The {@code ResourceResolver} defines the API which may be used
 * to resolve {@link org.apache.sling.api.resource.Resource} objects and
 * work with such resources like creating, editing or updating them.
 * The resource resolver is available to the request processing servlet
 * through the
 * {@link org.apache.sling.api.SlingHttpServletRequest#getResourceResolver()}
 * method. A resource resolver can also be created through the
 * {@link ResourceResolverFactory} service.
 * <p>
 * The {@code ResourceResolver} is also an {@link Adaptable} to get
 * adapters to other types. A JCR based resource resolver might support adapting
 * to the JCR Session used by the resolver to access the JCR Repository.
 * <p>
 * A {@code ResourceResolver} is generally not thread safe! As a
 * consequence, an application which uses the resolver, its returned resources
 * and/or objects resulting from adapting either the resolver or a resource,
 * must provide proper synchronization to ensure no more than one thread
 * concurrently operates against a single resolver, resource or resulting
 * objects.
 * <p>
 * <b>Accessing Resources</b>
 * <p>
 * This interface defines two kinds of methods to access resources: The
 * <code>resolve</code> methods and the <code>getResource</code> methods. The
 * difference lies in the algorithm applied to find the requested resource and
 * in the behavior in case a resource cannot be found:
 * <table summary="">
 * <tr>
 * <th>Method Kind</th>
 * <th>Access Algorithm</th>
 * <th>Missing Resource</th>
 * </tr>
 * <tr>
 * <td>resolve</td>
 * <td>Path is always assumed to be absolute. Uses elaborate resource resolution
 * algorithm. This kind of method is intended to resolve request URLs to
 * resources.</td>
 * <td>Returns {@link NonExistingResource}</td>
 * </tr>
 * <tr>
 * <td>getResource</td>
 * <td>Directly access resources with absolute path. For relative paths, the
 * {@link #getSearchPath() search path} is applied. This method is intended to
 * be used by request processing scripts to access further resources as
 * required.</td>
 * <td>Returns <code>null</code></td>
 * </tr>
 * </table>
 * <p>
 * <b>Resource Handling</b>
 * <p>
 * A resource resolver provides various methods to manage resources. All changes
 * are transient and require to commit them at the end.
 * <ul>
 * <li>{@link #create(Resource, String, Map)} for creating a new resource.
 * <li>{@link #delete(Resource)} to delete a resource.
 * <li>{@link #adaptTo(Class)} allows to adapt a resource to a {@link ModifiableValueMap}
 * to update a resource.
 * <li>{@link #move(String, String)} to move resources.
 * <li>{@link #copy(String, String)} to copy resources.
 * <li>{@link #commit()} commits all staged changes.
 * <li>{@link #revert()} reverts all staged changes.
 * </ul>
 * <p>
 * The resource tree accessible through the resource resolver is backed by one or
 * more {@link org.apache.sling.spi.resource.provider.ResourceProvider}s. In
 * general it is advisable to limit transient changes to a single resource provider.
 * The {@link #commit()} is not using a two phase commit, therefore if there
 * is more than one resource provider involved and one of them fails in persisting,
 * changes already committed to other providers are not reverted.
 * <p>
 * <b>Lifecycle</b>
 * <p>
 * A Resource Resolver has a life cycle which begins with the creation of the
 * Resource Resolver using any of the factory methods and ends with calling the
 * {@link #close()} method. It is very important to call the {@link #close()}
 * method once the resource resolver is not used any more to ensure any system
 * resources are properly cleaned up.
 *
 * A Resource Resolver may also be closed implicitly if the {@link ResourceResolverFactory}
 * which was used to create this resolver is no longer active.
 * <p>
 * To check whether a Resource Resolver can still be used, the {@link #isLive()}
 * method can be called.
 * <p>
 * A <code>ResourceResolver</code> is only valid for as long as the
 * <code>ResourceResolverFactory</code> that created this instance exists. The
 * same applies in general to all objects returned by this instance,
 * especially for all resources. If the <code>ResourceResolverFactory</code>
 * does not exist anymore, the resource resolver instances becomes invalid.
 * <p>
 * <b>Resource Resolver Attributes</b>
 * <p>
 * The authentication info properties provided to the
 * {@link ResourceResolverFactory#getResourceResolver(Map)},
 * {@link ResourceResolverFactory#getAdministrativeResourceResolver(Map)}, or
 * {@link #clone(Map)} are available through the {@link #getAttributeNames()}
 * and {@link #getAttribute(String)} methods with the exception of security
 * sensitive properties like {@link ResourceResolverFactory#PASSWORD} which is
 * not exposed.
 */
@ProviderType
public interface ResourceResolver extends Adaptable, Closeable {

    /**
     * A request attribute containing the workspace to use for
     * {@link #resolve(HttpServletRequest)} and
     * {@link #resolve(HttpServletRequest, String)} if not the default workspace
     * should be used to resolve the resource.
     *
     * @since 2.1 (Sling API Bundle 2.1.0)
     * @deprecated
     */
    @Deprecated
    String REQUEST_ATTR_WORKSPACE_INFO = ResourceResolver.class.getName()
        + "/use.workspace";

    /**
     * The name of the resource resolver attribute which is set if the resource
     * resolver has been impersonated as per the
     * {@link ResourceResolverFactory#USER_IMPERSONATION} property. The value of
     * this attribute is the name of the primary user provided to the resource
     * resolver factory method.
     *
     * @since 2.1 (Sling API Bundle 2.1.0)
     */
    String USER_IMPERSONATOR = "user.impersonator";

    /**
     * This is the suggested property to be used for setting the resource type
     * of a resource during either creation ({@link #create(Resource, String, Map)})
     * or modifying ({@link ModifiableValueMap}).
     * However the exact way to set the resource type of a resource is defined
     * by the underlying resource provider. It should value this property but
     * is not required to do so.
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    String PROPERTY_RESOURCE_TYPE = "sling:resourceType";

    /**
     * Resolves the resource from the given <code>absPath</code> optionally
     * taking <code>HttpServletRequest</code> into account, such as the value of
     * the <code>Host</code> request header. Returns a
     * {@link NonExistingResource} if the path cannot be resolved to an existing
     * and accessible resource.
     * <p>
     * The difference between this method and the {@link #resolve(String)}
     * method is, that this method may take request properties like the scheme,
     * the host header or request parameters into account to resolve the
     * resource.
     *
     * @param request The http servlet request object providing more hints at
     *            how to resolve the <code>absPath</code>. This parameter may be
     *            <code>null</code> in which case the implementation should use
     *            reasonable defaults.
     * @param absPath The absolute path to be resolved to a resource. If this
     *            parameter is <code>null</code>, it is assumed to address the
     *            root of the resource tree. If the path is relative it is
     *            assumed relative to the root, that is a slash is prepended to
     *            the path before resolving it.
     * @return The {@link Resource} addressed by the <code>absPath</code> or a
     *         {@link NonExistingResource} if no such resource can be resolved.
     * @throws org.apache.sling.api.SlingException Or a subclass thereof may be
     *             thrown if an error occurs trying to resolve the resource.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.0.4 (Sling API Bundle 2.0.4)
     */
    @NotNull Resource resolve(@NotNull HttpServletRequest request, @NotNull String absPath);

    /**
     * Resolves the resource from the given absolute path. Returns a
     * {@link NonExistingResource} if the path cannot be resolved to an existing
     * and accessible resource.
     * <p>
     * This method is intended to apply the same algorithm to the absolute path
     * as is used by the {@link #resolve(HttpServletRequest)} method except for
     * cases where the latter uses request property such as request headers or
     * request parameters to resolve a resource.
     * <p>
     * It is ok for the implementation of this method to just call the
     * {@link #resolve(HttpServletRequest, String)} method with
     * <code>null</code> as the request argument.
     *
     * @param absPath The absolute path to be resolved to a resource. If this
     *            parameter is <code>null</code>, it is assumed to address the
     *            root of the resource tree. If the path is relative it is
     *            assumed relative to the root, that is a slash is prepended to
     *            the path before resolving it.
     * @return The {@link Resource} addressed by the <code>absPath</code> or a
     *         {@link NonExistingResource} if no such resource can be resolved.
     * @throws org.apache.sling.api.SlingException Or a subclass thereof may be
     *             thrown if an error occurs trying to resolve the resource.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull Resource resolve(@NotNull String absPath);

    /**
     * Resolves the resource from the given <code>HttpServletRequest</code>.
     * Returns a {@link NonExistingResource} if the path cannot be resolved to
     * an existing and accessible resource.
     * <p>
     * This method is deprecated as of API version 2.0.4 and should not be used
     * anymore. Implementations are expected to implement this method calling
     * the {@link #resolve(HttpServletRequest, String)} where the
     * <code>absPath</code> argument is the result of calling the
     * <code>getPathInfo()</code> on the <code>request</code> object.
     *
     * @param request The http servlet request object used to resolve the
     *            resource for. This must not be <code>null</code>.
     * @return The {@link Resource} addressed by
     *         <code>HttpServletRequest.getPathInfo()</code> or a
     *         {@link NonExistingResource} if no such resource can be resolved.
     * @throws NullPointerException If <code>request</code> is <code>null</code>
     *             .
     * @throws org.apache.sling.api.SlingException Or a subclass thereof may be
     *             thrown if an error occurs trying to resolve the resource.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @deprecated as of 2.0.4, use {@link #resolve(HttpServletRequest, String)}
     *             instead.
     */
    @Deprecated
    @NotNull Resource resolve(@NotNull HttpServletRequest request);

    /**
     * Returns a path mapped from the (resource) path
     * 
     * @see {@link ResourceMapper#getMapping(String, HttpServletRequest)}
     */
    @NotNull String map(@NotNull String resourcePath);

    /**
     * Returns an URL mapped from the (resource) path
     * 
     * @see {@link ResourceMapper#getMapping(String, HttpServletRequest)}
     */
    @Nullable String map(@NotNull HttpServletRequest request, @NotNull String resourcePath);

    /**
     * Returns a {@link Resource} object for data located at the given path.
     * <p>
     * This specification does not define the location for resources or the
     * semantics for resource paths. For an implementation reading content from
     * a Java Content Repository, the path could be a
     * <code>javax.jcr.Item</code> path from which the resource object is
     * loaded. In contrast to the {@link #resolve(String)} method, this method
     * does not apply any logic to the path, so the path is used as-is to fetch
     * the content.
     *
     * @param path The absolute path to the resource object to be loaded. The
     *            path may contain relative path specifiers like <code>.</code>
     *            (current location) and <code>..</code> (parent location),
     *            which are resolved by this method. If the path is relative,
     *            that is the first character is not a slash, implementations
     *            are expected to apply a search path algorithm to resolve the
     *            relative path to a resource.
     * @return The <code>Resource</code> object loaded from the path or
     *         <code>null</code> if the path does not resolve to a resource.
     * @throws org.apache.sling.api.SlingException If an error occurs trying to
     *             load the resource object from the path.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @Nullable Resource getResource(@NotNull String path);

    /**
     * Returns a {@link Resource} object for data located at the given path.
     * <p>
     * This specification does not define the location for resources or the
     * semantics for resource paths. For an implementation reading content from
     * a Java Content Repository, the path could be a
     * <code>javax.jcr.Item</code> path from which the resource object is
     * loaded.
     *
     * @param base The base {@link Resource} against which a relative path
     *            argument given by <code>path</code> is resolved. This
     *            parameter may be <code>null</code> if the <code>path</code> is
     *            known to be absolute.
     * @param path The path to the resource object to be loaded. If the path is
     *            relative, i.e. does not start with a slash (<code>/</code>),
     *            the resource relative to the given <code>base</code> resource
     *            is returned. The path may contain relative path specifiers
     *            like <code>.</code> (current location) and <code>..</code>
     *            (parent location), which are resolved by this method.
     * @return The <code>Resource</code> object loaded from the path or
     *         <code>null</code> if the path does not resolve to a resource.
     * @throws org.apache.sling.api.SlingException If an error occurs trying to
     *             load the resource object from the path or if
     *             <code>base</code> is <code>null</code> and <code>path</code>
     *             is relative.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @Nullable Resource getResource(Resource base, @NotNull String path);

    /**
     * Returns the search path used by the {@link #getResource(String)} method
     * to search for resources by relative path. If no search path is set an
     * empty array is returned.
     * <p>
     * The returned array of strings is a copy of the internal value, so
     * modifications to this array have no influence on the operation of the
     * ResourceResolver.
     * <p>
     * The search path of a resource resolver never changes during the lifetime
     * of the resource resolver. Therefore clients may call this method once
     * and use the stored value together with this resource resolver.
     * <p>
     * Each entry in the array is an absolute path terminated with a slash
     * character. Thus to create an absolute path from a search path entry and a
     * relative path, the search path entry and relative path may just be
     * concatenated.
     *
     * @return The array of search paths
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull String[] getSearchPath();

    /**
     * Returns an <code>Iterator</code> of {@link Resource} objects loaded from
     * the children of the given <code>Resource</code>.
     * <p>
     * This specification does not define what the term "child" means. This is
     * left to the implementation to define. For example an implementation
     * reading content from a Java Content Repository, the children could be the
     * {@link Resource} objects loaded from child items of the <code>Item</code>
     * of the given <code>Resource</code>.
     *
     * @param parent The {@link Resource Resource} whose children are requested.
     * @return An <code>Iterator</code> of {@link Resource} objects.
     * @throws NullPointerException If <code>parent</code> is <code>null</code>.
     * @throws org.apache.sling.api.SlingException If any error occurs acquiring
     *             the child resource iterator.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull Iterator<Resource> listChildren(@NotNull Resource parent);

    /**
     * Returns the parent resource of this resource.
     * <p>
     * This method is implemented by getting the parent resource path first
     * calling the {@link ResourceUtil#getParent(String)} method and then to
     * retrieve that resource.
     *
     * @param child The {@link Resource Resource} whose parent is requested.
     * @return The parent resource or {@code null}.
     * @throws NullPointerException If <code>child</code> is <code>null</code>.
     * @throws org.apache.sling.api.SlingException If any error occurs acquiring
     *             the parent resource.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.9 (Sling API Bundle 2.11.0)
     */
    @Nullable Resource getParent(@NotNull Resource child);

    /**
     * Returns an <code>Iterable</code> of {@link Resource} objects loaded from
     * the children of the given <code>Resource</code>.
     * <p>
     * This specification does not define what the term "child" means. This is
     * left to the implementation to define. For example an implementation
     * reading content from a Java Content Repository, the children could be the
     * {@link Resource} objects loaded from child items of the <code>Item</code>
     * of the given <code>Resource</code>.
     *
     * @param parent The {@link Resource Resource} whose children are requested.
     * @return An <code>Iterable</code> of {@link Resource} objects.
     * @throws NullPointerException If <code>parent</code> is <code>null</code>.
     * @throws org.apache.sling.api.SlingException If any error occurs acquiring
     *             the child resource iterator.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    @NotNull Iterable<Resource> getChildren(@NotNull Resource parent);

    /**
     * Searches for resources using the given query formulated in the given
     * language.
     * <p>
     * The semantic meaning of the query and language depend on the actual
     * implementation and storage used for the resources. For JCR repository
     * being used as storage, the query and language parameters are used to
     * create a JCR <code>Query</code> through the <code>QueryManager</code>.
     * The result returned is then based on the <code>NodeIterator</code>
     * provided by the query result.
     *
     * @param query The query string to use to find the resources.
     * @param language The language in which the query is formulated. The
     *                 language should always be specified. However for
     *                 compatibility with older version, if no language
     *                 is specified, "xpath" is used.
     * @return An <code>Iterator</code> of {@link Resource} objects matching the
     *         query.
     * @throws QuerySyntaxException If the query is not syntactically correct
     *             according to the query language indicator.
     * @throws org.apache.sling.api.SlingException If an error occurs querying
     *             for the resources.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull Iterator<Resource> findResources(@NotNull String query, String language);

    /**
     * Queries the storage using the given query formulated in the given
     * language.
     * <p>
     * The semantic meaning of the query and language depend on the actual
     * implementation and storage used for the resources. For JCR repository
     * being used as storage, the query and language parameters are used to
     * create a JCR <code>Query</code> through the <code>QueryManager</code>.
     * The result returned is then based on the <code>RowIterator</code>
     * provided by the query result. The map returned for each row is indexed by
     * the column name and the column value is the JCR <code>Value</code> object
     * converted into the respective Java object, such as <code>Boolean</code>
     * for a value of property type <em>Boolean</em>.
     *
     * @param query The query string to use to find the resources.
     * @param language The language in which the query is formulated. The
     *                 language should always be specified. However for
     *                 compatibility with older version, if no language
     *                 is specified, "xpath" is used.
     * @return An <code>Iterator</code> of <code>Map</code> instances providing
     *         access to the query result.
     * @throws QuerySyntaxException If the query is not syntactically correct
     *             according to the query language indicator.
     * @throws org.apache.sling.api.SlingException If an error occurs querying
     *             for the resources.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull Iterator<Map<String, Object>> queryResources(@NotNull String query, String language);

    /**
     * Checks if the specified resource has any direct child resources.
     *
     * @param resource
     *            the resource to check for direct children
     * @return <code>true</code> if the resource has any child resources
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.4.4 (Sling API Bundle 2.5.0)
     */
    boolean hasChildren(@NotNull Resource resource);

    /**
     * Returns a new <code>ResourceResolver</code> instance based on the given
     * <code>authenticationInfo</code> map and the original authentication info
     * used to create this instance.
     * <p>
     * The new resource resolver is created according to the following
     * algorithm:
     *
     * <pre>
     * Map&lt;String, Object&gt; newAuthenticationInfo = new HashMap(
     *     authenticationInfoOfThisInstance);
     * newAuthenticationInfo.addAll(authenticationInfo);
     * return resourceResolverFactory.getResourceResolver(newAuthenticationInfo);
     * </pre>
     *
     * @param authenticationInfo The map or credential data to overlay the
     *            original credential data with for the creation of a new
     *            resource resolver. This may be <code>null</code> in which case
     *            the same credential data is used as was used to create this
     *            instance.
     * @return A new <code>ResourceResolver</code>
     * @throws LoginException If an error occurs creating the new
     *             <code>ResourceResolver</code> with the provided credential
     *             data.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.1 (Sling API Bundle 2.1.0)
     */
    @NotNull ResourceResolver clone(Map<String, Object> authenticationInfo)
            throws LoginException;

    /**
     * Returns <code>true</code> if this resource resolver is still usable.
     * This method tests different things like if it has not been closed
     * yet or if any of the used resource providers is not usable anymore.
     * <p>
     * Unlike the other methods defined in this interface, this method will
     * never throw an exception even after the resource resolver has been
     * {@link #close() closed}.
     *
     * @return <code>true</code> if the resource resolver is still usable.
     *      Once the resource resolver has been closed or a used resource
     *      provider has been unregistered, this method returns <code>false</code>.
     * @since 2.1 (Sling API Bundle 2.1.0)
     */
    boolean isLive();

    /**
     * Close this resource resolver. This method should be called by clients
     * when the resource resolver is not used anymore. Once this method has been
     * called, the resource resolver is considered unusable and will throw
     * exceptions if still used - with the exception of this method, which
     * can be called several times with no ill effects.
     *
     * A resolver may also be closed implicitly in case when the {@link ResourceResolverFactory}
     * which was used to create this resolver is no longer active or
     * any of the used resource providers is no longer active.
     *
     * @since 2.1 (Sling API Bundle 2.1.0)
     * @see ResourceResolver Resource Resolver (section lifecycle)
     */
    @Override
    void close();

    /**
     * Get the user ID, if any, associated with this resource resolver. The
     * meaning of this identifier is an implementation detail defined by the
     * underlying repository. This method may return null.
     *
     * @return the user ID
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.1 (Sling API Bundle 2.1.0)
     */
    @Nullable String getUserID();

    /**
     * Returns an iterator of attribute names whose value can be retrieved
     * calling the {@link #getAttribute(String)} method. This iterator will not
     * include any attributes which are not accessible.
     *
     * @return An iterator of attribute names
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @NotNull Iterator<String> getAttributeNames();

    /**
     * Returns the value of the given resource resolver attribute or
     * <code>null</code> if the attribute is not set (or not visible as is the
     * case of the {@link ResourceResolverFactory#PASSWORD} or other security
     * sensitive attributes).
     *
     * @param name The name of the attribute to access
     * @return The value of the attribute or <code>null</code> if the attribute
     *         is not set or not accessible.
     * @throws NullPointerException if <code>name</code> is <code>null</code>.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     */
    @Nullable Object getAttribute(@NotNull String name);

    /**
     * Delete the resource
     *
     * Deleting a non existing resource leads to no operation nor exception.
     *
     * The changes are transient and require a call to {@link #commit()} for persisting.
     *
     * @param resource The resource to delete
     *
     * @throws NullPointerException if the resource parameter is null
     * @throws UnsupportedOperationException If the resource provider does not allow to
     *                                       delete this resource.
     * @throws PersistenceException If the operation fails.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    void delete(@NotNull Resource resource)
    throws PersistenceException;

    /**
     * Add a child resource to the given parent resource
     * The changes are transient and require a call to {@link #commit()} for persisting.
     *
     * @param parent The parent resource
     * @param name   The name of the child resource - this is a plain name, not a path!
     * @param properties Optional properties for the resource
     * @return The new resource
     *
     * @throws NullPointerException if the resource parameter or name parameter is null
     * @throws IllegalArgumentException if the name contains a slash
     * @throws UnsupportedOperationException If the resource provider does not allow to
     *                                       create a resource at that location.
     * @throws PersistenceException If the operation fails.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    @NotNull Resource create(@NotNull Resource parent, @NotNull String name, Map<String, Object> properties)
    throws PersistenceException;

    /**
     * Revert all pending changes.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    void revert();

    /**
     * Persist all pending changes.
     *
     * @throws PersistenceException If persisting the changes fails.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    void commit() throws PersistenceException;

    /**
     * Are there any pending changes?
     * @return {@code true} if there are pending changes.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.2 (Sling API Bundle 2.2.0)
     */
    boolean hasChanges();

    /**
     * Returns the super type of the given resource. This method checks first if
     * the resource itself knows its super type by calling
     * {@link Resource#getResourceSuperType()}. If that returns
     * <code>null</code> {@link #getParentResourceType(String)}
     * is invoked with the resource type of the resource.
     *
     * @param resource The resource to return the resource super type for.
     * @return The resource super type or <code>null</code>. This
     *         method also returns <code>null</code> if the
     *         provided resource is <code>null</code>
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    @Nullable String getParentResourceType(final Resource resource);

    /**
     * Returns the super type of the given resource type. This method converts
     * the resource type to a resource path and checks the corresponding resource
     * (considering the search path).
     * If the resource exists, the {@link Resource#getResourceSuperType()} method
     * is called.
     *
     * @param resourceType The resource type whose super type is to be returned.
     * @return the super type of the {@code resourceType} or
     *         {@code null} if the resource given by the resource type does not exist or
     *         if it returns {@code null} for its super type. It also returns
     *         {@code null} if {@code resourceType} is null.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    public @Nullable String getParentResourceType(final String resourceType);

    /**
     * Returns <code>true</code> if the resource type or any of the resource's
     * super type(s) equals the given resource type.
     *
     * In case the type of the given resource or the given resource type starts with one of the resource resolver's search paths
     * it is converted to a relative resource type by stripping off the resource resolver's search path
     * before doing the comparison.
     *
     * @param resource The resource to check
     * @param resourceType The resource type to check this resource against.
     * @return <code>true</code> if the resource type or any of the resource's
     *         super type(s) equals the given resource type. <code>false</code>
     *         is also returned if <code>resource</code> or<code>resourceType</code>
     *         are <code>null</code>.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    boolean isResourceType(final Resource resource, final String resourceType);

    /**
     * The resolver is updated to reflect the latest state.
     * Resources which have changes pending are not discarded.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    void refresh();

    /**
     * This method copies the subgraph rooted at, and including, the resource at
     * <code>srcAbsPath</code> to the new location at <code>destAbsPath</code> and
     * adds it as a child node of the resource at <code>destAbsPath</code>.
     *
     * If the copy operation is within a single resource provider, the resource provider
     * can use an optimized copy operation. Otherwise the resource resolver copies resources
     * from one provider to another.
     *
     * The resource at <code>destAbsPath</code> needs to exist, if not a {@code PersistenceException}
     * is thrown. If a child resource with the same name already exists at <code>destAbsPath</code>
     * a {@code PersistenceException} is thrown. If the resource at {@code srcAbsPath} does not exist,
     * a {@code PersistenceException} is thrown.
     *
     * The changes are transient and require a call to {@link #commit()} for persisting.
     *
     * @param srcAbsPath  the path of the resource to be copied.
     * @param destAbsPath the location to which the resource at
     *                    <code>srcAbsPath</code> is to be copied.
     * @return The destination resource.
     * @throws PersistenceException If an error occurs.
     * @throws UnsupportedOperationException If one of the destination resource providers does
     *                                       not allow to create a resource at that location.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.9 (Sling API Bundle 2.11.0)
     */
    Resource copy(final String srcAbsPath,
              final String destAbsPath) throws PersistenceException;

    /**
     * This method moves the subgraph rooted at, and including, the resource at
     * <code>srcAbsPath</code> to the new location at <code>destAbsPath</code> and
     * adds it as a child node of the resource at <code>destAbsPath</code>.
     *
     * If the move operation is within a single resource provider, the resource provider
     * can use an optimized move operation. Otherwise the resource resolver moves resources
     * from one provider to another.
     *
     * The resource at <code>destAbsPath</code> needs to exist, if not a {@code PersistenceException}
     * is thrown. If a child resource with the same name already exists at <code>destAbsPath</code>
     * a {@code PersistenceException} is thrown. If the resource at {@code srcAbsPath} does not exist,
     * a {@code PersistenceException} is thrown.
     *
     * The changes are transient and require a call to {@link #commit()} for persisting.
     *
     * @param srcAbsPath  the path of the resource to be copied.
     * @param destAbsPath the location to which the resource at
     *                    <code>srcAbsPath</code> is to be moved.
     * @return The destination resource.
     * @throws PersistenceException If an error occurs.
     * @throws UnsupportedOperationException If one of the destination resource providers does
     *                                       not allow to create a resource at that location.
     * @throws IllegalStateException if this resource resolver has already been
     *             {@link #close() closed}.
     * @since 2.9 (Sling API Bundle 2.11.0)
     */
    Resource move(final String srcAbsPath,
              final String destAbsPath) throws PersistenceException;
}
