All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.unbound.tapestry.breadcrumbs.BreadCrumbDispatcher Maven / Gradle / Ivy

There is a newer version: 1.9
Show newest version
package se.unbound.tapestry.breadcrumbs;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;

import org.apache.tapestry5.EventContext;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.services.ApplicationStateManager;
import org.apache.tapestry5.services.ComponentEventLinkEncoder;
import org.apache.tapestry5.services.ComponentSource;
import org.apache.tapestry5.services.Dispatcher;
import org.apache.tapestry5.services.PageRenderLinkSource;
import org.apache.tapestry5.services.PageRenderRequestParameters;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.Response;

/**
 * Dispatcher which checks pages for the {@link BreadCrumb} annotation and adds a new crumb to the
 * {@link BreadCrumbList}.
 */
public class BreadCrumbDispatcher implements Dispatcher {
    private final ApplicationStateManager applicationStateManager;
    private final ComponentSource componentSource;
    private final PageRenderLinkSource pageRenderLinkSource;
    private final ComponentEventLinkEncoder componentEventLinkEncoder;

    /**
     * Constructs a new {@link BreadCrumbDispatcher}.
     * 
     * @param applicationStateManager The {@link ApplicationStateManager} to fetch the {@link BreadCrumbList} from.
     * @param componentSource The {@link ComponentSource} to use to retrieve page instances from.
     * @param pageRenderLinkSource The {@link PageRenderLinkSource} to use to render the {@link Link} for the crumb.
     */
    public BreadCrumbDispatcher(final ApplicationStateManager applicationStateManager,
            final ComponentSource componentSource, final PageRenderLinkSource pageRenderLinkSource,
            final ComponentEventLinkEncoder componentEventLinkEncoder) {
        this.applicationStateManager = applicationStateManager;
        this.componentSource = componentSource;
        this.pageRenderLinkSource = pageRenderLinkSource;
        this.componentEventLinkEncoder = componentEventLinkEncoder;
    }

    @Override
    public boolean dispatch(final Request tapestryRequest, final Response tapestryResponse)
            throws IOException {
        final PageRenderRequestParameters requestParameters = this.componentEventLinkEncoder
                .decodePageRenderRequest(tapestryRequest);

        if (requestParameters == null) {
            return false;
        }

        final Component previousPage;
        final String referrer = tapestryRequest.getHeader("Referer");
        final ReferrerRequest referrerRequest = ReferrerRequest.fromUri(referrer, tapestryRequest);
        if (referrerRequest != null) {
            final PageRenderRequestParameters referrerParameters = this.componentEventLinkEncoder
                    .decodePageRenderRequest(referrerRequest);
            if (referrerParameters != null) {
                previousPage = this.componentSource.getPage(referrerParameters.getLogicalPageName());
            } else {
                previousPage = null;
            }
        } else {
            previousPage = null;
        }

        /* Is the requested page tagged with BreadCrumb- or BreadCrumbReset-annotation? */
        final Component page = this.componentSource.getPage(requestParameters.getLogicalPageName());

        final BreadCrumbList breadCrumbList = this.applicationStateManager.get(BreadCrumbList.class);
        final BreadCrumbReset reset = this.findAnnotation(page.getClass(), BreadCrumbReset.class);
        if (reset != null) {
            if (previousPage == null
                    || !this.previousPageIsIgnored(previousPage.getClass(), reset.ignorePages())) {
                breadCrumbList.reset();
            }
        }

        final BreadCrumb annotation = this.findAnnotation(page.getClass(), BreadCrumb.class);
        if (annotation != null) {
            final String titleKey = annotation.titleKey();

            final EventContext context = requestParameters.getActivationContext();

            final Link link = this.pageRenderLinkSource.createPageRenderLinkWithContext(
                    requestParameters.getLogicalPageName(), context);
            final BreadCrumbInfo breadCrumbInfo = new BreadCrumbInfo(titleKey, link,
                    requestParameters.getLogicalPageName());

            breadCrumbList.add(breadCrumbInfo);
        }

        return false;
    }

    private boolean previousPageIsIgnored(final Class pageClass, final Class[] ignorePages) {
        return Arrays.asList(ignorePages).contains(pageClass);
    }

    private  T findAnnotation(final Class clazz, final Class annotation) {
        T result = clazz.getAnnotation(annotation);

        if (result == null && clazz.getSuperclass() != null) {
            result = this.findAnnotation(clazz.getSuperclass(), annotation);
        }

        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy