Author: hlship
Date: Fri Feb 19 18:53:19 2010
New Revision: 911911
URL: http://svn.apache.org/viewvc?rev=911911&view=rev
Log:
Add support for direct field access to TransformField
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java
(with props)
Modified:
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/services/MethodAccess.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
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=911911&r1=911910&r2=911911&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 Feb 19 18:53:19 2010
@@ -56,6 +56,14 @@
new Class[]
{ Object.class, Object[].class }, null);
+ public static final MethodSignature FIELD_ACCESS_READ_SIGNATURE = new
MethodSignature(Object.class, "read",
+ new Class[]
+ { Object.class }, null);
+
+ public static final MethodSignature FIELD_ACCESS_WRITE_SIGNATURE = new
MethodSignature(void.class, "write",
+ new Class[]
+ { Object.class, Object.class }, null);
+
private static final int INIT_BUFFER_SIZE = 100;
private boolean frozen;
@@ -385,6 +393,8 @@
String readValueBody, writeValueBody;
+ private org.apache.tapestry5.services.FieldAccess access;
+
TransformFieldImpl(CtField field, boolean added)
{
this.field = field;
@@ -481,7 +491,7 @@
failIfFrozen();
if (writeValueBody != null)
- throw new IllegalStateException(String.format("Field %s.%s has
already had write access replaces.",
+ throw new IllegalStateException(String.format("Field %s.%s has
already had write access replaced.",
getClassName(), name));
// Explicitly reference $0 (aka "this") because of TAPESTRY-1511.
@@ -494,6 +504,97 @@
fieldAccessReplaced = true;
}
+ public org.apache.tapestry5.services.FieldAccess getAccess()
+ {
+ failIfFrozen();
+
+ if (access == null)
+ createAccess();
+
+ return access;
+ }
+
+ private void createAccess()
+ {
+ TransformMethod reader = createReader();
+ TransformMethod writer = createWriter();
+
+ access = createFieldAccess(reader, writer);
+ }
+
+ private org.apache.tapestry5.services.FieldAccess
createFieldAccess(TransformMethod reader,
+ TransformMethod writer)
+ {
+ ClassFab cf =
classFactory.newClass(org.apache.tapestry5.services.FieldAccess.class);
+
+ addFieldAccessReadMethod(cf, reader);
+ addFieldAccessWriteMethod(cf, writer);
+
+ cf.addToString(String.format("FieldAccess<%s.%s>", getClassName(),
name));
+
+ Class accessClass = cf.createClass();
+
+ try
+ {
+ return (org.apache.tapestry5.services.FieldAccess)
accessClass.newInstance();
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private void addFieldAccessReadMethod(ClassFab cf, TransformMethod
readAccess)
+ {
+ BodyBuilder builder = new BodyBuilder().begin();
+
+ builder.addln("%s instance = (%<s) $1;", getClassName());
+ builder.addln("return ($w) instance.%s();",
readAccess.getSignature().getMethodName());
+
+ builder.end();
+
+ cf.addMethod(Modifier.PUBLIC, FIELD_ACCESS_READ_SIGNATURE,
builder.toString());
+ }
+
+ private void addFieldAccessWriteMethod(ClassFab cf, TransformMethod
writeAccess)
+ {
+ BodyBuilder builder = new BodyBuilder().begin();
+
+ builder.addln("%s instance = (%<s) $1;", getClassName());
+ builder.addln("%s value = %s;", type,
ClassFabUtils.castReference("$2", type));
+ builder.addln("instance.%s(value);",
writeAccess.getSignature().getMethodName());
+
+ builder.end();
+
+ cf.addMethod(Modifier.PUBLIC, FIELD_ACCESS_WRITE_SIGNATURE,
builder.toString());
+ }
+
+ private TransformMethod createReader()
+ {
+ String methodName = newMemberName("readaccess", name);
+
+ TransformMethodSignature signature = new
TransformMethodSignature(Modifier.PUBLIC, type, methodName, null,
+ null);
+
+ // Add the method as existing, so that the field access may be
replaced with a FieldValueConduit
+ // if necessary.
+ return addOrReplaceMethod(signature, String.format("return %s;",
name), false);
+ }
+
+ private TransformMethod createWriter()
+ {
+ String methodName = newMemberName("writeaccess", name);
+
+ TransformMethodSignature signature = new
TransformMethodSignature(Modifier.PUBLIC, "void", methodName,
+ new String[]
+ { type }, null);
+
+ // Add the method as existing, so that the field access may be
replaced with a FieldValueConduit
+ // if necessary.
+
+ return addOrReplaceMethod(signature, String.format("%s = $1;",
name), false);
+ }
+
public void remove()
{
if (removed)
@@ -1076,7 +1177,8 @@
addOrReplaceMethod(signature, methodBody, true);
}
- private void addOrReplaceMethod(TransformMethodSignature signature, String
methodBody, boolean addAsNew)
+ private TransformMethodImpl addOrReplaceMethod(TransformMethodSignature
signature, String methodBody,
+ boolean addAsNew)
{
failIfFrozen();
@@ -1088,6 +1190,8 @@
String action = "add" + suffix;
+ TransformMethodImpl result = null;
+
try
{
CtMethod existing =
ctClass.getDeclaredMethod(signature.getMethodName(), parameters);
@@ -1121,7 +1225,7 @@
ctClass.addMethod(method);
- recordMethod(method, addAsNew);
+ result = recordMethod(method, addAsNew);
}
catch (CannotCompileException ex)
{
@@ -1134,6 +1238,8 @@
}
addMethodToDescription(action, signature, methodBody);
+
+ return result;
}
public void addTransformedMethod(TransformMethodSignature signature,
String methodBody)
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java?rev=911911&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java
Fri Feb 19 18:53:19 2010
@@ -0,0 +1,42 @@
+// 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;
+
+/**
+ * Used when accessing the private instance variables of a component instance.
+ *
+ * @see TransformField#getAccess()
+ * @since 5.2.0
+ */
+public interface FieldAccess
+{
+ /**
+ * Reads the value of the field of the provided instance.
+ *
+ * @param instance
+ * object containing field to read
+ */
+ Object read(Object instance);
+
+ /**
+ * Updates the value of the field within the instance.
+ *
+ * @param instance
+ * object containing field to update
+ * @param value
+ * new value for field
+ */
+ void write(Object instance, Object value);
+}
Propchange:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldAccess.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java?rev=911911&r1=911910&r2=911911&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodAccess.java
Fri Feb 19 18:53:19 2010
@@ -20,6 +20,7 @@
* or the checked exception that is thrown).
*
* @since 5.2.0
+ * @see TransformMethod#getAccess()
*/
public interface MethodAccess
{
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java?rev=911911&r1=911910&r2=911911&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
Fri Feb 19 18:53:19 2010
@@ -75,7 +75,7 @@
void replaceAccess(TransformField conduitField);
/**
- * Replaces reand and write field access with a conduit. A new field is
created for the conduit instance,
+ * Replaces read and write field access with a conduit. A new field is
created for the conduit instance,
* and the original field is deleted.
*
* @param conduit
@@ -134,8 +134,12 @@
* type of field
* @param provider
* provides the value to be assigned to the field
- * @since 5.2.0
*/
<T> void injectIndirect(ComponentValueProvider<T> provider);
+ /**
+ * Returns an object that can be used to access the value of the field for
read and update.
+ * Changes to the field will honor any {...@link FieldValueConduit} that
has been applied to the field.
+ */
+ FieldAccess getAccess();
}