Package org.apache.lenya.cms.cocoon.generation

Source Code of org.apache.lenya.cms.cocoon.generation.SitetreeFragmentGenerator

/*
* Copyright  1999-2004 The Apache Software Foundation
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

/* @version $Id$*/

package org.apache.lenya.cms.cocoon.generation;

import java.io.IOException;
import java.util.Map;

import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.generation.AbstractGenerator;
import org.apache.lenya.cms.publication.Label;
import org.apache.lenya.cms.publication.PageEnvelope;
import org.apache.lenya.cms.publication.PageEnvelopeFactory;
import org.apache.lenya.cms.publication.Publication;
import org.apache.lenya.cms.publication.SiteTree;
import org.apache.lenya.cms.publication.SiteTreeException;
import org.apache.lenya.cms.publication.SiteTreeNode;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
* Generates a fragment of the XML from the sitetree, corresponding to a given
* node. The node is specified by the sitemap parameters area/documentid. If the
* sitemap parameter initialTree is true, the top nodes of the tree will be
* generated and the node given by the sitemap parameters area/documentid will
* be unfolded. If initialTree is false, only the children of the selected node
* will be generated.
*/
public class SitetreeFragmentGenerator extends AbstractGenerator {

    protected Publication publication;

    /** Parameter which denotes the documentid of the clicked node */
    protected String documentid;

    /** Parameter which denotes the area of the clicked node */
    protected String area;

    /**
     * Parameter which decides if the initial tree with the root nodes is
     * generated
     */
    protected boolean initialTree;

    /**
     * Parameter which denotes a comma-separated list of areas, for which the
     * xml will be generated.
     */
    protected String[] areas = null;

    /**
     * Convenience object, so we don't need to create an AttributesImpl for
     * every element.
     */
    protected AttributesImpl attributes;

    protected static final String PARAM_AREA = "area";

    protected static final String PARAM_DOCUMENTID = "documentid";

    protected static final String PARAM_INITIAL = "initial";

    protected static final String PARAM_AREAS = "areas";

    /** The URI of the namespace of this generator. */
    protected static final String URI = "http://apache.org/cocoon/lenya/sitetree/1.0";

    protected static final String XML_URI = "http://www.w3.org/XML/1998/namespace";

    /** The namespace prefix for this namespace. */
    protected static final String PREFIX = "site";

    protected static final String XML_PREFIX = "xml";

    protected static final String NODE_NODE = "node";

    protected static final String NODE_LABEL = "label";

    protected static final String NODE_SITE = "site";

    protected static final String NODE_FRAGMENT = "fragment";

    protected static final String ATTR_ID = "id";

    protected static final String ATTR_FOLDER = "folder";

    protected static final String ATTR_AREA = "area";

    protected static final String ATTR_LABEL = "label";

    protected static final String ATTR_VISIBLEINNAV = "visibleinnav";

    protected static final String ATTR_LINK = "link";

    protected static final String ATTR_BASE = "base";

    protected static final String ATTR_SUFFIX = "suffix";

    protected static final String ATTR_HREF = "href";

    protected static final String ATTR_LANG = "lang";

    /**
     * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver,
     *      java.util.Map, java.lang.String,
     *      org.apache.avalon.framework.parameters.Parameters)
     */
    public void setup(SourceResolver resolver, Map objectModel, String src,
            Parameters par) throws ProcessingException, SAXException,
            IOException {
        super.setup(resolver, objectModel, src, par);

        PageEnvelope envelope = null;

        if (getLogger().isDebugEnabled()) {
            Request request = ObjectModelHelper.getRequest(objectModel);
            getLogger().debug(
                    "Resolving page envelope for URL ["
                            + request.getRequestURI() + "]");
        }

        this.area = par.getParameter(PARAM_AREA, null);
        this.documentid = par.getParameter(PARAM_DOCUMENTID, null);

        if (par.isParameter(PARAM_INITIAL)) {
            this.initialTree = Boolean.valueOf(
                    par.getParameter(PARAM_INITIAL, null)).booleanValue();
        } else {
            this.initialTree = false;
        }

        if (par.isParameter(PARAM_AREAS)) {
            String parAreas = par.getParameter(PARAM_AREAS, null);
            this.areas = parAreas.split(",");
        } else {
            String temp[] = { "authoring", "archive", "trash" };
            this.areas = temp;
        }

        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("Parameter area: " + this.area);
            this.getLogger().debug("Parameter documentid: " + this.documentid);
            this.getLogger()
                    .debug("Parameter initialTree: " + this.initialTree);
            String areasStr = "";
            for (int i = 0; i < this.areas.length; i++)
                areasStr += this.areas[i] + " ";
            this.getLogger().debug("Parameter areas: " + areasStr);
        }

        try {
            envelope = PageEnvelopeFactory.getInstance().getPageEnvelope(
                    objectModel);
        } catch (Exception e) {
            throw new ProcessingException("Resolving page envelope failed: ", e);
        }

