org.apache.cocoon.portal.transformation.CopletTransformer.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cocoon.portal.transformation.CopletTransformer.java

Source

/*
 * Copyright 1999-2002,2004-2005 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.
 */
package org.apache.cocoon.portal.transformation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.wrapper.RequestParameters;
import org.apache.cocoon.portal.LinkService;
import org.apache.cocoon.portal.coplet.CopletInstanceData;
import org.apache.cocoon.portal.event.impl.ChangeCopletInstanceAspectDataEvent;
import org.apache.cocoon.portal.event.impl.CopletJXPathEvent;
import org.apache.cocoon.portal.event.impl.JXPathEvent;
import org.apache.cocoon.xml.AttributesImpl;
import org.apache.cocoon.xml.XMLUtils;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.excalibur.xml.sax.XMLizable;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * This transformer offers various functions for developing pipeline based coplets.
 *
 * Includes coplet instance data by using JXPath expressions.
 * The transformer searches for tags <coplet:coplet xmlns:coplet="http://apache.org/cocoon/portal/coplet/1.0">.
 * They must have an attribute "select" that contains a valid JXPath expression applying to the coplet instance data.<br><br>
 *
 * Example:<br><br>
 *
 * <pre>&lt;maxpageable xmlns:coplet="http://apache.org/cocoon/portal/coplet/1.0"&gt;
 *    &lt;coplet:coplet select="copletData.maxpageable"/&gt;
 * &lt;/maxpageable&gt;<br></pre>
 *
 * The transformer will insert the boolean value specifying whether the coplet is
 * maxpageable or not.<br>
 * Please see also the documentation of superclass AbstractCopletTransformer for how
 * the coplet instance data are acquired.
 *
 * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
 * @author <a href="mailto:bluetkemeier@s-und-n.de">Bj&ouml;rn L&uuml;tkemeier</a>
 * @version CVS $Id: CopletTransformer.java 344185 2005-11-14 19:40:03Z cziegeler $
 */
public class CopletTransformer extends AbstractCopletTransformer {

    /**
     * The namespace URI to listen for.
     */
    public static final String NAMESPACE_URI = "http://apache.org/cocoon/portal/coplet/1.0";

    /**
     * The XML element name to listen for.
     */
    public static final String COPLET_ELEM = "coplet";

    /**
     * The attribute containing the JXPath expression.
     */
    public static final String SELECT_ATTR = "select";

    /**
     * The XML element name to listen for.
     */
    public static final String LINK_ELEM = "link";

    /** Create a link containing several events */
    public static final String LINKS_ELEM = "links";

    /** Create a link containing several events */
    public static final String PARAMETER_ELEM = "parameter";

    /** The content for the links element */
    public static final String CONTENT_ELEM = "content";

    /** Are we inside a links element? */
    protected boolean insideLinks;

    /** The collected list of events */
    protected List collectedEvents = new ArrayList();

    /** The content of the links */
    protected XMLizable content;

    /**
     * Creates new CopletTransformer.
     */
    public CopletTransformer() {
        this.defaultNamespaceURI = NAMESPACE_URI;
    }

    /* (non-Javadoc)
     * @see org.apache.cocoon.transformation.AbstractSAXTransformer#setupTransforming()
     */
    public void setupTransforming() throws IOException, ProcessingException, SAXException {
        super.setupTransforming();
        this.insideLinks = false;
        this.content = null;
        this.collectedEvents.clear();
    }

    /**
     * Overridden from superclass.
     */
    public void startTransformingElement(String uri, String name, String raw, Attributes attr)
            throws ProcessingException, IOException, SAXException {
        if (name.equals(COPLET_ELEM)) {
            String expression = attr.getValue(SELECT_ATTR);
            if (expression == null) {
                throw new ProcessingException("Attribute " + SELECT_ATTR + " must be spcified.");
            }

            final CopletInstanceData cid = this.getCopletInstanceData();

            final JXPathContext jxpathContext = JXPathContext.newContext(cid);
            final Object object = jxpathContext.getValue(expression);

            if (object != null) {
                XMLUtils.valueOf(contentHandler, object);
            }

        } else if (name.equals(LINK_ELEM)) {

            final LinkService linkService = this.portalService.getComponentManager().getLinkService();
            final String format = attr.getValue("format");
            AttributesImpl newAttrs = new AttributesImpl();
            newAttrs.setAttributes(attr);
            newAttrs.removeAttribute("format");

            if (attr.getValue("href") != null) {
                final CopletInstanceData cid = this.getCopletInstanceData();
                ChangeCopletInstanceAspectDataEvent event = new ChangeCopletInstanceAspectDataEvent(cid, null,
                        null);

                String value = linkService.getLinkURI(event);
                if (value.indexOf('?') == -1) {
                    value = value + '?' + attr.getValue("href");
                } else {
                    value = value + '&' + attr.getValue("href");
                }
                newAttrs.removeAttribute("href");
                this.output(value, format, newAttrs);
            } else {
                final String path = attr.getValue("path");
                final String value = attr.getValue("value");

                newAttrs.removeAttribute("path");
                newAttrs.removeAttribute("value");

                JXPathEvent event = null;
                if (attr.getValue("layout") != null) {
                    newAttrs.removeAttribute("layout");
                    final String layoutId = attr.getValue("layout");
                    Object layout = this.portalService.getComponentManager().getProfileManager()
                            .getPortalLayout(null, layoutId);
                    if (layout != null) {
                        event = new JXPathEvent(layout, path, value);
                    }
                } else {
                    String copletId = attr.getValue("coplet");
                    newAttrs.removeAttribute("coplet");
                    final CopletInstanceData cid = this.getCopletInstanceData(copletId);
                    if (cid != null) {
                        event = new CopletJXPathEvent(cid, path, value);
                    }
                }
                if (this.insideLinks) {
                    if (event != null) {
                        this.collectedEvents.add(event);
                    }
                } else {
                    final String href = linkService.getLinkURI(event);
                    this.output(href, format, newAttrs);
                }
            }
        } else if (name.equals(PARAMETER_ELEM)) {
            if (this.insideLinks) {
                String href = attr.getValue("href");
                if (href != null) {
                    final int pos = href.indexOf('?');
                    if (pos != -1) {
                        href = href.substring(pos + 1);
                    }
                    this.collectedEvents.add(new LinkService.ParameterDescription(href));
                }
            }
        } else if (name.equals(LINKS_ELEM)) {
            this.insideLinks = true;
            final AttributesImpl newAttrs = new AttributesImpl();
            newAttrs.setAttributes(attr);
            newAttrs.removeAttribute("format");
            this.stack.push(newAttrs);

            String format = attr.getValue("format");
            if (format == null) {
                format = "html-link";
            }
            this.stack.push(format);
        } else if (name.equals(CONTENT_ELEM) && this.insideLinks) {
            this.startSAXRecording();
        } else {
            super.startTransformingElement(uri, name, raw, attr);
        }
    }

