[prev in list] [next in list] [prev in thread] [next in thread]
List: tapestry-dev
Subject: svn commit: r491145 - in /tapestry/tapestry5/tapestry-core/trunk/src:
From: hlship () apache ! org
Date: 2006-12-30 1:08:41
Message-ID: 20061230010841.CA1BE1A981A () eris ! apache ! org
[Download RAW message or body]
Author: hlship
Date: Fri Dec 29 17:08:39 2006
New Revision: 491145
URL: http://svn.apache.org/viewvc?view=rev&rev=491145
Log:
Support a value() attribute in the Parameter annotation, the default binding \
expression for the parameter if otherwise unbound
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html
Removed:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/ValidationTracker.java?view=diff&rev=491145&r1=491144&r2=491145 \
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java \
Fri Dec 29 17:08:39 2006 @@ -1,3 +1,17 @@
+// Copyright 2006 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.tapestry;
import java.util.List;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/ValidationTrackerImpl.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java \
Fri Dec 29 17:08:39 2006 @@ -1,3 +1,17 @@
+// Copyright 2006 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.tapestry;
import java.io.Serializable;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/ValidationTrackerImplTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java \
Fri Dec 29 17:08:39 2006 @@ -1,3 +1,17 @@
+// Copyright 2006 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.tapestry;
import java.io.ByteArrayInputStream;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/annotations/Parameter.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java \
Fri Dec 29 17:08:39 2006 @@ -12,47 +12,49 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotation placed on a field to indicate that it is, in fact, an parameter. \
Parameters may be
- * optional or required. Required parameters must be bound.
- * <p>
- * TODO: Do we want to support a notNull as well as required?
- *
- *
- */
-@Target(FIELD)
-@Documented
-@Retention(RUNTIME)
-public @interface Parameter {
-
- /**
- * The name of the parameter. If not specified, the name of the parameter is \
derived from the
- * name of the field (after stripping off leading punctuation) from the field \
name.
- */
- String name() default "";
-
- /**
- * If true, the parameter is required and and must be bound. If false (the \
default), then the
- * parameter is optional.
- */
- boolean required() default false;
-
- /**
- * If true (the default), then the value for the parameter is cached while the \
component is,
- * itself, rendering. Values from invariant bindings (such as literal strings) \
are always
- * cached, regardless of this setting. Set this attribute to false to force the \
parameter to be
- * {@link org.apache.tapestry.services.Binding#get() re-read} every time the \
field is accessed, even
- * while the component is rendering.
- */
-
- boolean cache() default true;
-}
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation placed on a field to indicate that it is, in fact, an parameter. \
Parameters may be + * optional or required. Required parameters must be bound.
+ */
+@Target(FIELD)
+@Documented
+@Retention(RUNTIME)
+public @interface Parameter {
+
+ /**
+ * The name of the parameter. If not specified, the name of the parameter is \
derived from the + * name of the field (after stripping off leading punctuation) \
from the field name. + */
+ String name() default "";
+
+ /**
+ * If true, the parameter is required and and must be bound. If false (the \
default), then the + * parameter is optional.
+ */
+ boolean required() default false;
+
+ /**
+ * If true (the default), then the value for the parameter is cached while the \
component is, + * itself, rendering. Values from invariant bindings (such as \
literal strings) are always + * cached, regardless of this setting. Set this \
attribute to false to force the parameter to be + * {@link \
org.apache.tapestry.services.Binding#get() re-read} every time the field is accessed, \
+ * even while the component is rendering. + */
+
+ boolean cache() default true;
+
+ /**
+ * The default value for the parameter if not bound (at not the empty string). \
This is a binding + * expression, typically the name of a property of the \
component to bind. + */
+ String value() default "";
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/internal/bindings/PropBindingFactory.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java \
Fri Dec 29 17:08:39 2006 @@ -133,7 +133,7 @@
private BindingConstructor createConstructor(String key, Class targetClass, \
String propertyPath) {
- // Race condition: simulataneous calls to fillCache() for the same \
targetClass/propertyName + // Race condition: simulataneous calls to \
createConstructor() for the same targetClass/propertyName
// combination may result in duplicate binding classes being created, which \
causes no great // harm.
@@ -178,7 +178,7 @@
if (adapter == null)
throw new RuntimeException(BindingsMessages.noSuchProperty(
- targetClass,
+ step,
terminalName,
propertyPath));
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java \
Fri Dec 29 17:08:39 2006 @@ -12,60 +12,60 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import org.apache.tapestry.internal.event.InvalidationEventHub;
-
-/**
- * Creates {@link org.apache.tapestry.internal.services.Instantiator}s for \
components, based on
- * component class name. This will involve transforming the component's class before \
it is loaded.
- * <p>
- * In addition, a source acts as an event hub for
- * {@link org.apache.tapestry.events.InvalidationListener}s, so that any information \
derived from
- * loaded classes can be discarded and rebuilt when classes change.
- * <p>
- * The strategy used is that when <em>any</em> class (in a controlled package) \
changes, the entire
- * class loader is discarded, along with any instances derived from those classes. A \
new class
- * loader is created, and then invalidation events are fired to listeners.
- */
-public interface ComponentInstantiatorSource extends InvalidationEventHub
-{
-
- /**
- * Given the name of a component class, provides an instantiator for that \
component.
- * Instantiators are cached, so repeated calls to this method with the same \
class name will
- * return the same instance; however, callers should also be aware that the \
instantiators may
- * lose validity after an invalidation (caused by changes to external Java class \
files).
- *
- * @param classname
- * FQCN to find (and perhaps transform and load)
- * @return an object which can instantiate an instance of the component
- */
- Instantiator findInstantiator(String classname);
-
- /**
- * Adds a controlled package. Only classes within controlled packages are \
subject to
- * transformation.
- *
- * @param packageName
- * the package name to add (must not be blank)
- */
- void addPackage(String packageName);
-
- /**
- * Checks to see if a fully qualfied class name exists.
- *
- * @param className
- * name of class to check
- * @return true if the class exists (there's a ".class" file), false otherwise
- */
- boolean exists(String className);
-
- /**
- * Returns a class loader with visibility to the transformed classes. Caution: \
callers of this
- * should also listen for invalidation events and re-acquire the class loader \
after an
- * invalidation.
- */
-
- ClassLoader getClassLoader();
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.event.InvalidationEventHub;
+import org.apache.tapestry.ioc.services.ClassFactory;
+
+/**
+ * Creates {@link org.apache.tapestry.internal.services.Instantiator}s for \
components, based on + * component class name. This will involve transforming the \
component's class before it is loaded. + * <p>
+ * In addition, a source acts as an event hub for
+ * {@link org.apache.tapestry.events.InvalidationListener}s, so that any information \
derived from + * loaded classes can be discarded and rebuilt when classes change.
+ * <p>
+ * The strategy used is that when <em>any</em> class (in a controlled package) \
changes, the entire + * class loader is discarded, along with any instances derived \
from those classes. A new class + * loader is created, and then invalidation events \
are fired to listeners. + */
+public interface ComponentInstantiatorSource extends InvalidationEventHub
+{
+
+ /**
+ * Given the name of a component class, provides an instantiator for that \
component. + * Instantiators are cached, so repeated calls to this method with \
the same class name will + * return the same instance; however, callers should \
also be aware that the instantiators may + * lose validity after an invalidation \
(caused by changes to external Java class files). + *
+ * @param classname
+ * FQCN to find (and perhaps transform and load)
+ * @return an object which can instantiate an instance of the component
+ */
+ Instantiator findInstantiator(String classname);
+
+ /**
+ * Adds a controlled package. Only classes within controlled packages are \
subject to + * transformation.
+ *
+ * @param packageName
+ * the package name to add (must not be blank)
+ */
+ void addPackage(String packageName);
+
+ /**
+ * Checks to see if a fully qualfied class name exists.
+ *
+ * @param className
+ * name of class to check
+ * @return true if the class exists (there's a ".class" file), false otherwise
+ */
+ boolean exists(String className);
+
+ /**
+ * Returns a class factory that can be used to generate additional classes \
around enhanced + * classes, or create subclasses of enhanced classes.
+ */
+ ClassFactory getClassFactory();
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java \
Fri Dec 29 17:08:39 2006 @@ -34,7 +34,10 @@
import org.apache.tapestry.events.UpdateListener;
import org.apache.tapestry.internal.event.InvalidationEventHubImpl;
import org.apache.tapestry.internal.util.URLChangeTracker;
+import org.apache.tapestry.ioc.internal.services.ClassFactoryClassPool;
+import org.apache.tapestry.ioc.internal.services.ClassFactoryImpl;
import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassFactory;
/**
* A wrapper around a Javassist class loader that allows certain classes to be \
modified as they are @@ -49,7 +52,7 @@
private final ClassLoader _parent;
- private ClassPool _classPool;
+ private ClassFactoryClassPool _classPool;
private Loader _loader;
@@ -57,6 +60,8 @@
private final Log _log;
+ private ClassFactory _classFactory;
+
/** Map from class name to Instantiator. */
private final Map<String, Instantiator> _instantiatorMap = newMap();
@@ -90,12 +95,6 @@
initializeService();
}
- /** @return the class loader used when loading enhanced/modified classes */
- public ClassLoader getClassLoader()
- {
- return _loader;
- }
-
public synchronized void checkForUpdates()
{
if (!_changeTracker.containsChanges())
@@ -121,13 +120,13 @@
*/
private void initializeService()
{
- _classPool = new ClassPool();
+ _classPool = new ClassFactoryClassPool(_parent);
- ClassPath path = new LoaderClassPath(_parent);
+ _loader = new PackageAwareLoader(_parent, _classPool);
- _classPool.appendClassPath(path);
+ ClassPath path = new LoaderClassPath(_loader);
- _loader = new PackageAwareLoader(_parent, _classPool);
+ _classPool.appendClassPath(path);
try
{
@@ -137,6 +136,8 @@
{
throw new RuntimeException(ex);
}
+
+ _classFactory = new ClassFactoryImpl(_classPool.getLoader(), _classPool, \
_log); }
// This is called from well within a synchronized block.
@@ -276,5 +277,10 @@
String path = className.replace(".", "/") + ".class";
return _parent.getResource(path) != null;
+ }
+
+ public ClassFactory getClassFactory()
+ {
+ return _classFactory;
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/internal/services/ParameterWorker.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java \
Fri Dec 29 17:08:39 2006 @@ -12,245 +12,275 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import java.lang.reflect.Modifier;
-import java.util.List;
-
-import org.apache.tapestry.annotations.Parameter;
+package org.apache.tapestry.internal.services;
+
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.ioc.internal.util.InternalUtils;
import org.apache.tapestry.ioc.util.BodyBuilder;
-import org.apache.tapestry.model.MutableComponentModel;
-import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
-import org.apache.tapestry.services.MethodSignature;
-import org.apache.tapestry.services.TransformConstants;
-import org.apache.tapestry.services.TransformUtils;
-
-/**
- * Responsible for identifying parameters via the {@link \
org.apache.tapestry.annotations.Parameter}
- * annotation on component fields. This is one of the most complex of the \
transformations.
- *
- *
- */
-public class ParameterWorker implements ComponentClassTransformWorker
-{
- public void transform(ClassTransformation transformation, MutableComponentModel \
model)
- {
- List<String> fieldNames = \
transformation.findFieldsWithAnnotation(Parameter.class);
-
- for (String name : fieldNames)
- {
- convertFieldIntoParameter(name, transformation, model);
- }
- }
-
- private void convertFieldIntoParameter(String name, ClassTransformation \
transformation,
- MutableComponentModel model)
- {
- Parameter annotation = transformation.getFieldAnnotation(name, \
Parameter.class);
-
- String parameterName = getParameterName(name, annotation.name());
-
- model.addParameter(parameterName, annotation.required());
-
- String type = transformation.getFieldType(name);
-
- boolean cache = annotation.cache();
-
- String cachedFieldName = transformation.addField(Modifier.PRIVATE, \
"boolean", name
- + "_cached");
-
- String resourcesFieldName = transformation.getResourcesFieldName();
-
- String invariantFieldName = addParameterSetup(
- name,
- parameterName,
- cachedFieldName,
- cache,
- type,
- resourcesFieldName,
- transformation);
-
- addReaderMethod(
- name,
- cachedFieldName,
- invariantFieldName,
- cache,
- parameterName,
- type,
- resourcesFieldName,
- transformation);
-
- addWriterMethod(
- name,
- cachedFieldName,
- cache,
- parameterName,
- type,
- resourcesFieldName,
- transformation);
-
- transformation.claimField(name, annotation);
- }
-
- /** Returns the name of a field that stores whether the parameter binding is \
invariant. */
-
- private String addParameterSetup(String fieldName, String parameterName,
- String cachedFieldName, boolean cache, String fieldType, String \
resourcesFieldName,
- ClassTransformation transformation)
- {
- String defaultFieldName = transformation.addField(Modifier.PRIVATE, \
fieldType, fieldName
- + "_default");
-
- String invariantFieldName = transformation.addField(Modifier.PRIVATE, \
"boolean", fieldName
- + "_invariant");
-
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
- builder.addln(
- "%s = %s.isInvariant(\"%s\");",
- invariantFieldName,
- resourcesFieldName,
- parameterName);
-
- // 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);
- 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).
-
- if (cache)
- {
- builder.clear();
-
- builder.addln("if (! %s)", invariantFieldName);
- builder.begin();
- builder.addln("%s = %s;", fieldName, defaultFieldName);
- builder.addln("%s = false;", cachedFieldName);
- builder.end();
-
- transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, \
builder
- .toString());
- }
-
- return invariantFieldName;
- }
-
- private void addWriterMethod(String fieldName, String cachedFieldName, boolean \
cache,
- String parameterName, 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();
-
- // 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("if (%s.isBound(\"%s\"))", resourcesFieldName, parameterName);
- builder.addln(" %s.writeParameter(\"%s\", ($w)$1);", resourcesFieldName, \
parameterName);
-
- builder.addln("%s = $1;", fieldName);
-
- if (cache)
- builder.addln("%s = %s.isRendering();", cachedFieldName, \
resourcesFieldName);
-
- builder.end();
-
- String methodName = transformation.newMemberName("_update_parameter_" + \
parameterName);
-
- MethodSignature signature = new MethodSignature(Modifier.PRIVATE, "void", \
methodName,
- new String[]
- { fieldType }, null);
-
- transformation.addMethod(signature, 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 invariantFieldName, boolean cache, String parameterName, 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 || ! %s.isLoaded() || ! %<s.isBound(\"%s\")) return %s;",
- cachedFieldName,
- resourcesFieldName,
- parameterName,
- 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.
-
- builder.addln(
- "%s result = ($r) ((%s) %s.readParameter(\"%s\", $type));",
- fieldType,
- cast,
- resourcesFieldName,
- parameterName);
-
- // 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", invariantFieldName);
-
- if (cache)
- builder.add(" || %s.isRendering()", resourcesFieldName);
-
- builder.addln(")");
- 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_parameter_" + \
parameterName);
-
- MethodSignature signature = new MethodSignature(Modifier.PRIVATE, fieldType, \
methodName,
- null, null);
-
- transformation.addMethod(signature, builder.toString());
-
- transformation.replaceReadAccess(fieldName, methodName);
- }
-
- private String getParameterName(String fieldName, String annotatedName)
- {
- if (InternalUtils.isNonBlank(annotatedName))
- return annotatedName;
-
- return InternalUtils.stripMemberPrefix(fieldName);
- }
-}
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.BindingSource;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.TransformConstants;
+import org.apache.tapestry.services.TransformUtils;
+
+/**
+ * Responsible for identifying parameters via the {@link \
org.apache.tapestry.annotations.Parameter} + * annotation on component fields. This \
is one of the most complex of the transformations. + */
+public class ParameterWorker implements ComponentClassTransformWorker
+{
+ private final BindingSource _bindingSource;
+
+ public ParameterWorker(BindingSource bindingSource)
+ {
+ _bindingSource = bindingSource;
+ }
+
+ public void transform(ClassTransformation transformation, MutableComponentModel \
model) + {
+ List<String> fieldNames = \
transformation.findFieldsWithAnnotation(Parameter.class); +
+ for (String name : fieldNames)
+ {
+ convertFieldIntoParameter(name, transformation, model);
+ }
+ }
+
+ private void convertFieldIntoParameter(String name, ClassTransformation \
transformation, + MutableComponentModel model)
+ {
+ Parameter annotation = transformation.getFieldAnnotation(name, \
Parameter.class); +
+ String parameterName = getParameterName(name, annotation.name());
+
+ model.addParameter(parameterName, annotation.required());
+
+ String type = transformation.getFieldType(name);
+
+ boolean cache = annotation.cache();
+
+ String cachedFieldName = transformation.addField(Modifier.PRIVATE, \
"boolean", name + + "_cached");
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ String invariantFieldName = addParameterSetup(
+ name,
+ annotation.value(),
+ parameterName,
+ cachedFieldName,
+ cache,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ addReaderMethod(
+ name,
+ cachedFieldName,
+ invariantFieldName,
+ cache,
+ parameterName,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ addWriterMethod(
+ name,
+ cachedFieldName,
+ cache,
+ parameterName,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ transformation.claimField(name, annotation);
+ }
+
+ /**
+ * Returns the name of a field that stores whether the parameter binding is \
invariant. + */
+ private String addParameterSetup(String fieldName, String defaultBinding, String \
parameterName, + String cachedFieldName, boolean cache, String fieldType, \
String resourcesFieldName, + ClassTransformation transformation)
+ {
+ String defaultFieldName = transformation.addField(Modifier.PRIVATE, \
fieldType, fieldName + + "_default");
+
+ String invariantFieldName = transformation.addField(Modifier.PRIVATE, \
"boolean", fieldName + + "_invariant");
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ if (InternalUtils.isNonBlank(defaultBinding))
+ {
+ builder.addln("if (! %s.isBound(\"%s\"))", resourcesFieldName, \
parameterName); +
+ String bindingFactoryFieldName = transformation.addInjectedField(
+ BindingSource.class,
+ "bindingSource",
+ _bindingSource);
+
+ builder
+ .addln(
+ " %s.addParameter(\"%s\", %s.newBinding(\"default \
%2$s\", %1$s, %1$s, \"%s\", \"%s\", null));", + \
resourcesFieldName, + parameterName,
+ bindingFactoryFieldName,
+ InternalConstants.PROP_BINDING_PREFIX,
+ defaultBinding);
+
+ }
+
+ builder.addln(
+ "%s = %s.isInvariant(\"%s\");",
+ invariantFieldName,
+ resourcesFieldName,
+ parameterName);
+
+ // 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);
+ 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). +
+ if (cache)
+ {
+ builder.clear();
+
+ builder.addln("if (! %s)", invariantFieldName);
+ builder.begin();
+ builder.addln("%s = %s;", fieldName, defaultFieldName);
+ builder.addln("%s = false;", cachedFieldName);
+ builder.end();
+
+ transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, \
builder + .toString());
+ }
+
+ return invariantFieldName;
+ }
+
+ private void addWriterMethod(String fieldName, String cachedFieldName, boolean \
cache, + String parameterName, 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();
+
+ // 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("if (%s.isBound(\"%s\"))", resourcesFieldName, parameterName);
+ builder.addln(" %s.writeParameter(\"%s\", ($w)$1);", resourcesFieldName, \
parameterName); +
+ builder.addln("%s = $1;", fieldName);
+
+ if (cache)
+ builder.addln("%s = %s.isRendering();", cachedFieldName, \
resourcesFieldName); +
+ builder.end();
+
+ String methodName = transformation.newMemberName("_update_parameter_" + \
parameterName); +
+ MethodSignature signature = new MethodSignature(Modifier.PRIVATE, "void", \
methodName, + new String[]
+ { fieldType }, null);
+
+ transformation.addMethod(signature, 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 invariantFieldName, boolean cache, String parameterName, 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 || ! %s.isLoaded() || ! %<s.isBound(\"%s\")) return %s;",
+ cachedFieldName,
+ resourcesFieldName,
+ parameterName,
+ 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.
+
+ builder.addln(
+ "%s result = ($r) ((%s) %s.readParameter(\"%s\", $type));",
+ fieldType,
+ cast,
+ resourcesFieldName,
+ parameterName);
+
+ // 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", invariantFieldName);
+
+ if (cache)
+ builder.add(" || %s.isRendering()", resourcesFieldName);
+
+ builder.addln(")");
+ 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_parameter_" + \
parameterName); +
+ MethodSignature signature = new MethodSignature(Modifier.PRIVATE, fieldType, \
methodName, + null, null);
+
+ transformation.addMethod(signature, builder.toString());
+
+ transformation.replaceReadAccess(fieldName, methodName);
+ }
+
+ private String getParameterName(String fieldName, String annotatedName)
+ {
+ if (InternalUtils.isNonBlank(annotatedName))
+ return annotatedName;
+
+ return InternalUtils.stripMemberPrefix(fieldName);
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java \
Fri Dec 29 17:08:39 2006 @@ -623,10 +623,6 @@
public void containingPageDidLoad()
{
- verifyRequiredParametersAreBound();
-
- _loaded = true;
-
// If this component has mixins, add the core component to the end of the \
list, after the // mixins.
@@ -661,7 +657,14 @@
_components = ordered;
}
+ _loaded = true;
+
+ // For some parameters, bindings (from defaults) are provided inside the \
callback method, so + // that is invoked first, before we check for unbound \
parameters. +
invoke(false, CONTAINING_PAGE_DID_LOAD);
+
+ verifyRequiredParametersAreBound();
}
/**
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/runtime/PageLifecycleListener.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java \
Fri Dec 29 17:08:39 2006 @@ -12,29 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.runtime;
-
-/**
- * A set of methods that allow components to know about page-level operations.
- */
-public interface PageLifecycleListener
-{
- /**
- * Invoked when the page finishes loading. This occurs once all components are \
loaded and all
- * parameters have been set.
- */
- void containingPageDidLoad();
-
- /**
- * Invoked when the page is detached, allowing components a chance to clear out \
any temporary or
- * client specific state.
- */
- void containingPageDidDetach();
-
- /**
- * Invoked when a page is first attached to the current request, giving \
components a chance to
- * initialize for the current request.
- */
-
- void containingPageDidAttach();
-}
+package org.apache.tapestry.runtime;
+
+/**
+ * A set of methods that allow components to know about page-level operations.
+ */
+public interface PageLifecycleListener
+{
+ /**
+ * Invoked when the page finishes loading. This occurs once all components are \
loaded and all + * parameters have been set.
+ */
+ void containingPageDidLoad();
+
+ /**
+ * Invoked when the page is detached, allowing components a chance to clear out \
any temporary or + * client specific state.
+ */
+ void containingPageDidDetach();
+
+ /**
+ * Invoked when a page is first attached to the current request, giving \
components a chance to + * initialize for the current request.
+ */
+
+ void containingPageDidAttach();
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/services/BindingSource.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java \
Fri Dec 29 17:08:39 2006 @@ -29,7 +29,7 @@
* factory for the default prefix (often "literal") is used (and passed the full \
prefix).
* <p>
* The binding represents a connection between the container and the component \
(the component is
- * usually the child of the component, though in a few cases, it is the \
component itself). In + * usually the child of the container, though in a few \
cases, it is the component itself). In
* most cases, the expression is evaluated in terms of the resources of the \
<em>container</em>
* and the component is ignored.
*
@@ -38,7 +38,7 @@
* @param container
* typically, the parent of the component
* @param component
- * the component whose paramter is to be bound
+ * the component whose parameter is to be bound
* @param defaultPrefix
* the default prefix used when the expression itself does not have a \
prefix
* @param expression
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/services/MethodSignature.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java \
Fri Dec 29 17:08:39 2006 @@ -12,231 +12,235 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.services;
-
+package org.apache.tapestry.services;
+
import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
-
-import java.lang.reflect.Modifier;
-
-/**
- * A representation of a method signature, which consists of its name, modifiers \
(primarily,
- * visibility), return type, parameter types, and declared exception types.
- * <p>
- * Types are stored as class names (or primitive names) because the MethodSignature \
is often used in
- * situations where the actual class has not been loaded yet. When classes are \
already loaded (such
- * as, for use with {@link org.apache.hivemind.service.ClassFab}), then a different \
implementation
- * with the same name, {@link org.apache.tapestry.ioc.services.MethodSignature} is \
used.
- */
-public class MethodSignature implements Comparable<MethodSignature>
-{
- private int _hashCode = -1;
-
- private final int _modifiers;
-
- private final String _returnType;
-
- private final String _methodName;
-
- private final String[] _parameterTypes;
-
- private final String[] _exceptionTypes;
-
- private static final String[] EMPTY_STRINGS = new String[0];
-
- /** Convienience for adding a public void method with no parameters or exception \
types. */
-
- public MethodSignature(String name)
- {
- this(Modifier.PUBLIC, "void", name, EMPTY_STRINGS, EMPTY_STRINGS);
- }
-
- public MethodSignature(int modifiers, String type, String name, String[] \
parameterTypes,
- String[] exceptionTypes)
- {
- _modifiers = modifiers;
-
- _returnType = notBlank(type, "type");
- _methodName = notBlank(name, "name");
-
- // TODO: Checks that no element within the two arrays
- // is null or blank.
-
- _parameterTypes = typeNamesOrEmpty(parameterTypes);
- _exceptionTypes = typeNamesOrEmpty(exceptionTypes);
- }
-
- private String[] typeNamesOrEmpty(String[] types)
- {
- return types == null ? EMPTY_STRINGS : types;
- }
-
- /**
- * Returns a non-null array of the names of each declared exception type thrown \
by the method.
- * Calling code should not modify the array.
- */
- public String[] getExceptionTypes()
- {
- return _exceptionTypes;
- }
-
- /** Returns the name of the method. */
- public String getMethodName()
- {
- return _methodName;
- }
-
- /**
- * Returns the set of modifier flags for this method.
- *
- * @see java.lang.reflect.Modifier
- */
- public int getModifiers()
- {
- return _modifiers;
- }
-
- /**
- * Returns an array of the type name for each parameter. Calling code should not \
modify the
- * array.
- */
- public String[] getParameterTypes()
- {
- return _parameterTypes;
- }
-
- /** Return the type name of the return type of the method. */
- public String getReturnType()
- {
- return _returnType;
- }
-
- @Override
- public int hashCode()
- {
- if (_hashCode == -1)
- {
- _hashCode = 17 * _modifiers;
- _hashCode += 31 * _returnType.hashCode();
- _hashCode += 31 * _methodName.hashCode();
-
- for (String parameterType : _parameterTypes)
- {
- _hashCode += 31 * parameterType.hashCode();
- }
-
- for (String exceptionType : _exceptionTypes)
- {
- _hashCode += 31 * exceptionType.hashCode();
- }
- }
-
- return _hashCode;
- }
-
- @Override
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof MethodSignature))
- return false;
-
- MethodSignature ms = (MethodSignature) other;
-
- return _modifiers == ms._modifiers && _returnType.equals(ms._returnType)
- && _methodName.equals(ms._methodName)
- && matches(_parameterTypes, ms._parameterTypes)
- && matches(_exceptionTypes, ms._exceptionTypes);
- }
-
- private boolean matches(String[] values, String[] otherValues)
- {
- if (values.length != otherValues.length)
- return false;
-
- for (int i = 0; i < values.length; i++)
- {
- if (!values[i].equals(otherValues[i]))
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns the long form description of the signature. This includes modifiers, \
return type,
- * method name, parameters and thrown exceptions, formatter approximately as it \
would appear in
- * Java source (except that parameter names, which are not known, do no appear).
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder();
-
- // Package private is simply omitted.
-
- if (_modifiers != 0)
- {
- builder.append(Modifier.toString(_modifiers));
- builder.append(' ');
- }
-
- builder.append(_returnType);
- builder.append(' ');
-
- addMethodNameAndParameters(builder);
-
- for (int i = 0; i < _exceptionTypes.length; i++)
- {
- if (i == 0)
- builder.append(" throws ");
- else
- builder.append(", ");
-
- builder.append(_exceptionTypes[i]);
- }
-
- return builder.toString();
- }
-
- private void addMethodNameAndParameters(StringBuilder builder)
- {
- builder.append(_methodName);
- builder.append('(');
-
- for (int i = 0; i < _parameterTypes.length; i++)
- {
- if (i > 0)
- builder.append(", ");
-
- builder.append(_parameterTypes[i]);
- }
-
- builder.append(')');
- }
-
- public int compareTo(MethodSignature o)
- {
- int result = _methodName.compareTo(o._methodName);
-
- if (result == 0)
- result = _parameterTypes.length - o._parameterTypes.length;
-
- return result;
- }
-
- /**
- * Returns a shortened form of the string representation of the method. It lists \
just the name
- * of the method and the types of any parameters, omitting return type, \
exceptions and
- * modifiers.
- *
- * @return
- */
- public String getMediumDescription()
- {
- StringBuilder builder = new StringBuilder();
-
- addMethodNameAndParameters(builder);
-
- return builder.toString();
- }
-
-}
+
+import java.lang.reflect.Modifier;
+
+/**
+ * A representation of a method signature, which consists of its name, modifiers \
(primarily, + * visibility), return type, parameter types, and declared exception \
types. + * <p>
+ * Types are stored as class names (or primitive names) because the MethodSignature \
is often used in + * situations where the actual class has not been loaded yet. When \
classes are already loaded (such + * as, for use with {@link \
org.apache.hivemind.service.ClassFab}), then a different implementation + * with the \
same name, {@link org.apache.tapestry.ioc.services.MethodSignature} is used. + */
+public class MethodSignature implements Comparable<MethodSignature>
+{
+ private int _hashCode = -1;
+
+ private final int _modifiers;
+
+ private final String _returnType;
+
+ private final String _methodName;
+
+ private final String[] _parameterTypes;
+
+ private final String[] _exceptionTypes;
+
+ private static final String[] EMPTY_STRINGS = new String[0];
+
+ /** Convienience for adding a public void method with no parameters or exception \
types. */ +
+ public MethodSignature(String name)
+ {
+ this(Modifier.PUBLIC, "void", name, EMPTY_STRINGS, EMPTY_STRINGS);
+ }
+
+ public MethodSignature(int modifiers, String type, String name, String[] \
parameterTypes, + String[] exceptionTypes)
+ {
+ _modifiers = modifiers;
+
+ _returnType = notBlank(type, "type");
+ _methodName = notBlank(name, "name");
+
+ // TODO: Checks that no element within the two arrays
+ // is null or blank.
+
+ _parameterTypes = typeNamesOrEmpty(parameterTypes);
+ _exceptionTypes = typeNamesOrEmpty(exceptionTypes);
+ }
+
+ private String[] typeNamesOrEmpty(String[] types)
+ {
+ return types == null ? EMPTY_STRINGS : types;
+ }
+
+ /**
+ * Returns a non-null array of the names of each declared exception type thrown \
by the method. + * Calling code should not modify the array.
+ */
+ public String[] getExceptionTypes()
+ {
+ return _exceptionTypes;
+ }
+
+ /** Returns the name of the method. */
+ public String getMethodName()
+ {
+ return _methodName;
+ }
+
+ /**
+ * Returns the set of modifier flags for this method.
+ *
+ * @see java.lang.reflect.Modifier
+ */
+ public int getModifiers()
+ {
+ return _modifiers;
+ }
+
+ /**
+ * Returns an array of the type name for each parameter. Calling code should not \
modify the + * array.
+ */
+ public String[] getParameterTypes()
+ {
+ return _parameterTypes;
+ }
+
+ /** Return the type name of the return type of the method. */
+ public String getReturnType()
+ {
+ return _returnType;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ if (_hashCode == -1)
+ {
+ _hashCode = 17 * _modifiers;
+ _hashCode += 31 * _returnType.hashCode();
+ _hashCode += 31 * _methodName.hashCode();
+
+ for (String parameterType : _parameterTypes)
+ {
+ _hashCode += 31 * parameterType.hashCode();
+ }
+
+ for (String exceptionType : _exceptionTypes)
+ {
+ _hashCode += 31 * exceptionType.hashCode();
+ }
+ }
+
+ return _hashCode;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof MethodSignature))
+ return false;
+
+ MethodSignature ms = (MethodSignature) other;
+
+ return _modifiers == ms._modifiers && _returnType.equals(ms._returnType)
+ && _methodName.equals(ms._methodName)
+ && matches(_parameterTypes, ms._parameterTypes)
+ && matches(_exceptionTypes, ms._exceptionTypes);
+ }
+
+ private boolean matches(String[] values, String[] otherValues)
+ {
+ if (values.length != otherValues.length)
+ return false;
+
+ for (int i = 0; i < values.length; i++)
+ {
+ if (!values[i].equals(otherValues[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the long form description of the signature. This includes modifiers, \
return type, + * method name, parameters and thrown exceptions, formatter \
approximately as it would appear in + * Java source (except that parameter names, \
which are not known, do no appear). + */
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder();
+
+ // Package private is simply omitted.
+
+ if (_modifiers != 0)
+ {
+ builder.append(Modifier.toString(_modifiers));
+ builder.append(' ');
+ }
+
+ builder.append(_returnType);
+ builder.append(' ');
+
+ addMethodNameAndParameters(builder);
+
+ for (int i = 0; i < _exceptionTypes.length; i++)
+ {
+ if (i == 0)
+ builder.append(" throws ");
+ else
+ builder.append(", ");
+
+ builder.append(_exceptionTypes[i]);
+ }
+
+ return builder.toString();
+ }
+
+ private void addMethodNameAndParameters(StringBuilder builder)
+ {
+ builder.append(_methodName);
+ builder.append('(');
+
+ for (int i = 0; i < _parameterTypes.length; i++)
+ {
+ if (i > 0)
+ builder.append(", ");
+
+ builder.append(_parameterTypes[i]);
+ }
+
+ builder.append(')');
+ }
+
+ /**
+ * Sorting is primarily via method name. For methods with the same name, the \
second level of + * sorting is by parameter count (ascending).
+ */
+ public int compareTo(MethodSignature o)
+ {
+ int result = _methodName.compareTo(o._methodName);
+
+ if (result == 0)
+ result = _parameterTypes.length - o._parameterTypes.length;
+
+ return result;
+ }
+
+ /**
+ * Returns a shortened form of the string representation of the method. It lists \
just the name + * of the method and the types of any parameters, omitting return \
type, exceptions and + * modifiers.
+ *
+ * @return
+ */
+ public String getMediumDescription()
+ {
+ StringBuilder builder = new StringBuilder();
+
+ addMethodNameAndParameters(builder);
+
+ return builder.toString();
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java \
/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java \
Fri Dec 29 17:08:39 2006 @@ -53,11 +53,11 @@
import org.apache.tapestry.internal.services.BindingSourceImpl;
import org.apache.tapestry.internal.services.ClasspathAssetAliasManagerImpl;
import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
-import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
import org.apache.tapestry.internal.services.ComponentEventDispatcher;
import org.apache.tapestry.internal.services.ComponentInstanceEventHandler;
import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
+import org.apache.tapestry.internal.services.ComponentInvocationMap;
import org.apache.tapestry.internal.services.ComponentLifecycleMethodWorker;
import org.apache.tapestry.internal.services.ComponentMessagesSourceImpl;
import org.apache.tapestry.internal.services.ComponentResourcesInjectionProvider;
@@ -69,7 +69,6 @@
import org.apache.tapestry.internal.services.EnvironmentalWorker;
import org.apache.tapestry.internal.services.FieldValidatorSourceImpl;
import org.apache.tapestry.internal.services.HeartbeatImpl;
-import org.apache.tapestry.internal.services.ComponentInvocationMap;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
import org.apache.tapestry.internal.services.InjectAnonymousWorker;
@@ -538,11 +537,12 @@
* Returns a {@link ClassFactory} that can be used to create extra classes \
around component
* classes.
*/
- public static ClassFactory buildComponentClassFactory(Log log,
+ public ClassFactory buildComponentClassFactory(
@InjectService("tapestry.internal.ComponentInstantiatorSource")
ComponentInstantiatorSource source)
{
- return new ComponentClassFactoryImpl(log, source);
+
+ return _shadowBuilder.build(source, "classFactory", ClassFactory.class);
}
/**
@@ -603,7 +603,8 @@
Environment environment, \
@InjectService("tapestry.ComponentClassResolver")
ComponentClassResolver resolver, \
@InjectService("tapestry.internal.RequestPageCache")
RequestPageCache requestPageCache, @Inject("infrastructure:AssetSource")
- AssetSource assetSource)
+ AssetSource assetSource, @Inject("infrastructure:BindingSource")
+ BindingSource bindingsource)
{
// TODO: Proper scheduling of all of this. Since a given field or method \
should
// only have a single annotation, the order doesn't matter so much, as long \
as @@ -617,7 +618,7 @@
configuration.add("AssetInject", new AssetInjectWorker(assetSource), \
"before:InjectNamed"); configuration.add("MixinAfter", new MixinAfterWorker());
- configuration.add("Parameter", new ParameterWorker());
+ configuration.add("Parameter", new ParameterWorker(bindingsource));
configuration.add("Component", new ComponentWorker(resolver));
configuration.add("Environment", new EnvironmentalWorker(environment));
configuration.add("Mixin", new MixinWorker(resolver));
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt Fri Dec \
29 17:08:39 2006 @@ -225,6 +225,29 @@
the min parameter has a default value of 1. That value is used unless the min \
parameter is bound, in which case, the bound value supercedes the default.
+Parameter Binding Defaults
+
+ The Parameter annotation's value() attribute can be used to specify a <binding \
expression> that will be the + default binding for the parameter is otherwise left \
unbound. Typically, this is the name of a property + that that will compute the \
value on the fly. +
+ Example:
+
++----+
+ @Parameter("defaultMessage")
+ private String _message;
+
+ @Parameter(required=true)
+ private int _maxLength;
+
+ public String getDefaultMessage()
+ {
+ return String.format("Maximum field length is %d.", _maxLength);
+ }
++---+
+
+ As elsewhere, you may use a prefix on the value. A common prefix to use is the \
"message:" prefix, to access a localized message. +
Unbound Parameters
If a parameter is not bound (and is optional), then the value may be read or \
<updated> at any time. @@ -232,11 +255,12 @@
Updates to unbound parameters cause no side effects. In the first example, the \
value parameter of the Count component is not bound, and this is perfectly valid.
- Note: updates to such fields are temporary; when the component finishes rendering, \
the field + Note: updates to such fields are temporary; when the component <finishes \
rendering>, the field will revert to its default value.
<<TODO: This seems contradictory. What does it mean to update an unbound component \
parameter when the component
- is not rendering?>>
+ is not rendering?>>
+
Parameter Caching
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Fri Dec 29 \
17:08:39 2006 @@ -57,6 +57,9 @@
<li>
<a href="InjectComponentMismatch.html">InjectComponentMismatch</a> \
-- check error reporting when @InjectComponent doesn't match the actual field type \
</li> + <li>
+ <a href="ParameterDefault.html">ParameterDefault</a> -- defaulter \
methods for component parameters + </li>
</ul>
</p>
</body>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java \
Fri Dec 29 17:08:39 2006 @@ -374,6 +374,15 @@
assertEquals(downloaded, actual);
}
+ @Test
+ public void component_parameter_default_from_method() throws Exception
+ {
+ _selenium.open(BASE_URL);
+ clickAndWait("link=ParameterDefault");
+
+ assertTextPresent("Echo component default: \
[org.apache.tapestry.integration.app1.pages.ParameterDefault:echo]"); + }
+
/**
* {@link InjectComponentWorker} is largely tested by the forms tests ({@link \
RenderDisabled}
* is built on it). This test is for the failure case, where a mixin class is \
used with the
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/integration/app1/components/Echo.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java \
Fri Dec 29 17:08:39 2006 @@ -12,26 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.integration.app1.components;
-
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.ComponentClass;
-import org.apache.tapestry.annotations.Parameter;
-
-/**
- * Echos out its value parameter (used to test parameter overrides between component \
annoation and
- * template).
- */
-@ComponentClass
-public class Echo
-{
- @Parameter(required = true)
- private String _value;
-
- @BeginRender
- void render(MarkupWriter writer)
- {
- writer.write(_value);
- }
-}
+package org.apache.tapestry.integration.app1.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ * Echos out its value parameter. Uused to test parameter overrides between \
component annoation and + * template. Also, used to test parameter defaulter methods.
+ */
+@ComponentClass
+public class Echo
+{
+ @Parameter("componentResources.completeId")
+ private String _value;
+
+ @BeginRender
+ void render(MarkupWriter writer)
+ {
+ writer.write(_value);
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/integration/app1/pages/ParameterDefault.java?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java \
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java \
Fri Dec 29 17:08:39 2006 @@ -0,0 +1,23 @@
+// Copyright 2006 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.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+
+@ComponentClass
+public class ParameterDefault
+{
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/internal/bindings/DefaultComponent.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java \
Fri Dec 29 17:08:39 2006 @@ -74,18 +74,13 @@
public void afterRenderBody(MarkupWriter writer, LifecycleEvent<Boolean> event)
{
- // TODO Auto-generated method stub
-
}
public void afterRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> \
event) {
- // TODO Auto-generated method stub
-
}
public void beforeRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> \
event) {
- // TODO Auto-generated method stub
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/internal/services/DefaultParameterComponent.java?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java \
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java \
Fri Dec 29 17:08:39 2006 @@ -0,0 +1,34 @@
+// Copyright 2006 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.tapestry.internal.services;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ * Used by {@link org.apache.tapestry.internal.services.ParameterWorkerTest}.
+ */
+@ComponentClass
+public class DefaultParameterComponent
+{
+ @Parameter("literal:greeting")
+ private String _value;
+
+ public String getValue()
+ {
+ return _value;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/internal/services/PageLocatorTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java \
Fri Dec 29 17:08:39 2006 @@ -1,3 +1,17 @@
+// Copyright 2006 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.tapestry.internal.services;
import java.util.Locale;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/internal/services/ParameterWorkerTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java \
Fri Dec 29 17:08:39 2006 @@ -21,11 +21,14 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.test.InternalBaseTestCase;
import org.apache.tapestry.ioc.internal.services.PropertyAccessImpl;
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.Binding;
+import org.apache.tapestry.services.BindingSource;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
@@ -450,6 +453,59 @@
verify();
}
+ @Test
+ public void parameter_with_default() throws Exception
+ {
+ final BindingSource source = newBindingSource();
+ final InternalComponentResources resources = \
newInternalComponentResources(); + final Binding binding = newBinding();
+ String boundValue = "howdy!";
+
+ MutableComponentModel model = newMutableComponentModel();
+
+ model.addParameter("value", false);
+
+ Runnable phaseTwoTraining = new Runnable()
+ {
+ public void run()
+ {
+ train_isBound(resources, "value", false);
+
+ expect(
+ source.newBinding(
+ "default value",
+ resources,
+ resources,
+ InternalConstants.PROP_BINDING_PREFIX,
+ "literal:greeting",
+ null)).andReturn(binding);
+
+ resources.addParameter("value", binding);
+
+ train_isInvariant(resources, "value", true);
+
+ };
+ };
+
+ Component component = setupForIntegrationTest(
+ resources,
+ newLog(),
+ DefaultParameterComponent.class.getName(),
+ model,
+ source,
+ phaseTwoTraining);
+
+ train_isLoaded(resources, true);
+ train_isBound(resources, "value", true);
+ train_readParameter(resources, "value", String.class, boundValue);
+
+ replay();
+
+ assertEquals(_access.get(component, "value"), boundValue);
+
+ verify();
+ }
+
protected final void train_isRendering(InternalComponentResources resources, \
boolean rendering) {
expect(resources.isRendering()).andReturn(rendering);
@@ -461,10 +517,40 @@
expect(resources.readParameter(parameterName, \
expectedType)).andReturn(value); }
- private Component setupForIntegrationTest(InternalComponentResources resources)
+ /** This is for the majority of tests. */
+ private Component setupForIntegrationTest(final InternalComponentResources \
resources) throws Exception
{
- Log log = newLog();
+ MutableComponentModel model = newMutableComponentModel();
+
+ model.addParameter("invariantObject", false);
+ model.addParameter("invariantPrimitive", false);
+ model.addParameter("object", false);
+ model.addParameter("primitive", true);
+ model.addParameter("uncached", false);
+
+ Runnable phaseTwoTraining = new Runnable()
+ {
+ public void run()
+ {
+ trainForPageDidLoad(resources);
+
+ }
+ };
+
+ return setupForIntegrationTest(
+ resources,
+ newLog(),
+ ParameterComponent.class.getName(),
+ model,
+ newBindingSource(),
+ phaseTwoTraining);
+ }
+
+ private Component setupForIntegrationTest(InternalComponentResources resources, \
Log log, + String componentClassName, MutableComponentModel model, \
BindingSource source, + Runnable phaseTwoTraining) throws Exception
+ {
ClassPool pool = new ClassPool();
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
pool.appendClassPath(new LoaderClassPath(contextLoader));
@@ -473,21 +559,13 @@
loader.delegateLoadingOf("org.apache.tapestry.");
- CtClass ctClass = pool.get(ParameterComponent.class.getName());
+ CtClass ctClass = pool.get(componentClassName);
InternalClassTransformation transformation = new \
InternalClassTransformationImpl(ctClass, _contextClassLoader, log, null);
- MutableComponentModel model = newMutableComponentModel();
-
- model.addParameter("invariantObject", false);
- model.addParameter("invariantPrimitive", false);
- model.addParameter("object", false);
- model.addParameter("primitive", true);
- model.addParameter("uncached", false);
-
replay();
- new ParameterWorker().transform(transformation, model);
+ new ParameterWorker(source).transform(transformation, model);
verify();
@@ -499,7 +577,7 @@
Instantiator instantiator = \
transformation.createInstantiator(transformedClass);
- trainForPageDidLoad(resources);
+ phaseTwoTraining.run();
replay();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java \
/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java \
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java \
Fri Dec 29 17:08:39 2006 @@ -150,6 +150,10 @@
train_getParameterModel(model, "fred", pmodel);
train_isRequired(pmodel, true);
+ // Now called *before* the check for unbound parametesr
+
+ component.containingPageDidLoad();
+
train_getComponentClassName(model, "foo.components.MyComponent");
replay();
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/reso \
urces/org/apache/tapestry/integration/app1/pages/ParameterDefault.html?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html \
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html \
Fri Dec 29 17:08:39 2006 @@ -0,0 +1,6 @@
+<t:comp type="Border" \
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> +
+
+ Echo component default: [<t:comp type="Echo" id="echo"/>]
+
+</t:comp>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic