You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/05 23:46:42 UTC
svn commit: r1089250 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/services/javascript/ test/conf/
test/groovy/org/apache/tapestry5/services/
test/groovy/org/apache/tapestry5/services/javascript/
Author: hlship
Date: Tue Apr 5 21:46:42 2011
New Revision: 1089250
URL: http://svn.apache.org/viewvc?rev=1089250&view=rev
Log:
TAP5-1502: Make it easier to create JavaScript Stacks using a standard implementation with an OrderedConfiguration
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStackTest.groovy
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java?rev=1089250&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java Tue Apr 5 21:46:42 2011
@@ -0,0 +1,127 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.javascript;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.func.Flow;
+import org.apache.tapestry5.func.Mapper;
+import org.apache.tapestry5.func.Predicate;
+import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.ServiceBindingOptions;
+import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.services.AssetSource;
+
+/**
+ * An extensible implementation of {@link JavaScriptStack} that can be used as the implementation of a service.
+ * The contributions to the service are used to supply the libraries, stylesheets, and initialization for a
+ * JavaScriptStack, allowing the stack to be more dynamically configured. In practice, one will use
+ * {@link ServiceBinder#bind(Class, Class)} and {@link ServiceBindingOptions#withMarker(Class...)} to construct the
+ * service, then use the marker annotation to inject the service when contributing the service into to the
+ * {@link JavaScriptStackSource}.
+ * <p>
+ * A limitation of this implementation is that the contributed assets are not localized at all.
+ *
+ * @since 5.3.0
+ * @see StackExtension
+ */
+@UsesOrderedConfiguration(StackExtension.class)
+public class ExtensibleJavaScriptStack implements JavaScriptStack
+{
+ private final AssetSource assetSource;
+
+ private final List<Asset> libraries;
+
+ private final List<StylesheetLink> stylesheets;
+
+ private final String initialization;
+
+ private final Predicate<StackExtension> by(final StackExtensionType type)
+ {
+ return new Predicate<StackExtension>()
+ {
+ public boolean accept(StackExtension element)
+ {
+ return element.type == type;
+ }
+ };
+ }
+
+ private final Mapper<StackExtension, String> extractValue = new Mapper<StackExtension, String>()
+ {
+ public String map(StackExtension element)
+ {
+ return element.value;
+ };
+ };
+
+ private final Mapper<String, Asset> stringToAsset = new Mapper<String, Asset>()
+ {
+ public Asset map(String value)
+ {
+ return assetSource.getExpandedAsset(value);
+ };
+ };
+
+ private final Mapper<Asset, StylesheetLink> assetToStylesheetLink = new Mapper<Asset, StylesheetLink>()
+ {
+ public StylesheetLink map(Asset asset)
+ {
+ return new StylesheetLink(asset);
+ };
+ };
+
+ public ExtensibleJavaScriptStack(AssetSource assetSource, List<StackExtension> configuration)
+ {
+ this.assetSource = assetSource;
+
+ Flow<StackExtension> extensions = F.flow(configuration);
+
+ libraries = extensions.filter(by(StackExtensionType.LIBRARY)).map(extractValue).map(stringToAsset).toList();
+
+ stylesheets = extensions.filter(by(StackExtensionType.STYLESHEET)).map(extractValue).map(stringToAsset)
+ .map(assetToStylesheetLink).toList();
+
+ List<String> initializations = extensions.filter(by(StackExtensionType.INITIALIZATION)).map(extractValue)
+ .toList();
+
+ initialization = initializations.isEmpty() ? null : InternalUtils.join(initializations, "\n");
+ }
+
+ public List<String> getStacks()
+ {
+ return Collections.emptyList();
+ }
+
+ public List<Asset> getJavaScriptLibraries()
+ {
+ return libraries;
+ }
+
+ public List<StylesheetLink> getStylesheets()
+ {
+ return stylesheets;
+ }
+
+ public String getInitialization()
+ {
+ return initialization;
+ }
+
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java?rev=1089250&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java Tue Apr 5 21:46:42 2011
@@ -0,0 +1,37 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.javascript;
+
+/**
+ * A contribution to an extensible {@link JavaScriptStack}. Such a stack is created in terms of all the contributions.
+ *
+ * @since 5.3.0
+ * @see ExtensibleJavaScriptStack
+ */
+public class StackExtension
+{
+ /** The type of extension. */
+ public final StackExtensionType type;
+
+ /** The value contributed; will have symbols expanded, then be converted to the appropriate type. */
+ public final String value;
+
+ public StackExtension(StackExtensionType type, String value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java?rev=1089250&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java Tue Apr 5 21:46:42 2011
@@ -0,0 +1,43 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.javascript;
+
+import org.apache.tapestry5.ioc.services.SymbolSource;
+import org.apache.tapestry5.services.AssetSource;
+
+/**
+ * Defines the types of extensions to a JavaScript stack that can be contributed to an extensible JavaScript stack.
+ *
+ * @since 5.3.0
+ * @see StackExtension
+ * @see ExtensibleJavaScriptStack
+ */
+public enum StackExtensionType
+{
+ /**
+ * A JavaScript library. The extension value will be converted using {@link AssetSource#getExpandedAsset(String)},
+ * meaning that {@linkplain SymbolSource symbols} will be expanded.
+ */
+ LIBRARY,
+
+ /**
+ * A stylesheet. The extension value will be converted using {@link AssetSource#getExpandedAsset(String)},
+ * meaning that {@linkplain SymbolSource symbols} will be expanded.
+ */
+ STYLESHEET,
+
+ /** Extra JavaScript initialization (rarely used). No symbol expansion takes place. */
+ INITIALIZATION;
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml?rev=1089250&r1=1089249&r2=1089250&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml Tue Apr 5 21:46:42 2011
@@ -23,6 +23,7 @@
<package name="org.apache.tapestry5.dom"/>
<package name="org.apache.tapestry5.runtime"/>
<package name="org.apache.tapestry5.services"/>
+ <package name="org.apache.tapestry5.services.javascript"/>
<package name="org.apache.tapestry5.util"/>
<package name="org.apache.tapestry5.validator"/>
<package name="org.apache.tapestry5.internal"/>
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStackTest.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStackTest.groovy?rev=1089250&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStackTest.groovy (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStackTest.groovy Tue Apr 5 21:46:42 2011
@@ -0,0 +1,98 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.javascript;
+
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.services.AssetSource;
+import org.apache.tapestry5.test.TapestryTestCase;
+import org.testng.annotations.Test;
+
+/** @since 5.3.0 */
+class ExtensibleJavaScriptStackTest extends TapestryTestCase {
+
+ @Test
+ void contributed_libraries_are_expanded() {
+ def lib1path = '${lib1}/lib.js'
+ Asset lib1 = mockAsset()
+ def lib2path = '${lib2}/lib.js'
+ Asset lib2 = mockAsset()
+
+ AssetSource mockSource = mockAssetSource()
+
+ expect(mockSource.getExpandedAsset(lib1path)).andReturn(lib1)
+ expect(mockSource.getExpandedAsset(lib2path)).andReturn(lib2)
+
+ replay()
+
+ ExtensibleJavaScriptStack stack = new ExtensibleJavaScriptStack(mockSource, [
+ new StackExtension (StackExtensionType.LIBRARY, lib1path),
+ new StackExtension (StackExtensionType.LIBRARY, lib2path),
+ ])
+
+ assert stack.stacks.empty
+ assert stack.javaScriptLibraries == [lib1, lib2]
+ assert stack.stylesheets.empty
+ assert stack.initialization == null
+
+ verify()
+ }
+
+ @Test
+ void contributed_stylesheets_are_expanded() {
+ def stylesheet1path = '${stylesheet1}/stylesheet.css'
+ def stylesheet1URL = "/foo/ss1/stylesheet.css"
+ Asset stylesheet1 = mockAsset()
+ def stylesheet2path = '${stylesheet2}/stylesheet.js'
+ def stylesheet2URL = '/foo/ss2/stylesheet.css'
+
+ Asset stylesheet2 = mockAsset()
+
+ AssetSource mockSource = mockAssetSource()
+
+ expect(mockSource.getExpandedAsset(stylesheet1path)).andReturn(stylesheet1)
+ expect(mockSource.getExpandedAsset(stylesheet2path)).andReturn(stylesheet2)
+
+ expect(stylesheet1.toClientURL()).andReturn(stylesheet1URL).atLeastOnce()
+ expect(stylesheet2.toClientURL()).andReturn(stylesheet2URL).atLeastOnce()
+
+ replay()
+
+ ExtensibleJavaScriptStack stack = new ExtensibleJavaScriptStack(mockSource, [
+ new StackExtension (StackExtensionType.STYLESHEET, stylesheet1path),
+ new StackExtension (StackExtensionType.STYLESHEET, stylesheet2path),
+ ])
+
+ assert stack.stacks.empty
+ assert stack.javaScriptLibraries.empty
+ assert stack.stylesheets == [
+ new StylesheetLink(stylesheet1),
+ new StylesheetLink(stylesheet2)
+ ]
+
+ assert stack.initialization == null
+
+ verify()
+ }
+
+ @Test
+ void initializations_are_combined() {
+ ExtensibleJavaScriptStack stack = new ExtensibleJavaScriptStack(null, [
+ new StackExtension (StackExtensionType.INITIALIZATION, "doThis();"),
+ new StackExtension (StackExtensionType.INITIALIZATION, "doThat();"),
+ ])
+
+ assert stack.initialization == "doThis();\ndoThat();"
+ }
+}