    001// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.services;
    016
    017import java.util.List;
    018
    019import org.apache.tapestry5.commons.services.TypeCoercer;
    020import org.apache.tapestry5.commons.util.CollectionFactory;
    021import org.apache.tapestry5.http.Link;
    022import org.apache.tapestry5.http.services.RequestGlobals;
    023import org.apache.tapestry5.internal.TapestryInternalUtils;
    024import org.apache.tapestry5.internal.structure.Page;
    025import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    026import org.apache.tapestry5.services.ComponentClassResolver;
    027import org.apache.tapestry5.services.ComponentEventLinkEncoder;
    028import org.apache.tapestry5.services.ComponentEventRequestParameters;
    029import org.apache.tapestry5.services.LinkCreationHub;
    030import org.apache.tapestry5.services.LinkCreationListener;
    031import org.apache.tapestry5.services.LinkCreationListener2;
    032import org.apache.tapestry5.services.PageRenderRequestParameters;
    033
    034@SuppressWarnings("all")
    035public class LinkSourceImpl implements LinkSource, LinkCreationHub
    036{
    037    private final PageRenderQueue pageRenderQueue;
    038
    039    private final PageActivationContextCollector contextCollector;
    040
    041    private final ComponentEventLinkEncoder linkEncoder;
    042
    043    private final List<LinkCreationListener2> listeners = CollectionFactory.newThreadSafeList();
    044
    045    private final TypeCoercer typeCoercer;
    046
    047    private final ComponentClassResolver resolver;
    048
    049    private final RequestGlobals requestGlobals;
    050
    051    private final RequestPageCache pageCache;
    052
    053    public LinkSourceImpl(PageRenderQueue pageRenderQueue, PageActivationContextCollector contextCollector,
    054            TypeCoercer typeCoercer, ComponentClassResolver resolver, ComponentEventLinkEncoder linkEncoder,
    055            RequestGlobals requestGlobals, RequestPageCache pageCache, List<LinkCreationListener2> configuration)
    056    {
    057        this.pageRenderQueue = pageRenderQueue;
    058        this.contextCollector = contextCollector;
    059        this.typeCoercer = typeCoercer;
    060        this.resolver = resolver;
    061        this.linkEncoder = linkEncoder;
    062        this.requestGlobals = requestGlobals;
    063        this.pageCache = pageCache;
    064
    065        listeners.addAll(configuration);
    066    }
    067
    068    public Link createComponentEventLink(Page page, String nestedId, String eventType, boolean forForm,
    069            Object... eventContext)
    070    {
    071        assert page != null;
    072        assert InternalUtils.isNonBlank(eventType);
    073
    074        Page activePage = pageRenderQueue.getRenderingPage();
    075
    076        // See TAPESTRY-2184
    077        if (activePage == null)
    078            activePage = page;
    079
    080        String activePageName = activePage.getName();
    081
    082        Object[] pageActivationContext = contextCollector.collectPageActivationContext(activePageName);
    083
    084        ComponentEventRequestParameters parameters = new ComponentEventRequestParameters(activePageName,
    085                page.getName(), toBlank(nestedId), eventType,
    086                new ArrayEventContext(typeCoercer, pageActivationContext), new ArrayEventContext(typeCoercer,
    087                        eventContext));
    088
    089        Link link = linkEncoder.createComponentEventLink(parameters, forForm);
    090
    091        for (LinkCreationListener2 listener : listeners)
    092            listener.createdComponentEventLink(link, parameters);
    093
    094        return link;
    095    }
    096
    097    private String toBlank(String input)
    098    {
    099        return input == null ? "" : input;
    100    }
    101
    102    public Link createPageRenderLink(String pageName, boolean override, Object... pageActivationContext)
    103    {
    104        // Resolve the page name to its canonical format (the best version for URLs). This also
    105        // validates
    106        // the page name.
    107
    108        String canonical = resolver.canonicalizePageName(pageName);
    109
    110        Object[] context = (override || pageActivationContext.length != 0) ? pageActivationContext : contextCollector
    111                .collectPageActivationContext(canonical);
    112
    113        boolean loopback = canonical.equals(requestGlobals.getActivePageName())
    114                && pageCache.get(pageName).hasResetListeners();
    115
    116        PageRenderRequestParameters parameters = new PageRenderRequestParameters(canonical, new ArrayEventContext(
    117                typeCoercer, context), loopback);
    118
    119        Link link = linkEncoder.createPageRenderLink(parameters);
    120
    121        for (LinkCreationListener2 listener : listeners)
    122            listener.createdPageRenderLink(link, parameters);
    123
    124        return link;
    125    }
    126
    127    public LinkCreationHub getLinkCreationHub()
    128    {
    129        return this;
    130    }
    131
    132    public void addListener(LinkCreationListener listener)
    133    {
    134        assert listener != null;
    135
    136        addListener(TapestryInternalUtils.toLinkCreationListener2(listener));
    137    }
    138
    139    public void addListener(LinkCreationListener2 listener)
    140    {
    141        assert listener != null;
    142
    143        listeners.add(listener);
    144    }
    145}