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