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