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}