001    // Copyright 2010, 2011 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    
015    package org.apache.tapestry5.internal.services.javascript;
016    
017    import org.apache.tapestry5.Asset;
018    import org.apache.tapestry5.SymbolConstants;
019    import org.apache.tapestry5.func.F;
020    import org.apache.tapestry5.func.Flow;
021    import org.apache.tapestry5.internal.TapestryInternalUtils;
022    import org.apache.tapestry5.ioc.annotations.Symbol;
023    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
024    import org.apache.tapestry5.ioc.services.SymbolSource;
025    import org.apache.tapestry5.ioc.services.ThreadLocale;
026    import org.apache.tapestry5.services.AssetSource;
027    import org.apache.tapestry5.services.javascript.JavaScriptStack;
028    import org.apache.tapestry5.services.javascript.StylesheetLink;
029    
030    import java.util.Collections;
031    import java.util.List;
032    import java.util.Locale;
033    
034    /**
035     * JavaScriptStack for core components.
036     *
037     * @since 5.2.0
038     */
039    public class CoreJavaScriptStack implements JavaScriptStack {
040      private final boolean productionMode;
041    
042      private final SymbolSource symbolSource;
043    
044      private final AssetSource assetSource;
045    
046      private final ThreadLocale threadLocale;
047    
048      private final List<Asset> javaScriptStack, stylesheetStack;
049    
050      private static final String ROOT = "org/apache/tapestry5";
051    
052      private static final String[] CORE_JAVASCRIPT = new String[]
053              {
054                      // Core scripts added to any page that uses scripting
055    
056                      "${tapestry.underscore}",
057    
058                      "${tapestry.scriptaculous}/prototype.js",
059    
060                      "${tapestry.scriptaculous}/scriptaculous.js",
061    
062                      "${tapestry.scriptaculous}/effects.js",
063    
064                      // Below uses functions defined by the prior three.
065    
066                      // Order is important, there are some dependencies
067                      // going on here. Switching over to a more managed module system
068                      // is starting to look like a really nice idea!
069    
070                      ROOT + "/t5-core.js",
071    
072                      ROOT + "/t5-spi.js",
073    
074                      ROOT + "/t5-prototype.js",
075    
076                      ROOT + "/t5-init.js",
077    
078                      ROOT + "/t5-pubsub.js",
079    
080                      ROOT + "/t5-events.js",
081    
082                      ROOT + "/t5-dom.js",
083    
084                      ROOT + "/t5-console.js",
085    
086                      ROOT + "/t5-ajax.js",
087    
088                      ROOT + "/t5-formfragment.js",
089    
090                      ROOT + "/t5-alerts.js",
091    
092                      ROOT + "/tapestry.js",
093    
094                      ROOT + "/tapestry-console.js",
095    
096                      ROOT + "/tree.js",
097              };
098    
099      // Because of changes to the logic of how stylesheets get incorporated, the default stylesheet
100      // was removed, the logic for it is now in TapestryModule.contributeMarkupRenderer().
101    
102      private static final String[] CORE_STYLESHEET = new String[]
103              {
104                      ROOT + "/tapestry-console.css",
105    
106                      ROOT + "/t5-alerts.css",
107    
108                      ROOT + "/tree.css"
109              };
110    
111      public CoreJavaScriptStack(
112              @Symbol(SymbolConstants.PRODUCTION_MODE)
113              boolean productionMode,
114    
115              SymbolSource symbolSource,
116    
117              AssetSource assetSource,
118    
119              ThreadLocale threadLocale) {
120        this.symbolSource = symbolSource;
121        this.productionMode = productionMode;
122        this.assetSource = assetSource;
123        this.threadLocale = threadLocale;
124    
125        javaScriptStack = convertToAssets(CORE_JAVASCRIPT);
126        stylesheetStack = convertToAssets(CORE_STYLESHEET);
127      }
128    
129      public String getInitialization() {
130        return productionMode ? null : "Tapestry.DEBUG_ENABLED = true;";
131      }
132    
133      public List<String> getStacks() {
134        return Collections.emptyList();
135      }
136    
137      private List<Asset> convertToAssets(String[] paths) {
138        List<Asset> assets = CollectionFactory.newList();
139    
140        for (String path : paths) {
141          assets.add(expand(path, null));
142        }
143    
144        return Collections.unmodifiableList(assets);
145      }
146    
147      private Asset expand(String path, Locale locale) {
148        String expanded = symbolSource.expandSymbols(path);
149    
150        return assetSource.getAsset(null, expanded, locale);
151      }
152    
153      public List<Asset> getJavaScriptLibraries() {
154        Asset messages = assetSource.getAsset(null, ROOT + "/tapestry-messages.js", threadLocale.getLocale());
155    
156        return createStack(javaScriptStack, messages).toList();
157      }
158    
159      public List<StylesheetLink> getStylesheets() {
160        return createStack(stylesheetStack).map(TapestryInternalUtils.assetToStylesheetLink)
161                .toList();
162      }
163    
164      private Flow<Asset> createStack(List<Asset> stack, Asset... assets) {
165        return F.flow(stack).append(assets);
166      }
167    }