Hi. Let me explain. Imagine that we have standard tapestry page:
Templates.java and of course we have template of this page Templates.tml and
it works perfect. But I need to change template of this page by user
request. More precisely I want to use one java class (Templates.java) with
many templates files (Template1.tml, Template2.tml, etc). And of course
EventLinks, ActionLinks, Zones, Componenst should work as usual.

Our team has spent much time to get this work by using tapestry standard
features. But no luck. I have working solution based on reflection wich
brakes oop ideology.
I introduce an interface:

public interface PageLoadService {
        Page loadPage(String defaultPageName, String templateName, Locale 
locale,
Object coreComponent);
} 

Where defaultPageName is default template (Templates.tml), templateName is
overriding template (Template1.tml, etc) and coreComponent is instance of
Page (Template.java instance). 

And in Template.onActivate() i use this interface like this:

        @Inject
        private PageResponseRenderer renderer;
        
        @Inject
        private PageLoadService pageLoadService;

        public void onActivate() {
                if (request.isXHR()) {
                        //Ajax 
                        return;
                }
                
                if (request.getPath().contains(":") || 
request.getPath().contains(".")) {
                        //EVENT, ACTION, ZONE
                        return;
                }
                
                if (template == null || template.equals(BASIC_TEMPLATE)) {
                        //Default approach
                        return;
                }

                Page page = pageLoadService.loadPage(
                                BASIC_TEMPLATE, 
                                template, 
                                Locale.getDefault(),
                                this);

                try {
                        page.attached();
                        renderer.renderPageResponse(page);
                        page.detached();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

Let me explain. I'm trying to use default approach (without templating
Template.tml+Template.java) to handle ajax,zone,event|action links requests,
and PageResponseRenderer to render page in other requests. And it works
(tested T5.1.05 and T5.2.0, 5.2.6). But tapestry is huge project, and i'm
not sure if there are hidden problems, what do you think?

---
Realization of PageLoadService is really ugly:

package org.apache.tapestry5.internal.pageload;

import java.lang.reflect.Method;
import java.util.Locale;

import org.apache.tapestry5.internal.parser.ComponentTemplate;
import org.apache.tapestry5.internal.services.ComponentInstantiatorSource;
import org.apache.tapestry5.internal.services.Instantiator;
import org.apache.tapestry5.internal.services.PageLoader;
import org.apache.tapestry5.internal.services.PersistentFieldManager;
import org.apache.tapestry5.internal.services.TemplateParser;
import org.apache.tapestry5.internal.structure.ComponentPageElement;
import
org.apache.tapestry5.internal.structure.ComponentPageElementResources;
import
org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.internal.structure.PageImpl;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.model.ComponentModel;
import org.apache.tapestry5.services.ComponentClassResolver;

public class PageLoadServiceT5_1Impl implements PageLoadService {

        private final PageLoaderImpl internalPageLoader;

        private final ComponentInstantiatorSource
internalInstantiatorSource;
        private final TemplateParser internalTemplateParser;
        private final ComponentPageElementResourcesSource
internalResourcesSource;
        private final ComponentClassResolver internalComponentClassResolver;
        private final PersistentFieldManager internalPersistentFieldManager;
        private final Method internalProgramAssembler;
   
        public PageLoadServiceT5_1Impl(PageLoader tapestryPageLoader,
TemplateParser templateParser) {
                this.internalPageLoader =
                        ReflectionToolkit.getDelegate(tapestryPageLoader);
                this.internalInstantiatorSource =
                        ReflectionToolkit.getField(internalPageLoader,
"instantiatorSource");
                this.internalResourcesSource =
                        ReflectionToolkit.getField(internalPageLoader,
"resourcesSource");
                this.internalComponentClassResolver =
                        ReflectionToolkit.getField(internalPageLoader,
"componentClassResolver");
                this.internalPersistentFieldManager =
                        ReflectionToolkit.getField(internalPageLoader,
"persistentFieldManager");
                this.internalProgramAssembler =
                        ReflectionToolkit.getMethod(internalPageLoader,
"programAssembler");

                this.internalTemplateParser = templateParser;
        }

        public Page loadPage(String defaultPageName, String pageName, Locale
locale, Object coreComponent) {
        Page page = new PageImpl(defaultPageName, locale,
internalPersistentFieldManager);
        ComponentAssembler assembler = createAssembler(pageName,
coreComponent.getClass().getCanonicalName(), locale);
        ComponentPageElement rootElement =
assembler.assembleRootComponent(page);

       
        Object newCoreComponent = ReflectionToolkit.getField(rootElement,
"coreComponent");
        ReflectionToolkit.copyAnnotatedFields(coreComponent,
newCoreComponent, CopyField.class);
       
        page.setRootElement(rootElement);
        page.loaded();
        return page;
        }

    private ComponentAssembler createAssembler(String pageName, String
className, Locale locale)
    {
        Instantiator instantiator =
internalInstantiatorSource.getInstantiator(className);

        ComponentModel componentModel = instantiator.getModel();

        Resource templateResource =
componentModel.getBaseResource().forFile(pageName + ".tml");
                ComponentTemplate template =
internalTemplateParser.parseTemplate(templateResource);

        ComponentPageElementResources resources =
internalResourcesSource.get(locale);

        ComponentAssembler assembler = new ComponentAssemblerImpl(
        internalPageLoader,
        internalInstantiatorSource,
        internalComponentClassResolver,
        instantiator,
        resources,
        locale);

        try {
                        internalProgramAssembler.invoke(internalPageLoader,
assembler, template);
                } catch (Exception e) {
                        throw new RuntimeException(e);
                }
       
        return assembler;
    }
   
}

---
Also this approach always creates new instance of Template.java and we
loosing setted context. But it is not a big problem - just copy fields from
one class to another.

--
View this message in context: 
http://tapestry.1045711.n5.nabble.com/Another-approach-to-dynamic-templating-T5-1-0-5-tp4868869p4868869.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to