You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by ro...@apache.org on 2009/07/18 00:53:32 UTC
svn commit: r795264 [2/3] - in /tapestry/tapestry5/trunk: src/site/apt/dev/
src/site/apt/guide/
tapestry-core/src/main/java/org/apache/tapestry5/annotations/
tapestry-core/src/main/java/org/apache/tapestry5/internal/
tapestry-core/src/main/java/org/apa...
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,348 @@
+// Copyright 2009 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.internal.transform;
+
+import org.apache.tapestry5.services.*;
+import org.apache.tapestry5.model.MutableComponentModel;
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.internal.*;
+import org.apache.tapestry5.internal.bindings.LiteralBinding;
+import org.apache.tapestry5.ioc.util.BodyBuilder;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.Binding;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.lang.reflect.Modifier;
+
+/**
+ * Responsible for identifying, via the {@link org.apache.tapestry5.annotations.BindParameter} annotation,
+ * mixin fields that should be bound to a core-component parameter value.
+ *
+ * @since 5.2.0.0
+ */
+public class BindParameterWorker implements ComponentClassTransformWorker
+{
+
+ private static final String EQUAL_METHOD_NAME = BindParameterWorker.class.getName() + ".equal";
+
+ public void transform(final ClassTransformation transformation, MutableComponentModel model)
+ {
+ List<String> fieldNames = transformation.findFieldsWithAnnotation(BindParameter.class);
+
+ for(String fieldName : fieldNames)
+ {
+ BindParameter annotation = transformation.getFieldAnnotation(fieldName, BindParameter.class);
+ convertFieldIntoContainerBoundParameter(fieldName, annotation, transformation, model);
+ }
+
+ }
+
+ private void convertFieldIntoContainerBoundParameter(String name, BindParameter annotation, ClassTransformation transformation,
+ MutableComponentModel model)
+ {
+ transformation.claimField(name, annotation);
+
+ String boundParameterName = getBoundParameterName(name, annotation.name());
+ String[] parentParameterNames = getParentParameterNames(name, annotation.value());
+
+
+ String type = transformation.getFieldType(name);
+
+ //we can't do this exactly the same as parameter. We can't know at transformation time which parameter
+ //this thing will be linked to, because it could be wired to any number of different components.
+ //So we have to wait until runtime to examine caching and whether we should cache, rather than
+ //constructing the class differently based on caching or not.
+ String cachedFieldName = transformation.addField(Modifier.PRIVATE, "boolean", name + "_cached");
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ String accessFieldName = addBoundParameterSetup(name,
+ boundParameterName, parentParameterNames,
+ cachedFieldName, type, resourcesFieldName,
+ transformation);
+
+ addReaderMethod(name, cachedFieldName, accessFieldName, boundParameterName, type, resourcesFieldName,
+ transformation);
+
+ addWriterMethod(name, cachedFieldName, accessFieldName, boundParameterName, type, resourcesFieldName,
+ transformation);
+ }
+
+
+ /**
+ * Returns the name of a field that stores whether the parameter binding is invariant.
+ */
+ private String addBoundParameterSetup(String fieldName, String boundParameterName, String[] parentParameterNames,
+ String cachedFieldName, String fieldType,
+ String resourcesFieldName, ClassTransformation transformation)
+ {
+ String accessFieldName = transformation.addField(Modifier.PRIVATE, ParameterAccess.class.getName(),
+ fieldName + "_access");
+
+ String parentNamesField = transformation.addField(Modifier.PRIVATE, String[].class.getName(),
+ fieldName + "_parentparameternames");
+
+ String defaultFieldName = transformation.addField(Modifier.PRIVATE, fieldType, fieldName + "_default");
+
+ BodyBuilder builder = new BodyBuilder().begin();
+
+ builder.addln("%s = new String[%d];",parentNamesField,parentParameterNames.length);
+
+ for(int i=0;i<parentParameterNames.length;i++)
+ {
+ builder.addln("%s[%d]=\"%s\";",parentNamesField,i,parentParameterNames[i]);
+ }
+
+ builder.addln("%s = %s.getContainerBoundParameterAccess(\"%s\",%s);",
+ accessFieldName,
+ resourcesFieldName,
+ boundParameterName,
+ parentNamesField);
+
+ // Store the current value of the field into the default field. This value will
+ // be used to reset the field after rendering.
+
+ builder.addln("%s = %s;", defaultFieldName, fieldName);
+
+
+ addListenerSetup(fieldName, fieldType, boundParameterName, parentParameterNames, accessFieldName, builder,
+ transformation);
+
+ builder.end();
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
+ .toString());
+
+ // Now, when the component completes rendering, ensure that any variant parameters are
+ // are returned to default value. This isn't necessary when the parameter is not cached,
+ // because (unless the binding is invariant), there's no value to get rid of (and if it is
+ // invariant, there's no need to get rid of it).
+ // as with reader/writer methods, we have to do the caching check at runtime.
+ builder.clear();
+
+ builder.addln("if (%s.shouldCache() && ! %1$s.isInvariant())", accessFieldName);
+ builder.begin();
+ builder.addln("%s = %s;", fieldName, defaultFieldName);
+ builder.addln("%s = false;", cachedFieldName);
+ builder.end();
+
+ // Clean up after the component renders.
+
+ String body = builder.toString();
+
+ transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, body);
+
+ // And again, when the page is detached (TAPESTRY-2460)
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE, body);
+
+ return accessFieldName;
+ }
+
+ private void addListenerSetup(
+ String fieldName,
+ String fieldType,
+ String boundParameterName,
+ String[] parentParameterNames,
+ String accessFieldName,
+ BodyBuilder builder,
+ ClassTransformation transformation)
+ {
+ transformation.addImplementedInterface(ParameterChangeListener.class);
+ builder.addln("%s.registerParameterChangeListener($0);",accessFieldName);
+
+ TransformMethodSignature signature = new TransformMethodSignature(Modifier.PUBLIC, "void", "parameterChanged",
+ new String[] {ParameterChangedEvent.class.getName()}, null);
+
+ BodyBuilder changedBody = new BodyBuilder().begin();
+ //by this point, we know that there is at least one entry in parent Parameter Names.
+ changedBody.add("if (%s($1, \"%s\")", EQUAL_METHOD_NAME, parentParameterNames[0]);
+ for(int i=1; i<parentParameterNames.length; i++)
+ {
+ changedBody.add(" || %s($1, \"%s\")", EQUAL_METHOD_NAME, parentParameterNames[i]);
+ }
+ changedBody.add(")").begin();
+
+ String cast = TransformUtils.getWrapperTypeName(fieldType);
+
+ if (TransformUtils.isPrimitive(fieldType))
+ changedBody.addln("%s = ((%s) $1.getNewValue()).%s();",
+ fieldName, cast, TransformUtils.getUnwrapperMethodName(fieldType));
+ else
+ changedBody.addln("%s = (%s) $1.getNewValue();",fieldName, cast);
+
+ changedBody.addln("return;").end();
+
+ changedBody.end();
+
+ transformation.extendMethod(signature,changedBody.toString());
+
+ }
+
+ private void addWriterMethod(String fieldName, String cachedFieldName, String accessFieldName,
+ String boundParameterName, String fieldType,
+ String resourcesFieldName, ClassTransformation transformation)
+ {
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ // Before the component is loaded, updating the property sets the default value
+ // for the parameter. The value is stored in the field, but will be
+ // rolled into default field inside containingPageDidLoad().
+
+ builder.addln("if (! %s.isLoaded())", resourcesFieldName);
+ builder.begin();
+ builder.addln("%s = $1;", fieldName);
+ builder.addln("return;");
+ builder.end();
+
+ //unregistering the listener from the parameter change listener list avoids double-setting the field,
+ builder.addln("%s.unregisterParameterChangeListener($0);",accessFieldName);
+
+ // Always start by updating the parameter; this will implicitly check for
+ // read-only or unbound parameters. $1 is the single parameter
+ // to the method.
+ builder.addln("%s.write(($w)$1);", accessFieldName);
+ builder.addln("%s = $1;",fieldName);
+ builder.addln("%s.registerParameterChangeListener($0);",accessFieldName);
+
+ //note that there's no way of knowing at class transformation time which component a mixin will
+ //be associated with and, further more, no way of knowing which @Parameter a mixin field will be
+ //@BindParameter'ed to. So we have to generate caching code that works at runtime, rather than
+ //including or not including caching logic at transformation time.
+ builder.addln("if (%s.shouldCache())",accessFieldName).begin();
+ builder.addln("%s = %s.isRendering();",cachedFieldName, resourcesFieldName).end();
+ builder.end();
+
+ String methodName = transformation.newMemberName("update_boundparameter", boundParameterName);
+
+ TransformMethodSignature signature = new TransformMethodSignature(Modifier.PRIVATE, "void", methodName,
+ new String[] {fieldType}, null);
+
+ transformation.addMethod(signature, builder.toString());
+
+ builder.clear();
+
+ //add the catch because if we don't re-register the class as a parameter change listener, it's value
+ //could wind up stale, and write can throw an exception.
+ builder.begin();
+ builder.addln("%s.registerParameterChangeListener($0);", accessFieldName);
+ builder.addln("throw $e;");
+ builder.end();
+
+ transformation.addCatch(signature,Exception.class.getName(),builder.toString());
+
+ transformation.replaceWriteAccess(fieldName, methodName);
+ }
+
+ /**
+ * Adds a private method that will be the replacement for read-access to the field.
+ */
+ private void addReaderMethod(String fieldName, String cachedFieldName, String accessFieldName,
+ String boundParameterName, String fieldType, String resourcesFieldName,
+ ClassTransformation transformation)
+ {
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ // While the component is still loading, or when the value for the component is cached,
+ // or if the value is not bound, then return the current value of the field.
+
+ builder.addln("if ((%s.shouldCache() && %s) || ! %s.isLoaded() || ! %s.isBound()) return %s;",
+ accessFieldName, cachedFieldName, resourcesFieldName, accessFieldName, fieldName);
+
+ String cast = TransformUtils.getWrapperTypeName(fieldType);
+
+ // The ($r) cast will convert the result to the method return type; generally
+ // this does nothing. but for primitive types, it will unwrap
+ // the wrapper type back to a primitive. We pass the desired type name
+ // to readParameter(), since its easier to convert it properly to
+ // a type on that end than in the generated code.
+
+ builder.addln("%s result = ($r) ((%s) %s.read(\"%2$s\"));", fieldType, cast, accessFieldName);
+
+ // If the binding is invariant, then it's ok to cache. Othewise, its only
+ // ok to cache if a) the @Parameter says to cache and b) the component
+ // is rendering at the point when field is accessed.
+
+ builder.add("if (%s.isInvariant() || (%1$s.shouldCache() && %s.isRendering()))",
+ accessFieldName, resourcesFieldName);
+
+ builder.begin();
+ builder.addln("%s = result;", fieldName);
+ builder.addln("%s = true;", cachedFieldName);
+ builder.end();
+
+ builder.addln("return result;");
+ builder.end();
+
+ String methodName = transformation.newMemberName("read_boundparameter", boundParameterName);
+
+ TransformMethodSignature signature = new TransformMethodSignature(Modifier.PRIVATE, fieldType, methodName, null,
+ null);
+
+ transformation.addMethod(signature, builder.toString());
+
+ transformation.replaceReadAccess(fieldName, methodName);
+ }
+
+ private String getBoundParameterName(String fieldName, String annotatedName)
+ {
+ if (InternalUtils.isNonBlank(annotatedName)) return annotatedName;
+
+ return InternalUtils.stripMemberName(fieldName);
+ }
+
+ private String[] getParentParameterNames(String fieldName, String... names)
+ {
+ List<String> temp = CollectionFactory.newList(names);
+ for(Iterator<String> it = temp.iterator();it.hasNext(); )
+ {
+ String name =it.next();
+ if (InternalUtils.isBlank(name)) it.remove();
+ }
+ if (temp.isEmpty())
+ return new String[] {InternalUtils.stripMemberName(fieldName)};
+
+ return temp.toArray(new String[temp.size()]);
+ }
+
+ /**
+ * Invoked from generated code as part of the handling of parameter default methods.
+ */
+ public static void bind(String parameterName, InternalComponentResources resources, Object value)
+ {
+ if (value == null) return;
+
+ if (value instanceof Binding)
+ {
+ Binding binding = (Binding) value;
+
+ resources.bindParameter(parameterName, binding);
+ return;
+ }
+
+ resources.bindParameter(parameterName, new LiteralBinding(null, "default " + parameterName, value));
+ }
+
+ public static <T> boolean equal(T left, T right)
+ {
+ return TapestryInternalUtils.isEqual(left,right);
+ }
+
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java Fri Jul 17 22:53:30 2009
@@ -20,9 +20,11 @@
import org.apache.tapestry5.internal.KeyValue;
import org.apache.tapestry5.internal.TapestryInternalUtils;
import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.ioc.Orderable;
import org.apache.tapestry5.ioc.internal.services.StringLocation;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.TapestryException;
import org.apache.tapestry5.model.ComponentModel;
import org.apache.tapestry5.model.MutableComponentModel;
import org.apache.tapestry5.model.MutableEmbeddedComponentModel;
@@ -95,8 +97,20 @@
if (annotation == null) return;
- for (Class c : annotation.value())
- model.addMixin(c.getName());
+ boolean orderEmpty = annotation.order().length == 0;
+
+ if (!orderEmpty && annotation.order().length != annotation.value().length)
+ throw new TapestryException(TransformMessages.badMixinConstraintLength(annotation,fieldName),
+ model,null);
+
+
+ for (int i=0; i<annotation.value().length;i++)
+ {
+ String[] constraints = orderEmpty?
+ new String[0]:
+ TapestryInternalUtils.splitMixinConstraints(annotation.order()[i]);
+ model.addMixin(annotation.value()[i].getName(), constraints);
+ }
}
private void addMixinTypes(String fieldName, ClassTransformation transformation,
@@ -108,8 +122,9 @@
for (String typeName : annotation.value())
{
- String mixinClassName = resolver.resolveMixinTypeToClassName(typeName);
- model.addMixin(mixinClassName);
+ Orderable<String> typeAndOrder = TapestryInternalUtils.mixinTypeAndOrder(typeName);
+ String mixinClassName = resolver.resolveMixinTypeToClassName(typeAndOrder.getTarget());
+ model.addMixin(mixinClassName,typeAndOrder.getConstraints());
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java Fri Jul 17 22:53:30 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 2009 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.
@@ -50,12 +50,14 @@
String mixinType = annotation.value();
+ String[] order = annotation.order();
+
String fieldType = transformation.getFieldType(fieldName);
String mixinClassName = InternalUtils.isBlank(mixinType) ? fieldType : resolver
.resolveMixinTypeToClassName(mixinType);
- model.addMixinClassName(mixinClassName);
+ model.addMixinClassName(mixinClassName,order);
transformation.makeReadOnly(fieldName);
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker.java Fri Jul 17 22:53:30 2009
@@ -16,8 +16,8 @@
import org.apache.tapestry5.Binding;
import org.apache.tapestry5.annotations.Parameter;
-import org.apache.tapestry5.internal.InternalComponentResources;
-import org.apache.tapestry5.internal.ParameterAccess;
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.internal.*;
import org.apache.tapestry5.internal.bindings.LiteralBinding;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.util.BodyBuilder;
@@ -35,6 +35,7 @@
public class ParameterWorker implements ComponentClassTransformWorker
{
private static final String BIND_METHOD_NAME = ParameterWorker.class.getName() + ".bind";
+ private static final String EQUAL_METHOD_NAME = ParameterWorker.class.getName() + ".equal";
private final BindingSource bindingSource;
@@ -84,11 +85,11 @@
String parameterName = getParameterName(name, annotation.name());
- model.addParameter(parameterName, annotation.required(), annotation.allowNull(), annotation.defaultPrefix());
+ boolean cache = annotation.cache();
- String type = transformation.getFieldType(name);
+ model.addParameter(parameterName, annotation.required(), annotation.allowNull(), annotation.defaultPrefix(),cache);
- boolean cache = annotation.cache();
+ String type = transformation.getFieldType(name);
String cachedFieldName = transformation.addField(Modifier.PRIVATE, "boolean", name + "_cached");
@@ -133,6 +134,9 @@
// be used to reset the field after rendering.
builder.addln("%s = %s;", defaultFieldName, fieldName);
+
+ addListenerSetup(fieldName, fieldType, parameterName, accessFieldName, builder, transformation);
+
builder.end();
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
@@ -232,9 +236,45 @@
actualMethodName);
}
+ private void addListenerSetup(
+ String fieldName,
+ String fieldType,
+ String parameterName,
+ String accessFieldName,
+ BodyBuilder builder,
+ ClassTransformation transformation)
+ {
+ transformation.addImplementedInterface(ParameterChangeListener.class);
+ builder.addln("%s.registerParameterChangeListener($0);",accessFieldName);
+
+ TransformMethodSignature signature = new TransformMethodSignature(Modifier.PUBLIC, "void", "parameterChanged",
+ new String[] {ParameterChangedEvent.class.getName()}, null);
+
+ BodyBuilder changedBody = new BodyBuilder();
+ changedBody.begin();
+
+ changedBody.addln("if (%s($1, \"%s\"))",EQUAL_METHOD_NAME,parameterName);
+ changedBody.begin();
+
+ String cast = TransformUtils.getWrapperTypeName(fieldType);
+
+ if (TransformUtils.isPrimitive(fieldType))
+ changedBody.addln("%s = ((%s) $1.getNewValue()).%s();",
+ fieldName, cast, TransformUtils.getUnwrapperMethodName(fieldType));
+ else
+ changedBody.addln("%s = (%s) $1.getNewValue();",fieldName, cast);
+
+ changedBody.addln("return;");
+ changedBody.end();
+
+ changedBody.end();
+
+ transformation.extendMethod(signature,changedBody.toString());
+
+ }
+
private void addWriterMethod(String fieldName, String cachedFieldName, String accessFieldName, boolean cache,
- String parameterName,
- String fieldType, String resourcesFieldName,
+ String parameterName, String fieldType, String resourcesFieldName,
ClassTransformation transformation)
{
BodyBuilder builder = new BodyBuilder();
@@ -253,11 +293,10 @@
// Always start by updating the parameter; this will implicitly check for
// read-only or unbound parameters. $1 is the single parameter
// to the method.
-
+ builder.addln("%s.unregisterParameterChangeListener($0);",accessFieldName);
builder.addln("%s.write(($w)$1);", accessFieldName);
-
+ builder.addln("%s.registerParameterChangeListener($0);",accessFieldName);
builder.addln("%s = $1;", fieldName);
-
if (cache) builder.addln("%s = %s.isRendering();", cachedFieldName, resourcesFieldName);
builder.end();
@@ -269,6 +308,17 @@
transformation.addMethod(signature, builder.toString());
+ builder.clear();
+
+ //add the catch because if we don't re-register the class as a parameter change listener, it's value
+ //could wind up stale, and write can throw an exception.
+ builder.begin();
+ builder.addln("%s.registerParameterChangeListener($0);",accessFieldName);
+ builder.addln("throw $e;");
+ builder.end();
+
+ transformation.addCatch(signature,Exception.class.getName(),builder.toString());
+
transformation.replaceWriteAccess(fieldName, methodName);
}
@@ -349,4 +399,9 @@
resources.bindParameter(parameterName, new LiteralBinding(null, "default " + parameterName, value));
}
+
+ public static <T> boolean equal(T left, T right)
+ {
+ return TapestryInternalUtils.isEqual(left,right);
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java Fri Jul 17 22:53:30 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2009 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.
@@ -21,6 +21,7 @@
import org.apache.tapestry5.ioc.internal.util.MessagesImpl;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.services.TransformMethodSignature;
+import org.apache.tapestry5.annotations.MixinClasses;
class TransformMessages
{
@@ -51,4 +52,10 @@
{
return MESSAGES.format("illegal-number-of-page-activation-context-handlers", InternalUtils.joinSorted(fields));
}
+
+
+ public static String badMixinConstraintLength(MixinClasses mixin, String fieldName)
+ {
+ return MESSAGES.format("bad-mixin-constraint-length",mixin.value().length,fieldName,mixin.order().length);
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java Fri Jul 17 22:53:30 2009
@@ -167,4 +167,11 @@
* @return true if event handler present
*/
boolean handlesEvent(String eventType);
+
+ /**
+ * @param mixinClassName class name of the mixin for which the ordering is desired
+ * @return the ordering constraint(s) for the mixin, potentially null.
+ * @since 5.2.0.0
+ */
+ String[] getOrderForMixin(String mixinClassName);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/EmbeddedComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/EmbeddedComponentModel.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/EmbeddedComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/EmbeddedComponentModel.java Fri Jul 17 22:53:30 2009
@@ -69,4 +69,11 @@
* @since 5.1.0.0
*/
List<String> getPublishedParameters();
+
+ /**
+ * @param mixinClassName
+ * @return the ordering constraints for the specified mixin, or null.
+ * @Since 5.2.0.0
+ */
+ String[] getConstraintsForMixin(String mixinClassName);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java Fri Jul 17 22:53:30 2009
@@ -34,10 +34,27 @@
* @param defaultBindingPrefix the default binding prefix for this parameter @throws IllegalArgumentException if a
* parameter with the given name has already been defined for this model
* @see Parameter
+ * @deprecated Use {@link #addParameter(String, boolean, boolean, String, boolean)} instead.
*/
void addParameter(String name, boolean required, boolean allowNull, String defaultBindingPrefix);
/**
+ * Adds a new formal parameter to the model. Each parameter has a unique name (though access to parameters is case
+ * insensitive).
+ *
+ * @param name new, unique name for the parameter
+ * @param required if true, the parameter must be bound
+ * @param allowNull if true, then parameter may be bound to null, if false a null check will be added
+ * @param defaultBindingPrefix the default binding prefix for this parameter @throws IllegalArgumentException if a
+ * parameter with the given name has already been defined for this model
+ * @param cached if true, the parameter value should be cached within the component during rendering
+ * @see org.apache.tapestry5.annotations.Parameter
+ * @since 5.2.0.0
+ */
+ public void addParameter(String name, boolean required, boolean allowNull, String defaultBindingPrefix,boolean cached);
+
+
+ /**
* Defines a new embedded component.
*
* @param id the unique id for the embedded component, which must not already exist.
@@ -66,9 +83,10 @@
String setFieldPersistenceStrategy(String fieldName, String strategy);
/**
- * Adds a mixin to the component's implementation.
+ * Adds a mixin to the component's implementation, optionally specifying ordering constraints, as per OrderedConfiguration.
+ * @since 5.2.0.0
*/
- void addMixinClassName(String mixinClassName);
+ void addMixinClassName(String mixinClassName, String... order);
/**
* Sets the internal flag to indicate that this model (and all models that extend from it) support informal
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableEmbeddedComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableEmbeddedComponentModel.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableEmbeddedComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableEmbeddedComponentModel.java Fri Jul 17 22:53:30 2009
@@ -25,9 +25,9 @@
void addParameter(String name, String value);
/**
- * Adds a mixin to the component in terms of its fully qualified class name.
+ * Adds a mixin to the component in terms of its fully qualified class name, with optional ordering constraints.
*/
- void addMixin(String mixinClassName);
+ void addMixin(String mixinClassName, String... orderingConstraints);
/**
* Sets the list of published parameters for this embedded component.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ParameterModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ParameterModel.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ParameterModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ParameterModel.java Fri Jul 17 22:53:30 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 2009 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.
@@ -42,4 +42,10 @@
* The default binding prefix for the parameter, usually "prop".
*/
String getDefaultBindingPrefix();
+
+ /**
+ * @return true if the bound-value is cached in the component during rendering.
+ * @since 5.2.0.0
+ */
+ boolean isCached();
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Fri Jul 17 22:53:30 2009
@@ -484,6 +484,12 @@
configuration.addInstance("Parameter", ParameterWorker.class, "after:Inject*");
+ //bind parameter should always go after parameter to make sure all parameters
+ //have been properly setup.
+
+ configuration.addInstance("BindParameter",BindParameterWorker.class, "after:Parameter");
+
+
// Workers for the component rendering state machine methods; this is in typical
// execution order.
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties Fri Jul 17 22:53:30 2009
@@ -0,0 +1,40 @@
+#
+# Copyright 2009 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.
+#
+
+unique_mixin_required=Mixins applied to a component must be unique. Mixin '%s' has already been applied.
+mixinid_for_paramnotfound="Mixin id for parameter '%s' not found. Attached mixins: %s."
+missing_component_type=You must specify the type via t:type, the element, or @Componentno_more_tokens=No more template tokens.
+could_not_find_override=Could not find an override for extension point '%s'.
+no_parent_for_extension=Component %s uses an extension template, but does not have a parent component.
+token_not_implemented=Not yet implemented: %s
+parameter_not_supported=Component %s does not include a formal parameter '%s' (and does not support informal parameters).
+redundant_embedded_component_types=Embedded component '%s' provides a type attribute in the template ('%s') \
+ as well as in the component class ('%s'). You should not provide a type attribute \
+ in the template when defining an embedded component within the component class.
+recursive_template=The template for component %s is recursive (contains another direct or indirect reference to \
+ component %<s). This is not supported (components may not contain themselves).
+composite_render_command_method_not_implemented=RenderQueue method %s() is not implemented for composited render commands.
+exception_assembling_root_component=Exception assembling root component of page %s: %s
+exception_assembling_embedded_component=Exception assembling embedded component '%s' (of type %s, within %s): %s
+embedded_components_not_in_template=Embedded component(s) %s are defined within component class %s \
+ (or a super-class of %s), but are not present in the component template (%s).
+parameter_already_published=Parameter '%s' of embedded component '%s' can not be published as a parameter of component \
+ %s, as it has previously been published by embedded component '%s'.
+failure_creating_embedded_component=Failure creating embedded component '%s' of %s: %s"
+published_parameter_nonexistant=Parameter '%s' of component %s is improperly published from embedded component '%s' \
+ (where it does not exist). This may be a typo in the publishParameters attribute of \
+ the @Component annotation.
+
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/structure/StructureStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/structure/StructureStrings.properties?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/structure/StructureStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/structure/StructureStrings.properties Fri Jul 17 22:53:30 2009
@@ -35,4 +35,8 @@
missing-render-variable=Component %s does not contain a stored render variable with name '%s'. Stored render variables: %s.
render-variable-set-when-not-rendering=Component %s is not rendering, so render variable '%s' may not be updated.
persist-change-before-load-complete=Persistent fields may not be updated until after the page has finished loading. \
- This may be due to a persistent field with a default value. The default value should be removed.
\ No newline at end of file
+ This may be due to a persistent field with a default value. The default value should be removed.
+no-such-core-component-parameter=Failed to BindParameter '%s' in mixin '%s': component '%s' does not provide a matching \
+ parameter (looking for: %s). Available parameters: %s
+bind-parameter-only-on-mixin=@BindParameter was used on '%s' in component class '%s', but @BindParameter should \
+ only be used in mixins.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties Fri Jul 17 22:53:30 2009
@@ -17,3 +17,5 @@
cached-no-return-value=@Cached may only be used with methods that return values: %s
cached-no-parameters=@Cached cannot be used with methods that accept parameters: %s
illegal-number-of-page-activation-context-handlers=Illegal number of fields annotated with @PageActivationContext: %s. Only one field is allowed.
+bad-mixin-constraint-length=%d mixins defined via @MixinClasses on field '%s', but %d ordering constraints \
+ specified (expected 0 or %1$d).
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ClientPersistenceDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ClientPersistenceDemo.tml?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ClientPersistenceDemo.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ClientPersistenceDemo.tml Fri Jul 17 22:53:30 2009
@@ -10,8 +10,12 @@
<p>
Session: [${sessionExists}]
</p>
-
-
+
+
+ <p>
+ <t:actionlink t:id="nixSession">nix session</t:actionlink>
+ </p>
+
<p>
<t:actionlink t:id="storeString">store string</t:actionlink>
</p>
@@ -24,4 +28,5 @@
<t:pagelink page="clientpersistencedemo">refresh</t:pagelink>
</p>
+
</html>
\ No newline at end of file
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Fri Jul 17 22:53:30 2009
@@ -41,6 +41,16 @@
super("src/test/app1");
}
+
+ @Test(enabled = false)
+ public static void main(String[] args) throws Exception {
+ IntegrationTests it = new IntegrationTests();
+ it.setup();
+ while(true) {
+ Thread.sleep(1000);
+ }
+ }
+
@Test
public void assets() throws Exception
{
@@ -133,12 +143,13 @@
@Test
public void exception_report()
{
+ //mismatched tag.
start("BadTemplate Page");
assertTextPresent("org.apache.tapestry5.ioc.internal.util.TapestryException",
- "Failure parsing template classpath:org/apache/tapestry5/integration/app1/pages/BadTemplate.tml, line 7, column 15",
- "<t:foobar>content from template</t:foobar>",
- "Element <t:foobar> is in the Tapestry namespace, but is not a recognized Tapestry template element.");
+ "Failure parsing template classpath:org/apache/tapestry5/integration/app1/pages/BadTemplate.tml: Unexpected close tag </foobar>; expected </t:foobar>",
+ "classpath:org/apache/tapestry5/integration/app1/pages/BadTemplate.tml, line 6",
+ "<t:foobar>content from template</foobar>");
}
@Test
@@ -566,7 +577,7 @@
// The XPath support is too weak for //div[@class='t-beandisplay-value'][%d], so we
// just look for the text itself.
- assertTextPresent("Howard", "Lewis Ship", "1966", "Martian", "U. S. Citizen", "***********", "line1", "line2",
+ assertTextPresent("Howard", "Lewis Ship", "1966", "Martian", "U.S. Citizen", "***********", "line1", "line2",
"line3");
}
@@ -581,10 +592,11 @@
type("firstName", "Howard");
type("lastName", "Lewis Ship");
type("password", "supersecret");
+ check("citizen");
clickAndWait("//input[@type=\'submit\']");
- assertTextPresent("Howard", "Lewis Ship", "0", "100% He-Man", "U. S. Citizen");
+ assertTextPresent("Howard", "Lewis Ship", "0", "100% He-Man", "U.S. Citizen");
}
@Test
@@ -847,7 +859,7 @@
clickAndWait(SUBMIT);
- assertTextPresent("Howard", "Lewis Ship", "1966", "U. S. Citizen");
+ assertTextPresent("Howard", "Lewis Ship", "1966", "U.S. Citizen");
}
@Test
@@ -865,7 +877,7 @@
{
start("Renderable Demo");
- assertTextPresent("Renderable Demo", "[proves it works.]");
+ assertTextPresent("Renderable Demo", "[This proves it works.]");
}
@Test
@@ -912,6 +924,9 @@
public void client_persistence()
{
start("Client Persistence Demo");
+ //can't assume session won't exist because other tests use form components w/ defaults, which means
+ //session creation to store the ValidationTracker. So we explicitly clear the session here.
+ clickAndWait("link=nix session");
assertTextPresent("Persisted value: []", "Session: [false]");
@@ -1045,16 +1060,17 @@
goBack();
waitForPageToLoad();
- // This has been failing? Why?
-
- // clickAndWait("link=URL");
- // assertTextPresent("Google");
- // goBack();
- // waitForPageToLoad();
+ /*
+ clickAndWait("link=URL");
+ assertTextPresent("Google>");
+ goBack();
+ waitForPageToLoad();
+ */
clickAndWait("link=bad");
assertTextPresent("An unexpected application exception has occurred.",
- "An event handler for component org.apache.tapestry5.integration.app1.pages.Index returned the value 20 (from method org.apache.tapestry5.integration.app1.pages.Index.onActionFromBadReturnType() (at Index.java:34)). Return type java.lang.Integer can not be handled.");
+ "A component event handler method returned the value 20. Return type java.lang.Integer can not be handled.",
+ "context:ReturnTypes.tml, line 50");
}
@Test
@@ -1260,7 +1276,7 @@
start("BeanEditor / Date Demo", "clear");
type("name", "Howard Lewis Ship");
- type("date", "12/24/66");
+ type("date", "12/24/1966");
clickAndWait(SUBMIT);
@@ -1635,7 +1651,7 @@
clickAndWait("link=force invalid event context");
assertTextPresent("An unexpected application exception has occurred.",
- "org.apache.tapestry5.ioc.internal.util.TapestryException",
+ "org.apache.tapestry5.runtime.ComponentEventException",
"java.lang.NumberFormatException");
}
@@ -2362,7 +2378,7 @@
assertTextPresent("org.apache.tapestry5.internal.services.RenderQueueException",
"Render queue error in SetupRender[FormFieldOutsideForm:textfield]: The Textfield component must be enclosed by a Form component.",
- "context:FormFieldOutsideForm.tml, line 5, column 45");
+ "context:FormFieldOutsideForm.tml, line 5");
}
/**
@@ -2968,6 +2984,130 @@
}
@Test
+ public void bindparameter()
+ {
+ start("BindParameter mixin annotation");
+ //implicit parameter name
+ assertEchoMixins("testmixin","mypropertyvalue",0,-1,-1,1,true);
+ assertText("mypropertyoutput","mypropertyvalue");
+
+ //explicit parameter name
+ assertEchoMixins("testmixin2","10",-1,0,-1,2,true);
+ assertText("mypropertyoutput2","10");
+
+ //multiple parameter names; first one found wins.
+ assertEchoMixins("testmixin3","hello",-1,-1,0,3,true);
+
+ //multiple mixins
+ assertEchoMixins("multimixins","supervalue",0,1,2,3,true);
+ assertText("mypropertyoutput4","supervalue");
+
+ //finally, binding to default bindings (which is tricky because of page load invocation order)
+ assertEchoMixins("defaultbinding","goodbye",0,-1,-1,1,false);
+ assertText("mypropertyoutput5","goodbye");
+ }
+
+ @Test
+ public void bindparameter_nomatchingparameter()
+ {
+ start("BindParameter error handling");
+
+ assertTextPresent("An unexpected application exception has occurred.",
+ "Failed to BindParameter 'boundParameter' in mixin 'org.apache.tapestry5.integration.app1.mixins.EchoValue2': "
+ + "component 'org.apache.tapestry5.corelib.components.Any' does not provide a matching parameter "
+ + "(looking for: value). Available parameters: [clientId, element]");
+
+ }
+
+ @Test
+ public void bindparameter_on_componentfield_throws_exception()
+ {
+ start("BindParameter on component");
+
+ assertTextPresent("An unexpected application exception has occurred.",
+ "@BindParameter was used on 'value' in component class 'org.apache.tapestry5.integration.app1.components.BindParameterComponent', but @BindParameter should only be used in mixins");
+ }
+
+ @Test
+ public void mixin_ordering()
+ {
+ //echo => <original>-before, temporaryvaluefromechovaluemixin, <original>-after
+ //echo2 => echo2-<original>-before, "3", echo2-<original>-after
+ //echo3 => echo3-<original>-before, "world", echo3-<original>-after
+ //order1: echo, echo2, echo3
+ start("Mixin Ordering Demo");
+
+ assertMixinOrder(1,0,1,2,3,true);
+ //order2: echo3, echo2, echo
+ assertMixinOrder(2,2,3,0,1,true);
+ //order3: echo2, echo3, echo
+ assertMixinOrder(3,3,0,2,1,true);
+ //order4: echo3, echo, echo2
+ assertMixinOrder(4,3,1,0,2,true);
+ //order5: echo2, echo, echo3
+ assertMixinOrder(5,2,0,1,3,true);
+ //order6: echo, echo3, echo2, TextOnlyOnDisabled
+ assertMixinOrder(6,0,3,1,2,false);
+ //make sure mixin after and mixin before constraints don't interfere...
+ //order7: echo, echo2 <corecomponent> echoafter2, echoafter
+ assertMixinOrder(7,0,1,-1,2,true);
+ assertText("order7_before_but_after","afterrender_for_mixinafter_isreally_justbefore_corecomponent_afterrender-before");
+ assertText("order7_after_but_before","afterrender_for_mixinafter_isreally_justbefore_corecomponent_afterrender-after");
+ //echoafter2 should have for its value at the point it renders
+ //the value that echo2 sets, since the core component isn't changing its value.
+ assertText("order7_before_but_after2","3-before");
+ assertText("order7_after_but_before2","3-after");
+ }
+
+ private void assertMixinOrder(int orderNum, int echo1From, int echo2From, int echo3From, int fieldFrom, boolean isField)
+ {
+ assertEchoMixins("order" + orderNum,"batman", echo1From,echo2From,echo3From,fieldFrom,isField);
+ }
+
+ /**
+ * asserts that the "echo value" mixins are properly functioning (ie @BindParameter, and mixin ordering).
+ * each integer value specifies the echo mixin number (echovalue => 1, echovalue2 => 2, echovalue3 => 3; 0 is the original value)
+ * from which the specified echo mixin is expected to "receive" its value. So if echo1From is 2, then the "original value"
+ * printed by echo1 is expected to be the value set by echo2. If a given "from" is < 0, checking the corresponding mixin values is disabled.
+ */
+
+ private void assertEchoMixins(String fieldName, String originalValue, int echo1From, int echo2From, int echo3From, int fieldFrom, boolean isField)
+ {
+ String[] vals = {originalValue,"temporaryvaluefromechovaluemixin","3","world"};
+ String before = fieldName + "_before";
+ String after = fieldName + "_after";
+ if (echo1From > -1)
+ {
+ assertText(before,vals[echo1From] + "-before");
+ assertText(after,vals[echo1From] + "-after");
+ }
+ if (echo2From > -1)
+ {
+ assertText(before + "2","echo2-" + vals[echo2From] + "-before");
+ assertText(after + "2","echo2-" + vals[echo2From] + "-after");
+ }
+ if (echo3From > -1)
+ {
+ assertText(before + "3","echo3-" + vals[echo3From] + "-before");
+ assertText(after + "3","echo3-" + vals[echo3From] + "-after");
+ }
+ if (isField)
+ assertFieldValue(fieldName,vals[fieldFrom]);
+ else
+ assertText(fieldName,vals[fieldFrom]);
+ }
+
+
+ @Test
+ public void missing_componentclass()
+ {
+ start("Missing Component Class Exception");
+ assertTextPresent(
+ "An unexpected application exception has occurred",
+ "Failure creating embedded component 'componentwithnotype' of org.apache.tapestry5.integration.app1.pages.MissingComponentClassException: You must specify the type via t:type, the element, or @Component");
+ }
+
+ @Test
public void session_attribute()
{
start("SessionAttribute Demo");
@@ -2980,4 +3120,4 @@
assertTextPresent("read Foo");
assertTextPresent("read Bar");
}
-}
\ No newline at end of file
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponent.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponent.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponent.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,28 @@
+// Copyright 2009 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.integration.app1.components;
+
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.MarkupWriter;
+
+/**
+ * @BindParameter should only be used inside a mixin; should get an intelligible exception when trying to use this component.
+ */
+public class BindParameterComponent
+{
+
+ @BindParameter
+ private Object value;
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponentContainer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponentContainer.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponentContainer.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BindParameterComponentContainer.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,31 @@
+// Copyright 2009 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.integration.app1.components;
+
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.MixinAfter;
+
+/**
+ * Used to help prove that BindParameter on a component field throws an intelligible exception, even if the containing
+ * resources actually do contain a declared parameter of the appropriate name.
+ */
+public class BindParameterComponentContainer
+{
+
+ @Parameter("literal:testvalue")
+ private String value;
+
+
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,30 @@
+// Copyright 2009 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.integration.app1.components;
+
+import org.apache.tapestry5.corelib.components.TextField;
+import org.apache.tapestry5.annotations.Mixin;
+import org.apache.tapestry5.integration.app1.mixins.TextOnlyOnDisabled;
+
+/**
+ *
+ */
+public class TextOnlyOnDisabledTextField extends TextField
+{
+
+ @Mixin(order = "after:*")
+ private TextOnlyOnDisabled theMixin;
+
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,56 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Field;
+import org.apache.tapestry5.ioc.annotations.Inject;
+
+/**
+ * Mixin demonstrating the use of the BindParameter annotation, using implicit parent-parameter naming.
+ * It echos the current value, changes said value for the duration of the component
+ * render, then changes it back and re-echos it.
+ */
+@MixinAfter
+public class EchoAfter
+{
+ @BindParameter
+ private String value;
+
+ private String temp;
+
+ @InjectContainer
+ private Field field;
+
+ @BeginRender
+ void beginRender(MarkupWriter writer)
+ {
+ writer.element("div","id",field.getClientId() + "_before_but_after");
+ writer.writeRaw(value + "-before");
+ writer.end();
+ temp = value;
+ value = "beginrender_for_mixinafter_isreally_justafter_corecomponent_render";
+ }
+
+ @AfterRender
+ void afterRender(MarkupWriter writer) {
+ value = temp;
+ writer.element("div","id",field.getClientId() + "_after_but_before");
+ writer.writeRaw(value + "-after");
+ writer.end();
+ }
+}
\ No newline at end of file
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter2.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter2.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoAfter2.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,56 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Field;
+import org.apache.tapestry5.ioc.annotations.Inject;
+
+/**
+ * Mixin demonstrating the use of the BindParameter annotation, using implicit parent-parameter naming.
+ * It echos the current value, changes said value for the duration of the component
+ * render, then changes it back and re-echos it.
+ */
+@MixinAfter
+public class EchoAfter2
+{
+ @BindParameter
+ private String value;
+
+ private String temp;
+
+ @InjectContainer
+ private Field field;
+
+ @BeginRender
+ void beginRender(MarkupWriter writer)
+ {
+ writer.element("div","id",field.getClientId() + "_before_but_after2");
+ writer.writeRaw(value + "-before");
+ writer.end();
+ temp = value;
+ value = "afterrender_for_mixinafter_isreally_justbefore_corecomponent_afterrender";
+ }
+
+ @AfterRender
+ void afterRender(MarkupWriter writer) {
+ value = temp;
+ writer.element("div","id",field.getClientId() + "_after_but_before2");
+ writer.writeRaw(value + "-after");
+ writer.end();
+ }
+}
\ No newline at end of file
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,55 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Field;
+import org.apache.tapestry5.ioc.annotations.Inject;
+
+/**
+ * Mixin demonstrating the use of the BindParameter annotation, using implicit parent-parameter naming.
+ * It echos the current value, changes said value for the duration of the component
+ * render, then changes it back and re-echos it.
+ */
+public class EchoValue
+{
+ @BindParameter
+ private String value;
+
+ private String temp;
+
+ @InjectContainer
+ private Field field;
+
+ @BeginRender
+ void beginRender(MarkupWriter writer)
+ {
+ writer.element("div","id",field.getClientId() + "_before");
+ writer.writeRaw(value + "-before");
+ writer.end();
+ temp = value;
+ value = "temporaryvaluefromechovaluemixin";
+ }
+
+ @AfterRender
+ void afterRender(MarkupWriter writer) {
+ value = temp;
+ writer.element("div","id",field.getClientId() + "_after");
+ writer.writeRaw(value + "-after");
+ writer.end();
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue2.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue2.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue2.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,51 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.annotations.InjectContainer;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ClientElement;
+
+/**
+ * Mixin demonstrating the use of BindParameter, using explicit naming of the parent parameter.
+ */
+public class EchoValue2
+{
+ @BindParameter(value = "value")
+ private Object boundParameter;
+
+ @InjectContainer
+ private ClientElement element;
+
+ private Object temp;
+
+ void beginRender(MarkupWriter writer)
+ {
+ writer.element("div","id",element.getClientId() + "_before2");
+ writer.writeRaw("echo2-" + boundParameter + "-before");
+ writer.end();
+ temp = boundParameter;
+ boundParameter = "3";
+ }
+
+ void afterRender(MarkupWriter writer)
+ {
+ boundParameter = temp;
+ writer.element("div","id",element.getClientId() + "_after2");
+ writer.writeRaw("echo2-" + boundParameter + "-after");
+ writer.end();
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue3.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue3.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue3.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/EchoValue3.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,51 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.annotations.InjectContainer;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ClientElement;
+
+/**
+ * Mixin demonstrating the use of BindParameter, using explicit naming of the parent parameter.
+ */
+public class EchoValue3
+{
+ @BindParameter(value = {"object","value"})
+ private Object boundParameter;
+
+ @InjectContainer
+ private ClientElement element;
+
+ private Object temp;
+
+ void beginRender(MarkupWriter writer)
+ {
+ writer.element("div","id",element.getClientId() + "_before3");
+ writer.writeRaw("echo3-" + boundParameter + "-before");
+ writer.end();
+ temp = boundParameter;
+ boundParameter = "world";
+ }
+
+ void afterRender(MarkupWriter writer)
+ {
+ boundParameter = temp;
+ writer.element("div","id",element.getClientId() + "_after3");
+ writer.writeRaw("echo3-" + boundParameter + "-after");
+ writer.end();
+ }
+}
\ No newline at end of file
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/TextOnlyOnDisabled.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/TextOnlyOnDisabled.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/TextOnlyOnDisabled.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/TextOnlyOnDisabled.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,65 @@
+// Copyright 2009 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.integration.app1.mixins;
+
+import org.apache.tapestry5.annotations.BindParameter;
+import org.apache.tapestry5.annotations.InjectContainer;
+import org.apache.tapestry5.*;
+import org.apache.tapestry5.internal.InternalComponentResources;
+import org.apache.tapestry5.internal.ParameterAccess;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+
+/**
+ * Renders a plain-text version of a value where
+ */
+public class TextOnlyOnDisabled
+{
+ @BindParameter
+ private Object value;
+
+ @BindParameter
+ private boolean disabled;
+
+
+ @BindParameter
+ private FieldTranslator translate;
+
+ @Inject
+ private TypeCoercer coercer;
+
+ @InjectContainer
+ private ClientElement field;
+
+ @Inject
+ private ComponentResources resources;
+
+ Boolean beginRender(MarkupWriter writer)
+ {
+ InternalComponentResources res = (InternalComponentResources) resources;
+ ParameterAccess acc = res.getContainerBoundParameterAccess("translate","translate");
+ if (disabled)
+ {
+ //We can short-circuit the text field's beginRender phase, but
+ //not it's afterRender phase, and TextField calls writer.end()
+ //in end render. So we add a dummy element to provide an element to end.
+ writer.element("span","id",field.getClientId());
+ writer.write(translate.toClient(value));
+ return false;
+ }
+ return null;
+ }
+
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,50 @@
+// Copyright 2009 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.integration.app1.pages;
+
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.SetupRender;
+
+/**
+ * Page for demonstrating/testing the use of the BindParameter mixin demonstration.
+ */
+public class BindParameterDemo
+{
+
+ @Property
+ private String myproperty;
+
+ @Property
+ private Integer myproperty2;
+
+ @Property
+ private String myproperty3;
+
+ @Property
+ private String myproperty4;
+
+ @Property
+ private String myproperty5;
+
+ @SetupRender
+ void initMyprop()
+ {
+ myproperty="mypropertyvalue";
+ myproperty2=10;
+ myproperty3="hello";
+ myproperty4="supervalue";
+ myproperty5="goodbye";
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterNoSuchParameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterNoSuchParameter.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterNoSuchParameter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterNoSuchParameter.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,22 @@
+// Copyright 2009 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.integration.app1.pages;
+
+/**
+ *
+ */
+public class BindParameterNoSuchParameter
+{
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterOnComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterOnComponent.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterOnComponent.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterOnComponent.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,24 @@
+// Copyright 2009 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.integration.app1.pages;
+
+import org.apache.tapestry5.annotations.Property;
+
+/**
+ *
+ */
+public class BindParameterOnComponent
+{
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientPersistenceDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientPersistenceDemo.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientPersistenceDemo.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientPersistenceDemo.java Fri Jul 17 22:53:30 2009
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2009 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.
@@ -15,8 +15,10 @@
package org.apache.tapestry5.integration.app1.pages;
import org.apache.tapestry5.annotations.Persist;
+
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
+import org.apache.tapestry5.services.Session;
public class ClientPersistenceDemo
{
@@ -33,7 +35,7 @@
public boolean getSessionExists()
{
- return request.getSession(false) != null;
+ return session() != null;
}
void onActionFromStoreString()
@@ -50,4 +52,17 @@
}
};
}
+
+ void onActionFromNixSession()
+ {
+ if (getSessionExists() && !session().isInvalidated())
+ {
+ session().invalidate();
+ }
+ }
+
+ private Session session()
+ {
+ return request.getSession(false);
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java Fri Jul 17 22:53:30 2009
@@ -357,6 +357,26 @@
"RenderClientId Mixin",
"Force render of client-side id of a client element via the RenderClientId mixin"),
+ new Item("BindParameterDemo",
+ "BindParameter mixin annotation",
+ "Accessing component parameter values from a mixin"),
+
+ new Item("BindParameterNoSuchParameter",
+ "BindParameter error handling",
+ "BindParameter throws exception if the containing component doesn't have a matching parameter"),
+
+ new Item("BindParameterOnComponent",
+ "BindParameter on component",
+ "Verify that BindParameter can only be used on mixin fields"),
+
+ new Item("MixinOrderingDemo",
+ "Mixin Ordering Demo",
+ "Various mixin-ordering scenarios"),
+
+ new Item("MissingComponentClassException",
+ "Missing Component Class Exception",
+ "Meaningful exception message thrown when component class can't be determined from template or field in containing component."),
+
new Item("SessionAttributeDemo",
"SessionAttribute Demo",
"Annotation to map a field to a specific session attribute")
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MissingComponentClassException.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MissingComponentClassException.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MissingComponentClassException.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MissingComponentClassException.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,22 @@
+// Copyright 2009 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.integration.app1.pages;
+
+/**
+ *
+ */
+public class MissingComponentClassException
+{
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinOrderingDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinOrderingDemo.java?rev=795264&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinOrderingDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinOrderingDemo.java Fri Jul 17 22:53:30 2009
@@ -0,0 +1,58 @@
+// Copyright 2009 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.integration.app1.pages;
+
+import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.corelib.components.TextField;
+import org.apache.tapestry5.integration.app1.mixins.EchoValue;
+import org.apache.tapestry5.integration.app1.mixins.EchoValue2;
+import org.apache.tapestry5.integration.app1.components.TextOnlyOnDisabledTextField;
+
+/**
+ * Page for demonstrating/testing the use of the BindParameter mixin demonstration.
+ */
+public class MixinOrderingDemo
+{
+
+ @Property
+ private String myproperty;
+
+ @Component
+ @Mixins("echovalue2::before:echovalue3")
+ @MixinClasses(value={EchoValue.class},order={"after:echovalue2;after:echovalue3"})
+ private TextField order3;
+
+ @Component
+ @Mixins("echovalue2::after:echovalue")
+ @MixinClasses(EchoValue.class)
+ private TextField order4;
+
+ @Component
+ @Mixins("echovalue2")
+ @MixinClasses(value=EchoValue.class,order={"after:echovalue2"})
+ private TextField order5;
+
+
+ @Component
+ @Mixins("echovalue3::before:echovalue2")
+ @MixinClasses(value=EchoValue2.class,order="after:echovalue")
+ private TextOnlyOnDisabledTextField order6;
+
+ @SetupRender
+ void initMyprop()
+ {
+ myproperty="batman";
+ }
+}
\ No newline at end of file
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java?rev=795264&r1=795263&r2=795264&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java Fri Jul 17 22:53:30 2009
@@ -910,7 +910,7 @@
ExtensionPointToken expansion = get(template.getTokens(), 2);
- assertEquals(expansion.getExtentionPointId(), "title");
+ assertEquals(expansion.getExtensionPointId(), "title");
List<TemplateToken> title = template.getExtensionPointTokens("title");