    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.services.javascript;
    014
    015import org.apache.tapestry5.ioc.Resource;
    016
    017import java.util.Arrays;
    018import java.util.List;
    019
    020/**
    021 * Used to define a <a href="http://requirejs.org/docs/api.html#config-shim">module shim</a>, used to adapt non-AMD JavaScript libraries
    022 * to operate like proper modules.  This information is used to build up a list of dependencies for the contributed JavaScript module,
    023 * and to identify the resource to be streamed to the client.
    024 *
    025 * Instances of this class are contributed to the {@link ModuleManager} service;  the contribution key is the module name
    026 * (typically, a single word).
    027 *
    028 * In some cases, an instance may be created and contributed to override a default module; if the module has no dependencies,
    029 * exports, or initExpression (that is, if it is a proper AMD module, where such dependencies are provided inside
    030 * the module itself), then no client-side shim configuration will be written for the module, but requests for the
    031 * module will be satisfied by the resource.'
    032 *
    033 * @since 5.4
    034 * @see AMDWrapper
    035 */
    036public final class JavaScriptModuleConfiguration
    037{
    038    /**
    039     * The resource for this shim module.
    040     */
    041    public final Resource resource;
    042
    043    /**
    044     * The names of other shim modules that should be loaded before this shim module.
    045     */
    046    private List<String> dependencies;
    047
    048    /**
    049     * Optional (but desirable) value exported by the shim module.
    050     */
    051    private String exports;
    052
    053    private String initExpression;
    054
    055    private boolean needsConfiguration;
    056
    057    public JavaScriptModuleConfiguration(Resource resource)
    058    {
    059        assert resource != null;
    060
    061        this.resource = resource;
    062    }
    063
    064    /**
    065     * A list of other module names the shim depends on.
    066     *
    067     * @param moduleNames
    068     * @return this JavaScriptModuleConfiguration for further configuration
    069     */
    070    public JavaScriptModuleConfiguration dependsOn(String... moduleNames)
    071    {
    072        assert moduleNames.length > 0;
    073
    074        dependencies = Arrays.asList(moduleNames);
    075
    076        needsConfiguration = true;
    077
    078        return this;
    079    }
    080
    081    public List<String> getDependencies()
    082    {
    083        return dependencies;
    084    }
    085
    086    /**
    087     * The name of a global variable exported by the module. This will be the value injected into
    088     * modules that depend on the shim.
    089     *
    090     * @return this JavaScriptModuleConfiguration for further configuration
    091     */
    092    public JavaScriptModuleConfiguration exports(String exports)
    093    {
    094        assert exports != null;
    095
    096        this.exports = exports;
    097
    098        needsConfiguration = true;
    099
    100        return this;
    101    }
    102
    103    public String getExports()
    104    {
    105        return exports;
    106    }
    107
    108    /**
    109     * Used as an alternative to {@linkplain #exports(String)}, this allows a short expression to be specified; the
    110     * expression is used to initialize, clean up, and (usually) return the module's export value. For Underscore, this
    111     * would be "_.noConflict()".  If the expression returns null, then the exports value is used.
    112     *
    113     * In RequireJS 2.1.1 (the version shipped with Tapestry, currently), an init function is not invoked unless
    114     * the shim also defines an exports. See <a href="https://github.com/jrburke/requirejs/issues/517">RequireJS issue 517</a>.
    115     * At this time, you should specify {@link #exports} even if you provide a {@link #initializeWith(String)}}.
    116     *
    117     * @param expression
    118     *         initialization expression
    119     * @return this JavaScriptModuleConfiguration, for further configuration
    120     */
    121    public JavaScriptModuleConfiguration initializeWith(String expression)
    122    {
    123        assert expression != null;
    124
    125        this.initExpression = expression;
    126
    127        needsConfiguration = true;
    128
    129        return this;
    130    }
    131
    132    public String getInitExpression()
    133    {
    134        return initExpression;
    135    }
    136
    137    /**
    138     * Returns true if the module contains any additional configuration beyond its {@link Resource}.
    139     */
    140    public boolean getNeedsConfiguration()
    141    {
    142        return needsConfiguration;
    143    }
    144}