com.springsource.petclinic.web.menu.MenuLoader.java Source code

Java tutorial

Introduction

Here is the source code for com.springsource.petclinic.web.menu.MenuLoader.java

Source

/*
 * gvNIX is an open source tool for rapid application development (RAD).
 * Copyright (C) 2010 Generalitat Valenciana
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.springsource.petclinic.web.menu;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationContextException;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Menu model loader and publisher.
 * <p>
 * This class automatically is loaded by Spring ({@link Component} and
 * {@link Configurable}).
 * <p>
 * In application initialization ({@link WebApplicationObjectSupport}) loads
 * the menu structure and put it in the application context ready for
 * rendering. Then {@link ContextMenuStrategy} and security will decide which
 * section and items have to be shown.
 *
 * @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for
 *         <a href="http://www.dgti.gva.es">General Directorate for Information Technologies (DGTI)</a>
 */
@Component
@Configurable
public class MenuLoader extends WebApplicationObjectSupport {

    /** Configuration file for menus */
    public static final String MENU_CONFIG_FILE = "/WEB-INF/views/menu.xml";

    /** Key to store Menu in application context */
    public static final String MENU_SERVLET_CONTEXT_KEY = "gvnixMenu";

    public static final String MENU_ITEM_ELEMENT = "menu-item";

    /**
     * Calls to {@link #loadMenu()} and set the menu to the {@link ServletContext}
     */
    protected void initApplicationContext() throws ApplicationContextException {
        if (!(getApplicationContext() instanceof WebApplicationContext)) {
            return;
        }
        Menu menu;
        try {
            menu = loadMenu();
        } catch (Exception e) {
            throw new ApplicationContextException("Error loading gvNIX web menu", e);
        }
        getServletContext().setAttribute(MENU_SERVLET_CONTEXT_KEY, menu);
    }

    /**
     * Loads menu model from XML file {@link #MENU_CONFIG_FILE}. This method loads
     * menu using recursivity. Override this
     * method to change menu's source. Remember to set to <code>null</code>
     * {@link #MENU_CONFIG_FILE}.
     *
     * @return
     * @throws Exception
     */
    protected Menu loadMenu() throws Exception {

        // load and parse menu.xml
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document xml = null;

        InputStream input = getServletContext().getResourceAsStream(MENU_CONFIG_FILE);
        Assert.notNull(input, "gvNIX menu configuration not found '".concat(MENU_CONFIG_FILE).concat("'"));
        try {
            xml = db.parse(input);
        } catch (Exception e) {
            throw e;
        } finally {
            input.close();
        }

        // create menu root
        Element root = xml.getDocumentElement();
        String menuId = root.getAttribute("id");
        Menu menu = new Menu(menuId);

        // parse children
        NodeList childNodes = root.getChildNodes();

        // return empty menu if there are no children
        if (childNodes.getLength() == 0) {
            return menu;
        }

        // load root menu items and their children
        List<MenuItem> childItems = loadMenuItems(childNodes);
        menu.setChildren(childItems);

        return menu;
    }

    /**
     * Transform a list of {@code <menu-item>} elements into {@code MenuItem}
     * objects.
     * <p>
     * This method loads the children recursively.
     *
     * @param nodes List of XML elements
     * @return List of MenuItem, note that MenuItem is complete, that is
     * each MenuItem will contain their children List
     */
    public List<MenuItem> loadMenuItems(NodeList nodes) {
        List<MenuItem> items = new ArrayList<MenuItem>();

        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() != Node.ELEMENT_NODE || !MENU_ITEM_ELEMENT.equals(node.getNodeName())) {
                continue;
            }

            // create the MenuItem object
            MenuItem item = new MenuItem((Element) node);

            // recursively load children
            NodeList childNodes = node.getChildNodes();

            if (childNodes.getLength() > 0) {
                List<MenuItem> childItems = loadMenuItems(childNodes);
                item.setChildren(childItems);
            }

            // add MenuItem to result list
            items.add(item);
        }
        return items;
    }
}