    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
    015    package org.apache.tapestry5.internal.services;
    016
    017    import java.util.List;
    018
    019    import org.apache.tapestry5.Link;
    020    import org.apache.tapestry5.internal.TapestryInternalUtils;
    021    import org.apache.tapestry5.internal.structure.Page;
    022    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
    023    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    024    import org.apache.tapestry5.ioc.services.TypeCoercer;
    025    import org.apache.tapestry5.services.ComponentClassResolver;
    026    import org.apache.tapestry5.services.ComponentEventLinkEncoder;
    027    import org.apache.tapestry5.services.ComponentEventRequestParameters;
    028    import org.apache.tapestry5.services.LinkCreationHub;
    029    import org.apache.tapestry5.services.LinkCreationListener;
    030    import org.apache.tapestry5.services.LinkCreationListener2;
    031    import org.apache.tapestry5.services.PageRenderRequestParameters;
    032    import org.apache.tapestry5.services.RequestGlobals;
    033
    034    @SuppressWarnings("all")
    035    public 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    }