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();
 }


Reply via email to