You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2010/01/22 17:31:21 UTC
svn commit: r902156 - in
/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5:
annotations/ internal/ internal/services/ internal/structure/
internal/transform/ services/
Author: hlship
Date: Fri Jan 22 16:31:21 2010
New Revision: 902156
URL: http://svn.apache.org/viewvc?rev=902156&view=rev
Log:
Introduce new interface, FieldValueConduit, and add ability to ClassTransformation to redirect all field access through the conduit
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java (with props)
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/BindParameter.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker2.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/BindParameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/BindParameter.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/BindParameter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/BindParameter.java Fri Jan 22 16:31:21 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009 , 2010 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.
@@ -20,6 +20,8 @@
import java.lang.annotation.RetentionPolicy;
import static org.apache.tapestry5.ioc.annotations.AnnotationUseContext.MIXIN;
+
+import org.apache.tapestry5.internal.transform.BindParameterWorker;
import org.apache.tapestry5.ioc.annotations.UseWith;
@@ -34,7 +36,8 @@
* uservariable <=> mixin.value <=> component.value.
* Changes to any one value in the chain will be propagated accordingly.
*
- * @since 5.2.0.0
+ * @since 5.2.0
+ * @see BindParameterWorker
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java Fri Jan 22 16:31:21 2010
@@ -4,7 +4,7 @@
// 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
+// 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,
@@ -18,7 +18,9 @@
import org.apache.tapestry5.internal.services.PersistentFieldManager;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.internal.structure.PageResetListener;
+import org.apache.tapestry5.internal.transform.ParameterConduit;
import org.apache.tapestry5.runtime.RenderQueue;
+import org.apache.tapestry5.services.FieldValueConduit;
/**
* An extension of {@link org.apache.tapestry5.ComponentResources} that represents additional
@@ -86,8 +88,17 @@
String... parentParameterNames);
/**
- * Delegates to {@link Page#addResetListener(org.apache.tapestry5.internal.structure.PageResetListener)}.
- * @param listener to register
+ * Delegates to
+ * {@link Page#addResetListener(org.apache.tapestry5.internal.structure.PageResetListener)}.
+ *
+ * @param listener
+ * to register
*/
void addPageResetListener(PageResetListener listener);
+
+ /** @since 5.2.0 */
+ FieldValueConduit getParameterConduit(String parameterName);
+
+ /** @since 5.2.0 */
+ void setParameterConduit(String parameterName, ParameterConduit conduit);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java Fri Jan 22 16:31:21 2010
@@ -55,6 +55,7 @@
import org.apache.tapestry5.services.ComponentMethodAdvice;
import org.apache.tapestry5.services.ComponentValueProvider;
import org.apache.tapestry5.services.FieldFilter;
+import org.apache.tapestry5.services.FieldValueConduit;
import org.apache.tapestry5.services.MethodFilter;
import org.apache.tapestry5.services.TransformMethodSignature;
import org.apache.tapestry5.services.TransformUtils;
@@ -2007,4 +2008,44 @@
makeReadOnly(fieldName);
}
+ @Override
+ public void replaceFieldAccess(String fieldName,
+ ComponentValueProvider<FieldValueConduit> conduitProvider)
+ {
+ replaceFieldAccess(fieldName, addIndirectInjectedField(FieldValueConduit.class, fieldName
+ + "$conduit", conduitProvider));
+ }
+
+ @Override
+ public void replaceFieldAccess(String fieldName, String conduitFieldName)
+ {
+ String fieldType = getFieldType(fieldName);
+
+ String readMethodName = newMemberName("get", fieldName);
+
+ TransformMethodSignature readSig = new TransformMethodSignature(Modifier.PRIVATE,
+ fieldType, readMethodName, null, null);
+
+ 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.
+
+ addMethod(readSig, String.format("return ($r) ((%s) %s.get());", cast, conduitFieldName));
+
+ replaceReadAccess(fieldName, readMethodName);
+
+ String writeMethodName = newMemberName("set", fieldName);
+
+ TransformMethodSignature writeSig = new TransformMethodSignature(Modifier.PRIVATE, "void",
+ writeMethodName, new String[]
+ { fieldType }, null);
+
+ addMethod(writeSig, String.format("%s.set(($w) $1);", conduitFieldName));
+
+ replaceWriteAccess(fieldName, writeMethodName);
+
+ removeField(fieldName);
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java Fri Jan 22 16:31:21 2010
@@ -32,6 +32,7 @@
import org.apache.tapestry5.internal.ParameterChangeListener;
import org.apache.tapestry5.internal.ParameterChangedEvent;
import org.apache.tapestry5.internal.services.Instantiator;
+import org.apache.tapestry5.internal.transform.ParameterConduit;
import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.Location;
import org.apache.tapestry5.ioc.Messages;
@@ -45,6 +46,7 @@
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.PageLifecycleListener;
import org.apache.tapestry5.runtime.RenderQueue;
+import org.apache.tapestry5.services.FieldValueConduit;
import org.slf4j.Logger;
/**
@@ -79,6 +81,10 @@
// Case-insensitive map from container-parameter name to ParameterAccess, for BindParameter.
// Should only ever be used for mixins.
private Map<String, ParameterAccess> containerParameterAccess;
+
+ // Case insentive map from parameter name to ParameterConduit, used to support mixins
+ // which need access to the containing component's PC's
+ private Map<String, ParameterConduit> conduits;
private Messages messages;
@@ -779,4 +785,20 @@
{
page.addResetListener(listener);
}
+
+ @Override
+ public FieldValueConduit getParameterConduit(String parameterName)
+ {
+ return InternalUtils.get(conduits, parameterName);
+ }
+
+ @Override
+ public void setParameterConduit(String parameterName, ParameterConduit conduit)
+ {
+ if (conduits == null) conduits = CollectionFactory.newCaseInsensitiveMap();
+
+ conduits.put(parameterName, conduit);
+ }
+
+
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java Fri Jan 22 16:31:21 2010
@@ -18,16 +18,17 @@
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.bindings.LiteralBinding;
-import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.runtime.Component;
+import org.apache.tapestry5.services.FieldValueConduit;
/**
* A facade around {@link Binding} and {@link InternalComponentResources} that is used to instrument
- * fields with the {@link Parameter} annotation.
+ * fields with the {@link Parameter} annotation. Extends {@link FieldValueConduit} so that
+ * the get() method implicitly coerces the value to the field's type.
*
* @since 5.2.0
*/
-public interface ParameterConduit
+public interface ParameterConduit extends FieldValueConduit
{
/**
* Sets the default value for the parameter based on either the current value of the field,
@@ -41,24 +42,6 @@
void setDefault(Object defaultValue);
/**
- * Reads the current value of the parameter (via the {@link Binding}) and uses the
- * {@link TypeCoercer} to convert the actual value to one assignable to the underlying field.
- * The actual read value may be cached.
- *
- * @throws RuntimeException
- * if the parameter does not allow null but the current value is null
- * @return current value (possibly null)
- */
- Object get();
-
- /**
- * Sets the value of the parameter, pushing it through the {@link Binding}.
- *
- * @param newValue
- */
- void set(Object newValue);
-
- /**
* Determines if the parameter is actually bound.
*
* @return
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker2.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker2.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker2.java Fri Jan 22 16:31:21 2010
@@ -14,7 +14,6 @@
package org.apache.tapestry5.internal.transform;
-import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
@@ -36,7 +35,6 @@
import org.apache.tapestry5.services.MethodFilter;
import org.apache.tapestry5.services.TransformConstants;
import org.apache.tapestry5.services.TransformMethodSignature;
-import org.apache.tapestry5.services.TransformUtils;
public class ParameterWorker2 implements ComponentClassTransformWorker
{
@@ -107,7 +105,7 @@
// better
// if there was a way to defer until the component's page loaded lifecycle method). The
// issues
- // are addressed by deferring some behaviors until the reset() method.
+ // are addressed by deferring some behaviors until the load() method.
@Override
public ParameterConduit get(ComponentResources resources)
@@ -116,8 +114,6 @@
final Class fieldType = classCache.forName(fieldTypeName);
- // final ParameterAccess parameterAccess = icr.getParameterAccess(parameterName);
-
// Rely on some code generation in the component to set the default binding from
// the field, or from a default method.
@@ -149,15 +145,11 @@
if (javaType.isPrimitive())
{
- if (javaType == boolean.class)
- {
- defaultValue = false;
- }
- else
- {
- defaultValue = typeCoercer.coerce(0l, javaType);
- }
+ // Reminder: 0 coerces to false
+ defaultValue = typeCoercer.coerce(0l, javaType);
}
+
+ icr.setParameterConduit(parameterName, this);
}
private boolean isInvariant()
@@ -184,19 +176,15 @@
return;
}
- // TODO: Disable parameter change listener before updating PA
-
// This will catch read-only or unbound parameters.
parameterAccess.write(newValue);
- // TODO: Re-enable parameter change listener after updating PA
-
value = newValue;
// If caching is enabled for the parameter (the typical case) and the
// component is currently rendering, then the result
- // can be cached in the ParameterConduit (until the component finished
+ // can be cached in the ParameterConduit (until the component finishes
// rendering).
cached = enableCaching && icr.isRendering();
@@ -215,22 +203,19 @@
@Override
public void load()
{
- boolean isBound = icr.isBound(parameterName);
-
-
// If it's bound at this point, that's because of an explicit binding
// in the template or @Component annotation.
-
+
if (!icr.isBound(parameterName))
{
// Otherwise, construct a default binding, or use one provided from
// the component.
-
+
Binding binding = getDefaultBindingForParameter();
if (binding != null)
icr.bindParameter(parameterName, binding);
-
+
defaultBinding = null;
}
@@ -250,9 +235,10 @@
if (annotation.autoconnect())
return defaultProvider.defaultBinding(parameterName, icr);
- // Return (if not null) the binding from the setDefault() method which is set
- // via a default method on the component, or from the field's initial value.
-
+ // Return (if not null) the binding from the setDefault() method which is
+ // set via a default method on the component, or from the field's initial
+ // value.
+
return defaultBinding;
}
@@ -277,7 +263,7 @@
// If the value is invariant, we can cache it forever. Otherwise, we
// we may want to cache it for the remainder of the component render (if the
// component is currently rendering).
-
+
if (isInvariant() || (enableCaching && icr.isRendering()))
{
value = result;
@@ -313,9 +299,7 @@
addCodeForParameterDefaultMethod(transformation, parameterName, conduitFieldName);
- addParameterWriteMethod(transformation, fieldName, fieldTypeName, conduitFieldName);
-
- addParameterReadMethod(transformation, fieldName, fieldTypeName, conduitFieldName);
+ transformation.replaceFieldAccess(fieldName, conduitFieldName);
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, String
.format("%s.load();", conduitFieldName));
@@ -323,43 +307,6 @@
transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, String
.format("%s.reset();", conduitFieldName));
- transformation.removeField(fieldName);
- }
-
- private void addParameterReadMethod(ClassTransformation transformation, String fieldName,
- final String fieldTypeName, String conduitFieldName)
- {
- String readMethodName = transformation.newMemberName("read_parameter", fieldName);
-
- TransformMethodSignature readSig = new TransformMethodSignature(Modifier.PRIVATE,
- fieldTypeName, readMethodName, null, null);
-
- String cast = TransformUtils.getWrapperTypeName(fieldTypeName);
-
- // 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.
-
- transformation.addMethod(readSig, String.format("return ($r) ((%s) %s.get());", cast,
- conduitFieldName));
-
- transformation.replaceReadAccess(fieldName, readMethodName);
- }
-
- private void addParameterWriteMethod(ClassTransformation transformation, String fieldName,
- String fieldTypeName, String conduitFieldName)
- {
- String writeMethodName = transformation.newMemberName("update_parameter", fieldName);
-
- TransformMethodSignature writeSig = new TransformMethodSignature(Modifier.PRIVATE, "void",
- writeMethodName, new String[]
- { fieldTypeName }, null);
-
- transformation.addMethod(writeSig, String.format("%s.set(($w) $1);", conduitFieldName));
-
- transformation.replaceWriteAccess(fieldName, writeMethodName);
}
private void addCodeForParameterDefaultMethod(ClassTransformation transformation,
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java?rev=902156&r1=902155&r2=902156&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java Fri Jan 22 16:31:21 2010
@@ -249,7 +249,7 @@
* Like {@link #addInjectedField(Class, String, Object)}, but instead of specifying the value,
* a provider for the value is specified. In the generated class' constructor, the provider
* will be passed the {@link ComponentResources} and will return the final value; thus
- * each component <em>instance</em> will receive a unique
+ * each component <em>instance</em> will receive a matching unique instance via the provider.
*
* @param <T>
* @param type
@@ -519,4 +519,28 @@
*/
<T> void assignFieldIndirect(String fieldName, TransformMethodSignature methodSig,
ComponentValueProvider<T> provider);
+
+ /**
+ * Replaces read and write field access with a conduit. The field will be deleted.
+ *
+ * @param fieldName
+ * field to replace
+ * @param conduitProvider
+ * provides the actual conduit at class instantiation time
+ * @since 5.2.0
+ */
+ void replaceFieldAccess(String fieldName,
+ ComponentValueProvider<FieldValueConduit> conduitProvider);
+
+ /**
+ * Replaces read and write field access with a previously injected conduit (identified by its
+ * field name). The conduit must implement {@link FieldValueConduit}. The field will be removed.
+ *
+ * @since 5.2.0
+ * @param fieldName
+ * field to replace
+ * @param conduitFieldName
+ * name of field which will have an instance of {@link FieldValueConduit}
+ */
+ void replaceFieldAccess(String fieldName, String conduitFieldName);
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java?rev=902156&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java Fri Jan 22 16:31:21 2010
@@ -0,0 +1,46 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services;
+
+import org.apache.tapestry5.Binding;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+
+/**
+ * A callback object that is used to replace storage of a value inside a component field.
+ *
+ * @since 5.2.0
+ */
+public interface FieldValueConduit
+{
+
+ /**
+ * Reads the current value of the parameter (via the {@link Binding}) and uses the
+ * {@link TypeCoercer} to convert the actual value to one assignable to the underlying field.
+ * The actual read value may be cached.
+ *
+ * @throws RuntimeException
+ * if the parameter does not allow null but the current value is null
+ * @return current value (possibly null)
+ */
+ Object get();
+
+ /**
+ * Sets the value of the parameter, pushing it through the {@link Binding}.
+ *
+ * @param newValue
+ */
+ void set(Object newValue);
+
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java
------------------------------------------------------------------------------
svn:eol-style = native