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
015package org.apache.tapestry5.internal.services.javascript;
016
017import org.apache.tapestry5.Asset;
018import org.apache.tapestry5.SymbolConstants;
019import org.apache.tapestry5.func.F;
020import org.apache.tapestry5.func.Flow;
021import org.apache.tapestry5.internal.TapestryInternalUtils;
022import org.apache.tapestry5.ioc.annotations.Symbol;
023import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
024import org.apache.tapestry5.ioc.services.SymbolSource;
025import org.apache.tapestry5.ioc.services.ThreadLocale;
026import org.apache.tapestry5.services.AssetSource;
027import org.apache.tapestry5.services.javascript.JavaScriptStack;
028import org.apache.tapestry5.services.javascript.StylesheetLink;
029
030import java.util.Collections;
031import java.util.List;
032import java.util.Locale;
033
034/**
035 * JavaScriptStack for core components.
036 *
037 * @since 5.2.0
038 */
039public 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}