I add cached property support to tapestry. A cached
property is actually a method in the form of a getter,
which will return an object could be used by page
components for several times, and worth cache it. For
example, a selection model containing data retrieved
from database, and the selection model could be used
several times in the template and the page class. 
The implementation consists of the following:
1. an EnhancementWorker class - CachePropertyWorker
2. hivemind config
========================
        <service-point id="CachePropertyWorker"
        
interface="org.apache.tapestry.enhance.EnhancementWorker">

                <invoke-factory>
                        <construct
                        
class="com.newtouch.newtouchone.tapestry.CachePropertyWorker"
/>
                </invoke-factory>
        </service-point>

        <contribution
        
configuration-id="tapestry.enhance.EnhancementWorkers">
                <command id="cache-properties"
                        object="service:CachePropertyWorker"
before="tapestry.enhance.abstract-property" />
        </contribution>
================================================

3. page spec definition, an specified property named
_cache will be defined, with its initial value as the
properties need to be cached. For example,
    <property name="_cache"
initial-value="literal:foo,bar" />
which will cache the result of getFoo() and getBar().
Maybe a better solution would be add an special tag,
such as <cache property="foo" />, but the
implementation might be more complex.

Yunfeng Hou



CachePropertyWorker.java
==============================
package com.newtouch.newtouchone.tapestry;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.hivemind.ErrorLog;
import org.apache.hivemind.Location;
import org.apache.hivemind.service.MethodSignature;
import org.apache.hivemind.util.StringUtils;
import org.apache.tapestry.enhance.EnhanceUtils;
import
org.apache.tapestry.enhance.EnhancementOperation;
import org.apache.tapestry.enhance.EnhancementWorker;
import org.apache.tapestry.event.PageDetachListener;
import
org.apache.tapestry.spec.IComponentSpecification;
import
org.apache.tapestry.spec.IPropertySpecification;

public class CachePropertyWorker implements
EnhancementWorker {

        private static final String LITERAL_PREFIX =
"literal:";

        private static final Class[] NULL_ARGS = new
Class[0];

        private ErrorLog _errorLog;

        private static final String GETTERBODY = "return
_cache.containsKey(\"XXX\")?"
                + "(TTT) _cache.get(\"XXX\"): "
                + "(TTT)
com.newtouch.newtouchone.tapestry.CachePropertyWorker"
                + ".cachedObject(\"XXX\", _cache, super.getXXX());";

        public void performEnhancement(EnhancementOperation
op,
                        IComponentSpecification spec) {
                Location location = (Location) spec.getLocation();

                IPropertySpecification propSpec = spec
                                .getPropertySpecification("_cache");
                if (propSpec == null)
                        return;
                String names = propSpec.getInitialValue();
                if (names == null ||
!names.startsWith(LITERAL_PREFIX))
                        return;

                String pageClassName = spec.getComponentClassName();
                Class pageClass = null;
                try {
                        pageClass = Class.forName(pageClassName);
                } catch (ClassNotFoundException e) {
                        _errorLog.error("page class not found:" +
pageClassName, location,
                                        e);
                        return;
                }

                op.addInjectedField("_cache", java.util.Map.class,
new HashMap());
                // createGetCacheMethod(op, location);

                names = names.substring(LITERAL_PREFIX.length());
                StringTokenizer st = new StringTokenizer(names, ",;
");
                while (st.hasMoreTokens()) {
                        String name = st.nextToken();
                        String getterName = "get" + name.substring(0,
1).toUpperCase()
                                        + name.substring(1);

                        try {
                                Method getter = pageClass.getMethod(getterName,
NULL_ARGS);
                                createProperty(op, getter, location);
                        } catch (Exception e) {
                                _errorLog.error("getter not found:" + 
getterName,
location, e);
                        }
                }

        }

        private void createProperty(EnhancementOperation op,
Method getter,
                        Location location) {

                String name = getter.getName().substring(3);
                String body = StringUtils.replace(GETTERBODY, "XXX",
name);
                body = StringUtils.replace(body, "TTT",
getter.getReturnType()
                                .getName());

                op
                                .addMethod(Modifier.PUBLIC, new
MethodSignature(getter
                                                .getReturnType(), 
getter.getName(), null, null),
body,
                                                location);
                
        
op.extendMethodImplementation(PageDetachListener.class,
                                EnhanceUtils.PAGE_DETACHED_SIGNATURE,
"_cache.clear();");
        }

        public void setErrorLog(ErrorLog errorLog) {
                _errorLog = errorLog;
        }

        public static Object cachedObject(String name, Map
cache, Object obj) {
                cache.put(name, obj);
                return obj;
        }

}


                
__________________________________________ 
Yahoo! DSL – Something to write home about. 
Just $16.99/mo. or less. 
dsl.yahoo.com 
<?xml version="1.0"?>
<module id="tapestry.spring" version="1.0.0">

	<service-point id="CachePropertyWorker"
		interface="org.apache.tapestry.enhance.EnhancementWorker">

		<invoke-factory>
			<construct
				class="com.newtouch.newtouchone.tapestry.CachePropertyWorker" />
		</invoke-factory>
	</service-point>

	<contribution
		configuration-id="tapestry.enhance.EnhancementWorkers">
		<command id="cache-properties"
			object="service:CachePropertyWorker" before="tapestry.enhance.abstract-property" />
	</contribution>

</module>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to