        this.publication = envelope.getPublication();
        this.attributes = new AttributesImpl();

    }

    /**
     * @see org.apache.cocoon.generation.Generator#generate()
     */
    public void generate() throws IOException, SAXException,
            ProcessingException {

        try {

            this.contentHandler.startDocument();
            this.contentHandler.startPrefixMapping(PREFIX, URI);

            attributes.clear();
            if (!initialTree) {
                attributes.addAttribute("", ATTR_AREA, ATTR_AREA, "CDATA",
                        this.area);
                attributes.addAttribute("", ATTR_BASE, ATTR_BASE, "CDATA",
                        this.documentid);
            }

            this.contentHandler.startElement(URI, NODE_FRAGMENT, PREFIX + ':'
                    + NODE_FRAGMENT, this.attributes);

            if (this.initialTree) {
                for (int i = 0; i < this.areas.length; i++) {
                    generateFragmentInitial(this.areas[i]);
                }
            } else {
                generateFragment();
            }

            this.contentHandler.endElement(URI, NODE_FRAGMENT, PREFIX + ':'
                    + NODE_FRAGMENT);

            this.contentHandler.endPrefixMapping(PREFIX);
            this.contentHandler.endDocument();

        } catch (SAXException e) {
            throw new ProcessingException(e);
        } catch (SiteTreeException e) {
            throw new ProcessingException(e);
        }

    }

    /**
     * Generates a fragment of the tree which contains the children of a given
     * node.
     *
     * @throws SiteTreeException
     * @throws SAXException
     * @throws ProcessingException
     */
    protected void generateFragment() throws SiteTreeException, SAXException,
            ProcessingException {

        SiteTree siteTree = null;
        if (!this.area.equals(Publication.AUTHORING_AREA)
                && !this.area.equals(Publication.ARCHIVE_AREA)
                && !this.area.equals(Publication.TRASH_AREA)
                && !this.area.equals(Publication.STAGING_AREA)
                && !this.area.equals(Publication.LIVE_AREA)) {
            throw new ProcessingException("Invalid area: " + this.area);
        }
        siteTree = publication.getTree(this.area);

        SiteTreeNode node = siteTree.getNode(this.documentid);
        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug(
                    "Node with documentid " + documentid + " found.");
        }
        if (node == null)
            throw new SiteTreeException("Node with documentid " + documentid
                    + " not found.");

        SiteTreeNode[] children = node.getChildren();

        for (int i = 0; i < children.length; i++) {
            startNode(NODE_NODE, children[i]);
            addLabels(children[i]);
            endNode(NODE_NODE);
        }
    }

    /**
     * Generates the top node of the given area and then calls a recursive
     * method to traverse the tree, if the node given by area/documentid is in
     * this area.
     *
     * @param siteArea
     * @throws SiteTreeException
     * @throws SAXException
     * @throws ProcessingException
     */
    protected void generateFragmentInitial(String siteArea)
            throws SiteTreeException, SAXException, ProcessingException {

        SiteTree siteTree = publication.getTree(siteArea);

        String label = "";
        String isFolder = "";

        // FIXME: don't hardcode area label
        if (siteArea.equals(Publication.AUTHORING_AREA))
            label = "Authoring";
        if (siteArea.equals(Publication.ARCHIVE_AREA))
            label = "Archive";
        if (siteArea.equals(Publication.TRASH_AREA))
            label = "Trash";
        if (siteArea.equals(Publication.LIVE_AREA))
            label = "Live";
        if (siteArea.equals(Publication.STAGING_AREA))
            label = "Staging";

        if (siteTree.getTopNodes().length > 0)
            isFolder = "true";
        else
            isFolder = "false";

        this.attributes.clear();
        this.attributes.addAttribute("", ATTR_AREA, ATTR_AREA, "CDATA",
                siteArea);
        this.attributes.addAttribute("", ATTR_FOLDER, ATTR_FOLDER, "CDATA",
                isFolder);
        this.attributes
                .addAttribute("", ATTR_LABEL, ATTR_LABEL, "CDATA", label);

        startNode(NODE_SITE);

        if (area.equals(siteArea)) {
            generateFragmentRecursive(siteTree.getTopNodes(), this.documentid);
        }

        endNode(NODE_SITE);
    }

    /**
     * Follows the documentid to find the way in the sitetree to the specified
     * node and opens all folders on its way.
     *
     * @param nodes
     * @param docid
     * @throws SiteTreeException
     * @throws SAXException
     */
    protected void generateFragmentRecursive(SiteTreeNode[] nodes, String docid)
            throws SiteTreeException, SAXException {
        String nodeid;
        String childid;

        if (nodes == null)
            return;
        if (docid.startsWith("/"))
            docid = docid.substring(1);
        if (docid.indexOf("/") != -1) {
            nodeid = docid.substring(0, docid.indexOf("/"));
            childid = docid.substring(docid.indexOf("/") + 1);
        } else {
            nodeid = docid;
            childid = "";
        }

        for (int i = 0; i < nodes.length; i++) {
            startNode(NODE_NODE, nodes[i]);
            addLabels(nodes[i]);
            if (nodes[i].getId().equals(nodeid)) {
                generateFragmentRecursive(nodes[i].getChildren(), childid);
            }
            endNode(NODE_NODE);
        }
    }

    /**
     * Begins a named node and calls setNodeAttributes to set its attributes.
     *
     * @param nodeName
     *            the name of the new node
     * @throws SAXException
     *             if an error occurs while creating the node
     */
    protected void startNode(String nodeName) throws SAXException {
        this.contentHandler.startElement(URI, nodeName,
                PREFIX + ':' + nodeName, this.attributes);
    }

    /**
     * Begins a named node and calls setNodeAttributes to set its attributes.
     *
     * @param nodeName
     *            the name of the new node
     * @param node
     *            The attributes are taken from this node
     * @throws SAXException
     *             if an error occurs while creating the node
     */
    protected void startNode(String nodeName, SiteTreeNode node)
            throws SAXException {
        setNodeAttributes(node);
        this.contentHandler.startElement(URI, nodeName,
                PREFIX + ':' + nodeName, this.attributes);
    }

    /**
     * Sets the attributes for a given node. Sets attributes id, href, folder,
     * suffix, basic-url, language-suffix.
     *
     * @param node
     * @throws SAXException
     *             if an error occurs while setting the attributes
     */
    protected void setNodeAttributes(SiteTreeNode node) throws SAXException {
        this.attributes.clear();

        String id = node.getId();
        String isVisible = Boolean.toString(node.visibleInNav());
        String hasLink = Boolean.toString(node.hasLink());
        String href = node.getHref();
        String suffix = node.getSuffix();
        String isFolder = isFolder(node);

        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("adding attribute id: " + id);
            this.getLogger().debug(
                    "adding attribute visibleinnav: " + isVisible);
            this.getLogger().debug("adding attribute link: " + hasLink);
            if (href != null)
                this.getLogger().debug("adding attribute href: " + href);
            if (suffix != null)
                this.getLogger().debug("adding attribute suffix: " + suffix);
            this.getLogger().debug("adding attribute folder: " + isFolder);
        }
        this.attributes.addAttribute("", ATTR_ID, ATTR_ID, "CDATA", id);
        this.attributes.addAttribute("", ATTR_VISIBLEINNAV, ATTR_VISIBLEINNAV,
                "CDATA", isVisible);
        this.attributes
                .addAttribute("", ATTR_LINK, ATTR_LINK, "CDATA", hasLink);
        if (href != null)
            this.attributes.addAttribute("", ATTR_HREF, ATTR_HREF, "CDATA",
                    href);
        if (suffix != null)
            this.attributes.addAttribute("", ATTR_SUFFIX, ATTR_SUFFIX, "CDATA",
                    suffix);
        this.attributes.addAttribute("", ATTR_FOLDER, ATTR_FOLDER, "CDATA",
                isFolder);
    }

    /**
     * Returns a value to indicate whether a node is a folder (contains
     * subnodes). With the incremental sitetree loading, we sometimes load nodes
     * which are folders, but we don't load their children. But we still have to
     * know if it's a folder or not, i.e. if it can be opened.
     *
     * @param node
     * @return "true" or "false"
     */
    protected String isFolder(SiteTreeNode node) {
        if (node.getChildren().length > 0)
            return "true";
        else
            return "false";
    }

    /**
     * Ends the named node.
     *
     * @param nodeName
     *            the name of the new node
     * @throws SAXException
     *             if an error occurs while closing the node
     */
    protected void endNode(String nodeName) throws SAXException {
        this.contentHandler.endElement(URI, nodeName, PREFIX + ':' + nodeName);
    }

    /**
     * Finds all the label children of a node and adds them to the nav xml.
     *
     * @param node
     * @throws SAXException
     */
    protected void addLabels(SiteTreeNode node) throws SAXException {
        Label[] labels = node.getLabels();

        for (int i = 0; i < labels.length; i++) {
            String lang = labels[i].getLanguage();
            if (lang == null)
                lang = "";
            addLabel(labels[i].getLabel(), lang);
        }
    }

    /**
     * Adds a label element of a given language.
     *
     * @param label
     *            the value of the label
     * @param language
     *            the language of the label
     * @throws SAXException
     */
    protected void addLabel(String label, String language) throws SAXException {
        this.attributes.clear();
        this.attributes.addAttribute(XML_URI, ATTR_LANG, XML_PREFIX + ":"
                + ATTR_LANG, "CDATA", language);

        this.contentHandler.startElement(URI, NODE_LABEL, PREFIX + ':'
                + NODE_LABEL, this.attributes);
        char[] labelArray = label.toCharArray();
        this.contentHandler.characters(labelArray, 0, labelArray.length);
        this.contentHandler.endElement(URI, NODE_LABEL, PREFIX + ':'
                + NODE_LABEL);
    }

}
TOP

Related Classes of org.apache.lenya.cms.cocoon.generation.SitetreeFragmentGenerator

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.