/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript.commonjs.module.provider;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.mozilla.javascript.Scriptable;

/**
 * Implemented by objects that can provide the source text for the script. The design of the
 * interface supports cache revalidation.
 *
 * @author Attila Szegedi
 * @version $Id: ModuleSourceProvider.java,v 1.3 2011/04/07 20:26:12 hannes%helma.at Exp $
 */
public interface ModuleSourceProvider {
    /**
     * A special return value for {@link #loadSource(String, Scriptable, Object)} and {@link
     * #loadSource(URI, URI, Object)} that signifies that the cached representation is still valid
     * according to the passed validator.
     */
    public static final ModuleSource NOT_MODIFIED = new ModuleSource(null, null, null, null, null);

    /**
     * Returns the script source of the requested module. More specifically, it resolves the module
     * ID to a resource. If it can not resolve it, null is returned. If the caller passes a non-null
     * validator, and the source provider recognizes it, and the validator applies to the same
     * resource that the provider would use to load the source, and the validator validates the
     * current cached representation of the resource (using whatever semantics for validation that
     * this source provider implements), then {@link #NOT_MODIFIED} should be returned. Otherwise,
     * it should return a {@link ModuleSource} object with the actual source text of the module,
     * preferrably a validator for it, and a security domain, where applicable.
     *
     * @param moduleId the ID of the module. An implementation must only accept an absolute ID,
     *     starting with a term.
     * @param paths the value of the require() function's "paths" attribute. If the require()
     *     function is sandboxed, it will be null, otherwise it will be a JavaScript Array object.
     *     It is up to the provider implementation whether and how it wants to honor the contents of
     *     the array.
     * @param validator a validator for an existing loaded and cached module. This will either be
     *     null, or an object that this source provider returned earlier as part of a {@link
     *     ModuleSource}. It can be used to validate the existing cached module and avoid reloading
     *     it.
     * @return a script representing the code of the module. Null should be returned if the script
     *     is not found. {@link #NOT_MODIFIED} should be returned if the passed validator validates
     *     the current representation of the module (the currently cached module script).
     * @throws IOException if there was an I/O problem reading the script
     * @throws URISyntaxException if the final URI could not be constructed.
     * @throws IllegalArgumentException if the module ID is syntactically not a valid absolute
     *     module identifier.
     */
    public ModuleSource loadSource(String moduleId, Scriptable paths, Object validator)
            throws IOException, URISyntaxException;

    /**
     * Returns the script source of the requested module from the given URI. The URI is absolute but
     * does not contain a file name extension such as ".js", which may be specific to the
     * ModuleSourceProvider implementation.
     *
     * <p>If the resource is not found, null is returned. If the caller passes a non-null validator,
     * and the source provider recognizes it, and the validator applies to the same resource that
     * the provider would use to load the source, and the validator validates the current cached
     * representation of the resource (using whatever semantics for validation that this source
     * provider implements), then {@link #NOT_MODIFIED} should be returned. Otherwise, it should
     * return a {@link ModuleSource} object with the actual source text of the module, preferrably a
     * validator for it, and a security domain, where applicable.
     *
     * @param uri the absolute URI from which to load the module source, but without an extension
     *     such as ".js".
     * @param baseUri the module path base URI from which <code>uri</code> was derived.
     * @param validator a validator for an existing loaded and cached module. This will either be
     *     null, or an object that this source provider returned earlier as part of a {@link
     *     ModuleSource}. It can be used to validate the existing cached module and avoid reloading
     *     it.
     * @return a script representing the code of the module. Null should be returned if the script
     *     is not found. {@link #NOT_MODIFIED} should be returned if the passed validator validates
     *     the current representation of the module (the currently cached module script).
     * @throws IOException if there was an I/O problem reading the script
     * @throws URISyntaxException if the final URI could not be constructed
     */
    public ModuleSource loadSource(URI uri, URI baseUri, Object validator)
            throws IOException, URISyntaxException;
}
