You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/02/19 19:54:04 UTC
svn commit: r911925 -
/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java
Author: hlship
Date: Fri Feb 19 18:54:03 2010
New Revision: 911925
URL: http://svn.apache.org/viewvc?rev=911925&view=rev
Log:
Recode PersistWorker to use FieldValueConduit
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java?rev=911925&r1=911924&r2=911925&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PersistWorker.java Fri Feb 19 18:54:03 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 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.
// 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,
@@ -14,106 +14,130 @@
package org.apache.tapestry5.internal.transform;
+import java.util.List;
+
+import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.Persist;
-import org.apache.tapestry5.ioc.util.BodyBuilder;
+import org.apache.tapestry5.internal.InternalComponentResources;
+import org.apache.tapestry5.internal.services.ComponentClassCache;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.model.MutableComponentModel;
-import org.apache.tapestry5.services.*;
-
-import java.lang.reflect.Modifier;
+import org.apache.tapestry5.runtime.PageLifecycleAdapter;
+import org.apache.tapestry5.services.ClassTransformation;
+import org.apache.tapestry5.services.ComponentClassTransformWorker;
+import org.apache.tapestry5.services.ComponentValueProvider;
+import org.apache.tapestry5.services.TransformField;
/**
* Converts fields with the {@link org.apache.tapestry5.annotations.Persist} annotation into persistent fields.
*/
public class PersistWorker implements ComponentClassTransformWorker
{
-
- public void transform(ClassTransformation transformation, MutableComponentModel model)
- {
- for (String name : transformation.findFieldsWithAnnotation(Persist.class))
- {
- makeFieldPersistent(name, transformation, model);
- }
- }
-
- /**
- * Making a field persistent: <ul> <li>Need a secondary default field that stores the initial value</li> <li>Store
- * the active value into the default field when the page finishes loading</li> <li>Roll the active value back to the
- * default when the page detaches</li> <ii>On changes to the active field, post the change via the {@link
- * org.apache.tapestry5.internal.InternalComponentResources} </li> <li>When the page attaches, pull the persisted
- * value for the field out of the {@link org.apache.tapestry5.services.PersistentFieldBundle}</li> </ul>
- *
- * @see org.apache.tapestry5.runtime.PageLifecycleListener#restoreStateBeforePageAttach()
- */
- private void makeFieldPersistent(String fieldName, ClassTransformation transformation,
- MutableComponentModel model)
+ class PersistentFieldConduit implements FieldValueConduit
{
- String fieldType = transformation.getFieldType(fieldName);
- Persist annotation = transformation.getFieldAnnotation(fieldName, Persist.class);
+ private final InternalComponentResources resources;
- transformation.claimField(fieldName, annotation);
+ private final String name;
- // Record the type of persistence, until needed later.
+ private final Object defaultValue;
- String logicalFieldName = model.setFieldPersistenceStrategy(fieldName, annotation.value());
+ private Object currentValue;
- String defaultValue = TransformUtils.getDefaultValue(fieldType);
+ public PersistentFieldConduit(InternalComponentResources resources, String name, Object defaultValue)
+ {
+ this.resources = resources;
+ this.name = name;
+ this.currentValue = defaultValue;
+ this.defaultValue = defaultValue;
+
+ resources.addPageLifecycleListener(new PageLifecycleAdapter()
+ {
+ @Override
+ public void containingPageDidDetach()
+ {
+ resetToDefaultAtPageDetach();
+ }
+
+ @Override
+ public void restoreStateBeforePageAttach()
+ {
+ restoreStateAtPageAttach();
+ }
+ });
+ }
- // Force the field back to its default value (null, 0, false) at the end of each request.
+ public Object get()
+ {
+ return currentValue;
+ }
- transformation.extendMethod(
- TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
- String.format("%s = %s;", fieldName, defaultValue));
+ public void set(Object newValue)
+ {
+ resources.persistFieldChange(name, newValue);
- String resourcesFieldName = transformation.getResourcesFieldName();
+ currentValue = newValue;
+ }
- String writeMethodName = transformation.newMemberName("write", fieldName);
+ private void resetToDefaultAtPageDetach()
+ {
+ currentValue = defaultValue;
+ }
- BodyBuilder builder = new BodyBuilder();
+ private void restoreStateAtPageAttach()
+ {
+ if (resources.hasFieldChange(name))
+ currentValue = resources.getFieldChange(name);
+ }
+ }
- builder.begin();
- builder.addln(
- "%s.persistFieldChange(\"%s\", ($w) $1);",
- resourcesFieldName,
- logicalFieldName);
- builder.addln("%s = $1;", fieldName);
- builder.end();
+ private final TypeCoercer typeCoercer;
- transformation.addMethod(new TransformMethodSignature(Modifier.PRIVATE, "void", writeMethodName,
- new String[]
- { fieldType }, null), builder.toString());
+ private final ComponentClassCache classCache;
- transformation.replaceWriteAccess(fieldName, writeMethodName);
+ public PersistWorker(TypeCoercer typeCoercer, ComponentClassCache classCache)
+ {
+ this.typeCoercer = typeCoercer;
+ this.classCache = classCache;
+ }
- builder.clear();
- builder.begin();
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ List<TransformField> fieldsWithAnnotation = transformation.matchFieldsWithAnnotation(Persist.class);
- // Check to see if there's a recorded change for this component, this field.
+ for (TransformField field : fieldsWithAnnotation)
+ {
+ makeFieldPersistent(field, model);
+ }
+ }
- builder.addln("if (%s.hasFieldChange(\"%s\"))", resourcesFieldName, logicalFieldName);
+ private void makeFieldPersistent(TransformField field, MutableComponentModel model)
+ {
+ Persist annotation = field.getAnnotation(Persist.class);
- String wrapperType = TransformUtils.getWrapperTypeName(fieldType);
+ field.claim(annotation);
- // Get the value, cast it to the correct type (or wrapper type)
- builder.add(
- " %s = ((%s) %s.getFieldChange(\"%s\"))",
- fieldName,
- wrapperType,
- resourcesFieldName,
- logicalFieldName);
+ final String logicalFieldName = model.setFieldPersistenceStrategy(field.getName(), annotation.value());
- // For primtive types, add in the method call to unwrap the wrapper type to a primitive type
+ final Object defaultValue = determineDefaultValueFromFieldType(field);
- String unwrapMethodName = TransformUtils.getUnwrapperMethodName(fieldType);
+ ComponentValueProvider<FieldValueConduit> provider = new ComponentValueProvider<FieldValueConduit>()
+ {
+ public FieldValueConduit get(ComponentResources resources)
+ {
+ return new PersistentFieldConduit((InternalComponentResources) resources, logicalFieldName,
+ defaultValue);
+ }
+ };
- if (unwrapMethodName == null)
- builder.addln(";");
- else
- builder.addln(".%s();", unwrapMethodName);
+ field.replaceAccess(provider);
+ }
- builder.end();
+ @SuppressWarnings("unchecked")
+ private Object determineDefaultValueFromFieldType(TransformField field)
+ {
+ Class javaType = classCache.forName(field.getType());
- transformation.extendMethod(
- TransformConstants.RESTORE_STATE_BEFORE_PAGE_ATTACH_SIGNATURE,
- builder.toString());
+ return javaType.isPrimitive() ? typeCoercer.coerce(0, javaType) : null;
}
}