    /**
     * Overridden from superclass.
     */
    public void endTransformingElement(String uri, String name, String raw)
            throws ProcessingException, IOException, SAXException {
        if (name.equals(LINK_ELEM)) {
            if (!this.insideLinks) {
                String elem = (String) this.stack.pop();
                if (elem.length() > 0) {
                    this.sendEndElementEvent(elem);
                }
            }
        } else if (name.equals(LINKS_ELEM)) {
            this.insideLinks = false;
            final String format = (String) this.stack.pop();
            final LinkService linkService = this.portalService.getComponentManager().getLinkService();
            String href = linkService.getLinkURI(this.collectedEvents);

            AttributesImpl newAttrs = (AttributesImpl) this.stack.pop();
            // test for alternate base url
            final String baseURL = newAttrs.getValue("base-url");
            if (baseURL != null) {
                newAttrs.removeAttribute("base-url");
                int pos = href.indexOf('?') + 1;
                final char separator;
                if (baseURL.indexOf('?') == -1) {
                    separator = '?';
                } else {
                    separator = '&';
                }
                href = baseURL + separator + href.substring(pos);

            }
            this.output(href, format, newAttrs);

            this.collectedEvents.clear();
            if (this.content != null) {
                this.content.toSAX(this.contentHandler);
                this.content = null;
            }
            String elem = (String) this.stack.pop();
            if (elem.length() > 0) {
                this.sendEndElementEvent(elem);
            }
        } else if (name.equals(CONTENT_ELEM) && this.insideLinks) {
            this.content = this.endSAXRecording();
        } else if (!name.equals(COPLET_ELEM) && !name.equals(PARAMETER_ELEM)) {
            super.endTransformingElement(uri, name, raw);
        }
    }

    /**
     * Output the link
     */
    protected void output(String uri, String format, AttributesImpl newAttrs) throws SAXException {
        if (format == null) {
            // default
            format = "html-link";
        }

        if ("html-link".equals(format)) {
            newAttrs.addCDATAAttribute("href", uri);
            this.sendStartElementEvent("a", newAttrs);
            this.stack.push("a");

        } else if ("html-form".equals(format)) {
            boolean addParametersAsHiddenFields = false;
            String parameters = null;
            final String enctype = newAttrs.getValue("enctype");
            if (enctype == null || "application/x-www-form-urlencoded".equalsIgnoreCase(enctype)
                    || "multipart/form-data".equalsIgnoreCase(enctype)) {
                final int pos = uri.indexOf('?');
                if (pos != -1) {
                    parameters = uri.substring(pos + 1);
                    uri = uri.substring(0, pos);
                    addParametersAsHiddenFields = true;
                }
            }
            newAttrs.addCDATAAttribute("action", uri);
            this.sendStartElementEvent("form", newAttrs);
            this.stack.push("form");
            if (addParametersAsHiddenFields) {
                // create hidden input fields
                RequestParameters pars = new RequestParameters(parameters);
                Enumeration enumeration = pars.getParameterNames();
                while (enumeration.hasMoreElements()) {
                    final String pName = (String) enumeration.nextElement();
                    final String[] pValues = pars.getParameterValues(pName);
                    for (int k = 0; k < pValues.length; k++) {
                        final String pValue = pValues[k];
                        AttributesImpl hiddenAttrs = new AttributesImpl();
                        hiddenAttrs.addCDATAAttribute("type", "hidden");
                        hiddenAttrs.addCDATAAttribute("name", pName);
                        hiddenAttrs.addCDATAAttribute("value", pValue);
                        this.startElement("", "input", "input", hiddenAttrs);
                        this.endElement("", "input", "input");
                    }
                }

            }
        } else if ("text".equals(format)) {
            this.sendTextEvent(uri);
            this.stack.push("");
        } else if ("parameters".equals(format)) {
            final String value = uri.substring(uri.indexOf('?') + 1);
            this.sendTextEvent(value);
            this.stack.push("");
        } else {
            // own format
            newAttrs.addCDATAAttribute("href", uri);
            this.sendStartElementEvent("link", newAttrs);
            this.stack.push("link");
        }
    }
}