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}