Package org.apache.tapestry.internal.services

Source Code of org.apache.tapestry.internal.services.LinkFactoryImpl$PassivateContextHandler

// Copyright 2006, 2007 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.tapestry.internal.services;

import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newThreadSafeList;
import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
import static org.apache.tapestry.ioc.internal.util.Defense.notNull;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.net.URLCodec;
import org.apache.tapestry.ComponentEventHandler;
import org.apache.tapestry.Link;
import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.structure.ComponentPageElement;
import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.ioc.services.TypeCoercer;
import org.apache.tapestry.ioc.util.StrategyRegistry;
import org.apache.tapestry.runtime.Component;
import org.apache.tapestry.services.ComponentClassResolver;

public class LinkFactoryImpl implements LinkFactory
{
    private final ContextPathSource _contextPathSource;

    private final URLEncoder _encoder;

    private final ComponentClassResolver _componentClassResolver;

    private final ComponentInvocationMap _componentInvocationMap;

    private final RequestPageCache _pageCache;

    private final TypeCoercer _typeCoercer;

    private final List<LinkFactoryListener> _listeners = newThreadSafeList();

    private final StrategyRegistry<PassivateContextHandler> _registry;

    // URLCodec is thread-safe and sharable.
    private final URLCodec _urlCodec = new URLCodec();

    private interface PassivateContextHandler<T>
    {
        void handle(T result, List context);
    }

    public LinkFactoryImpl(ContextPathSource contextPathSource, URLEncoder encoder,
            ComponentClassResolver componentClassResolver,
            ComponentInvocationMap componentInvocationMap, RequestPageCache pageCache,
            TypeCoercer typeCoercer)
    {
        _contextPathSource = contextPathSource;
        _encoder = encoder;
        _componentClassResolver = componentClassResolver;
        _componentInvocationMap = componentInvocationMap;
        _pageCache = pageCache;
        _typeCoercer = typeCoercer;

        Map<Class, PassivateContextHandler> registrations = newMap();

        registrations.put(Object.class, new PassivateContextHandler()
        {
            @SuppressWarnings("unchecked")
            public void handle(Object result, List context)
            {
                context.add(result);
            }
        });

        registrations.put(Object[].class, new PassivateContextHandler<Object[]>()
        {

            @SuppressWarnings("unchecked")
            public void handle(Object[] result, List context)
            {
                for (Object o : result)
                    context.add(o);
            }
        });

        registrations.put(Collection.class, new PassivateContextHandler<Collection>()
        {
            @SuppressWarnings("unchecked")
            public void handle(Collection result, List context)
            {
                context.addAll(result);
            }
        });

        _registry = StrategyRegistry.newInstance(PassivateContextHandler.class, registrations);
    }

    public void addListener(LinkFactoryListener listener)
    {
        _listeners.add(listener);
    }

    public Link createActionLink(ComponentPageElement component, String action, boolean forForm,
            Object... context)
    {
        notBlank(action, "action");

        Page containingPage = component.getContainingPage();
        String pageName = containingPage.getName();

        String logicalPageName = _componentClassResolver.resolvePageClassNameToPageName(pageName);

        ActionLinkTarget target = new ActionLinkTarget(action, logicalPageName, component
                .getNestedId());

        String[] contextStrings = toContextStrings(context);

        String[] activationContext = collectActivationContextForPage(containingPage);

        ComponentInvocation invocation = new ComponentInvocation(target, contextStrings,
                activationContext);

        Link link = new LinkImpl(_encoder, _contextPathSource.getContextPath(), invocation, forForm);

        // Now see if the page has an activation context.

        addActivationContextToLink(link, activationContext);

        // TODO: query parameter for case where active page != component page.

        _componentInvocationMap.store(link, invocation);

        for (LinkFactoryListener listener : _listeners)
            listener.createdActionLink(link);

        return link;
    }

    private void addActivationContextToLink(Link link, String[] activationContext)
    {
        if (activationContext.length == 0)
            return;

        StringBuilder builder = new StringBuilder();

        try
        {
            for (int i = 0; i < activationContext.length; i++)
            {
                if (i > 0)
                    builder.append("/");

                builder.append(_urlCodec.encode(activationContext[i]));
            }
        }
        catch (Exception ex)
        {
            throw new RuntimeException(ex);
        }

        link.addParameter(InternalConstants.PAGE_CONTEXT_NAME, builder.toString());

    }

    public Link createPageLink(final Page page, Object... activationContext)
    {
        notNull(page, "page");

        String pageName = page.getName();
        String logicalPageName = _componentClassResolver.resolvePageClassNameToPageName(pageName);

        String[] context = activationContext.length != 0 ? toContextStrings(activationContext)
                : collectActivationContextForPage(page);

        PageLinkTarget target = new PageLinkTarget(logicalPageName);
        ComponentInvocation invocation = new ComponentInvocation(target, context, null);

        Link link = new LinkImpl(_encoder, _contextPathSource.getContextPath(), invocation, false);

        _componentInvocationMap.store(link, invocation);

        for (LinkFactoryListener listener : _listeners)
            listener.createdPageLink(link);

        return link;
    }

    /**
     * Returns a list of objects acquired by invoking triggering the passivate event on the page's
     * root element. May return an empty list.
     */
    private String[] collectActivationContextForPage(final Page page)
    {
        final List context = newList();

        ComponentEventHandler handler = new ComponentEventHandler()
        {
            @SuppressWarnings("unchecked")
            public boolean handleResult(Object result, Component component, String methodDescription)
            {
                PassivateContextHandler contextHandler = _registry.getByInstance(result);

                contextHandler.handle(result, context);

                return true;
            }
        };

        ComponentPageElement rootElement = page.getRootElement();

        rootElement.triggerEvent(TapestryConstants.PASSIVATE_EVENT, null, handler);

        return toContextStrings(context.toArray());
    }

    private String[] toContextStrings(Object[] context)
    {
        if (context == null)
            return new String[0];

        String[] result = new String[context.length];

        for (int i = 0; i < context.length; i++)
            result[i] = _typeCoercer.coerce(context[i], String.class);

        return result;
    }

    public Link createPageLink(String pageName, Object... context)
    {
        // This verifies that the page name is valid.
        Page page = _pageCache.get(pageName);

        return createPageLink(page, context);
    }
}
TOP

Related Classes of org.apache.tapestry.internal.services.LinkFactoryImpl$PassivateContextHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.