Package jsx.application

Source Code of jsx.application.Application$Route

/*
* Copyright (C) 2012 Nameless Production Committee
*
* Licensed under the MIT License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*          http://opensource.org/licenses/mit-license.php
*/
package jsx.application;

import static js.lang.Global.*;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import js.dom.DocumentFragment;
import js.dom.UIAction;
import js.dom.UIEvent;
import jsx.event.Publishable;
import kiss.I;

/**
* @version 2012/12/11 14:19:29
*/
public abstract class Application {

    /** The page router. */
    private static final Router router = new Router();

    /**
     * <p>
     * Initialize application.
     * </p>
     */
    protected Application() {
        // Collect all pages and register it.
        for (Class page : I.findAs(Page.class)) {
            for (Constructor<?> constructor : page.getConstructors()) {
                PageInfo info = constructor.getAnnotation(PageInfo.class);

                if (info != null) {
                    if (info.path().contains("*")) {
                        router.wildcards.add(new Route(constructor, info));
                    } else {
                        router.route.put(info.path(), constructor);
                    }
                }
            }
        }

        // Activate router system.
        window.observe(UIAction.HashChange).to(router);

        // View initial page by URL.
        router.dispatch(location.hash);
    }

    /**
     * <p>
     * Configure header part.
     * </p>
     *
     * @param header
     */
    protected void configure(Header header) {
    }

    /**
     * <p>
     * Show page with effect.
     * </p>
     *
     * @param page
     */
    public static void show(Page page) {
        if (page != null) {
            router.dispatch(page.getPageId());
            history.pushState("", "", "#" + page.getPageId());
        }
    }

    /**
     * @version 2013/06/17 13:57:06
     */
    private static class Router implements Consumer<UIEvent> {

        /** The current page. */
        private static Page current;

        /** The page router. */
        private final Map<String, Constructor> route = new HashMap();

        /** The page router. */
        private final List<Route> wildcards = new ArrayList();

        /**
         * <p>
         * URI dispatcher.
         * </p>
         */
        @Override
        public void accept(UIEvent event) {
            dispatch(location.hash);
        }

        /**
         * <p>
         * Dispatch page by identifier
         * </p>
         *
         * @param pageId
         */
        private void dispatch(String pageId) {
            if (pageId.length() != 0 && pageId.startsWith("#")) {
                pageId = pageId.substring(1);
            }

            Constructor constructor = route.get(pageId);

            if (constructor != null) {
                try {
                    dispatch((Page) constructor.newInstance());
                } catch (Exception e) {
                    // do nothing
                }
            } else {
                for (Route route : wildcards) {
                    Page page = route.match(pageId);

                    if (page != null) {
                        dispatch(page);
                        return;
                    }
                }
            }
        }

        /**
         * <p>
         * Dispatch page.
         * </p>
         *
         * @param pageId
         */
        private void dispatch(Page page) {
            // fire page unload event
            if (page != null) {
                Publishable.Global.publish(new PageUnload(page));
            }

            // fire page load event
            // window.trigger(UIAction.PageLoad);

            // create element cradle
            DocumentFragment cradle = document.createDocumentFragment();

            // build page element
            page.load(cradle);

            // clear old page and append new page
            document.getElementById("Content").empty().append(cradle);

            // record page
            current = page;
        }
    }

    /**
     * @version 2013/01/18 10:43:43
     */
    private static class Route {

        /** The page pattern. */
        private final Pattern pattern;

        /** The page constructor. */
        private Constructor constructor;

        /**
         * <p>
         * Create new route.
         * </p>
         *
         * @param constructor
         * @param info
         */
        private Route(Constructor constructor, PageInfo info) {
            this.constructor = constructor;
            this.pattern = Pattern.compile(info.path().replaceAll("\\*", "([^/].+)"));
        }

        /**
         * <p>
         * Detect pattern matching.
         * </p>
         *
         * @param path
         * @return
         */
        private Page match(String path) {
            Matcher matcher = pattern.matcher(path);

            if (!matcher.matches()) {
                return null;
            } else {
                List<String> wildcards = new ArrayList();

                for (int i = 0; i < matcher.groupCount(); i++) {
                    wildcards.add(matcher.group(i + 1));
                }

                try {
                    return (Page) constructor.newInstance(wildcards.toArray());
                } catch (Exception e) {
                    return null;
                }
            }
        }
    }
}
TOP

Related Classes of jsx.application.Application$Route

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.