Package org.apache.cocoon.acting

Source Code of org.apache.cocoon.acting.AbstractXMLFormAction

/*

============================================================================
                   The Apache Software License, Version 1.1
============================================================================

Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:

1. Redistributions of  source code must  retain the above copyright  notice,
    this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any, must
    include  the following  acknowledgment:  "This product includes  software
    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
    Alternately, this  acknowledgment may  appear in the software itself,  if
    and wherever such third-party acknowledgments normally appear.

4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
    used to  endorse or promote  products derived from  this software without
    prior written permission. For written permission, please contact
    apache@apache.org.

5. Products  derived from this software may not  be called "Apache", nor may
    "Apache" appear  in their name,  without prior written permission  of the
    Apache Software Foundation.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
(INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software  consists of voluntary contributions made  by many individuals
on  behalf of the Apache Software  Foundation and was  originally created by
Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
Software Foundation, please see <http://www.apache.org/>.

*/
package org.apache.cocoon.acting;

import org.apache.avalon.excalibur.pool.Poolable;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.source.SourceUtil;
import org.apache.cocoon.components.validation.Schema;
import org.apache.cocoon.components.validation.SchemaFactory;
import org.apache.cocoon.components.validation.Validator;
import org.apache.cocoon.components.xmlform.Form;
import org.apache.cocoon.components.xmlform.FormListener;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.excalibur.source.Source;
import org.xml.sax.InputSource;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
* This is the base action class for
* xmlform handling.
*
* This action is Poolable which means that
* subclasses of this class should not be
* concerned about thread safety.
* The framework ensures that only one thread
* has access to a concrete instance at any time.
*
* However once an action is complete, the instance
* will be recycled and reused for another request.
*
*
* Several ideas are borrowed from the original work of
* Torsten Curdt.
*
* @author Ivelin Ivanov <ivelin@apache.org>
* @version CVS $Id: AbstractXMLFormAction.java,v 1.5 2003/10/15 20:47:15 cziegeler Exp $
*/
public abstract class AbstractXMLFormAction
  extends ConfigurableServiceableAction
  implements Poolable, Recyclable, FormListener {

    public static final String OBJECT_MAP_NEXT_PAGE = "page";

    protected static final Map PREPARE_RESULT_CONTINUE = null;

    // action state objects
    private Redirector redirector_;
    private SourceResolver resolver_;
    private Map objectModel_;
    private Parameters params_;
    private String src_;
    private String command_;

    /**
     * The first method which is called
     * when an action is invoked.
     *
     * It is called before population.
     *
     * @return null if the Action is prepared to continue.
     * an objectModel map which will be immediately returned by the action.
     *
     * This method is a good place to handle buttons with Cancel
     * kind of semantics. For example
     * <pre>return page("input")</pre>
     */
    protected Map prepare() {
        // by default, assume that there is
        // no preparation needed
        return PREPARE_RESULT_CONTINUE;
    }

    /**
     * FormListener callback
     * called in the beginning of Form.populate()
     * before population starts.
     *
     * This is the place to intialize the model for this request.
     *
     * This method should not handle unchecked check boxes
     * when the form is session scope, which is the most common case.
     * It should only do so, if the form is request scoped.
     *
     * @param form      
     */
    public void reset(Form form) {
        // Do Nothing by default
        return;
    }

    /**
     * FormListener callback.
     *
     * Invoked during Form.populate();
     *
     * It is invoked before a request parameter is mapped to
     * an attribute of the form model.
     *
     * It is appropriate to use this method for filtering
     * custom request parameters which do not reference
     * the model.
     *
     * Another appropriate use of this method is for graceful filtering of invalid
     * values, in case that knowledge of the system state or
     * other circumstainces make the standard validation
     * insufficient. For example if a registering user choses a username which
     * is already taken - the check requires database transaction, which is
     * beyond the scope of document validating schemas.
     * Of course customized Validators can be implemented to do
     * this kind of domain specific validation
     * instead of using this method.
     *
     * @param form      
     * @param parameterName
     * @return false if the request parameter should not be filtered.
     * true otherwise.
     */
    public boolean filterRequestParameter(Form form, String parameterName) {
        // in this example we do not expect "custom" parameters
        return false;
    }

    /**
     * Invoked during the form population process
     *
     * Provides default implementation, which
     * can be extended or replaced by subclasses
     *
     * Implementations of this method are responsible
     * for creating and
     * returning the Form object which the action
     * is working on.
     *
     * @return Form the form object this action works with
     */
    protected Form getForm() {
        Form form = Form.lookup(getObjectModel(), getFormId());

        if (form!=null) {
            return form;
        } else {
            // create new form
            form = new Form(getFormId(), getFormModel());
            Validator v = getFormValidator();

            form.setValidator(v);
            form.save(getObjectModel(), getFormScope());
            return form;
        }
    }

    public Map act(Redirector redirector, SourceResolver resolver,
                   Map objectModel, String src,
                   Parameters params) throws Exception {
        // populate action state objects
        redirector_ = redirector;
        resolver_ = resolver;
        objectModel_ = objectModel;
        src_ = src;
        params_ = params;

        // ensure that there is a form available
        // through the rest of the flow
        Form form = getForm();

        if (form==null) {
            throw new IllegalStateException("Action could not obtain the Form");
        }

        // find and save the action command
        findCommand();

        // call the subclass prepare()
        // give it a chance to get ready for action
        Map prepareResult = prepare();

        if (prepareResult!=null) {
            return prepareResult;
        }

        // attache callback hooks to the form
        // in case the action subclasses are interested in
        // form events
        getForm().addFormListener(this);
        Map result = null;

        try {
            // populate form with request parameters
            // population is automatically followed by validation by default.
            // If this is not the desired behaviour, the Form class can be subclassed
            form.populate(objectModel);

            result = perform();
        } finally {
            // since the action may be recycled immediately after
            // the request. It is important that it's callback hooks
            // are removed from the Form.
            getForm().removeFormListener(this);
        }

        return result;
    }

    /**
     * Get the command which was submitted with the form.
     * It is extracted from the standard cocoon-action-* request parameter
     *
     */
    public String getCommand() {
        return command_;
    }

    protected void findCommand() {
        command_ = null;
        Enumeration enum = getRequest().getParameterNames();

        while (enum.hasMoreElements()) {
            String paramName = (String) enum.nextElement();

            // search for the command
            if (paramName.startsWith(Constants.ACTION_PARAM_PREFIX)) {
                command_ = paramName.substring(Constants.ACTION_PARAM_PREFIX.length(),
                                               paramName.length());
            }
        }
    }

    /**
     * @return the @view attribute of the xmlform form tag.
     * This attribute is used to identify the part(or view)
     * of the model which is used in the specific xmlform
     * document.
     *
     */
    public String getFormView() {
        return getForm().getFormView(getObjectModel());
    }

    /**
     * Called to determine the exit point of an action.
     * The pageName is made available in the objectMap,
     * which can be then referenced in the pipeline

     * @param pageName logical name for a next page
     * @return Map a pipeline objectMap containing the pageName
     */
    protected Map page(String pageName) {
        Map objectModel = new HashMap();

        objectModel.put(OBJECT_MAP_NEXT_PAGE, pageName);
        return objectModel;
    }

    /**
     * Invoked after form population
     * unless a Cancel button was pressed,
     * in which case population is skipped and this method
     * is invoked immediately.
     *
     * Semanticly similar to Struts Action.perform()
     *
     * Take appropriate action based on the command.
     */
    public abstract Map perform();

    protected SourceResolver getSourceResolver() {
        return resolver_;
    }

    protected Redirector getRedirector() {
        return redirector_;
    }

    protected Map getObjectModel() {
        return objectModel_;
    }

    protected Parameters getParameters() {
        return params_;
    }

    protected String getSrc() {
        return src_;
    }

    protected Request getRequest() {
        return (Request) (getObjectModel().get(ObjectModelHelper.REQUEST_OBJECT));
    }

    protected Session getSession(boolean shouldCreateNew) {
        return getRequest().getSession(shouldCreateNew);
    }

    protected Session getSession() {
        return getSession(true);
    }

    /**
     * Extract action parameters and
     * instantiate a new validator based on them.
     *
     * xmlform-validator-schema-ns
     * xmlform-validator-schema
     *
     * Subclasses may override this method
     * to use custom validators
     *
     */
    protected Validator getFormValidator() {
        try {
            // initialize the Validor with a schema file
            String schNS = getParameters().getParameter("xmlform-validator-schema-ns",
                                                        null);
            String schDoc = getParameters().getParameter("xmlform-validator-schema",
                                null);

            // if validator params are not specified, then
            // there is no validation by default
            if ((schNS==null) || (schDoc==null)) {
                return null;
            }

            Source schemaSrc = getSourceResolver().resolveURI(schDoc);

            try {
                InputSource is = SourceUtil.getInputSource(schemaSrc);
                SchemaFactory schf = SchemaFactory.lookup(schNS);
                Schema sch = schf.compileSchema(is);

                return sch.newValidator();
            } finally {
                getSourceResolver().release(schemaSrc);
            }
        } catch (Exception e) {
            // couldn't load the validator
            throw new CascadingRuntimeException(" Failed loading validating schema ",
                                                e);
        }
    }

    /**
     * Extract xmlform-model action parameter and
     * instantiate a new form model it.
     *
     * Subclasses may override this method
     * to use custom model instantiation technique
     *
     */
    protected Object getFormModel() {
        try {
            String modelClassName = getParameters().getParameter("xmlform-model",
                                        null);
            Class modelClass = Class.forName(modelClassName);
            Object o = modelClass.newInstance();

            return o;
        } catch (Exception e) {
            throw new CascadingRuntimeException(" Failed instantiating form model ",
                                                e);
        }
    }

    protected String getFormId() {
        String formId = getParameters().getParameter("xmlform-id", null);

        if (formId==null) {
            throw new RuntimeException(" xmlform-id not specified ");
        } else {
            return formId;
        }
    }

    protected String getFormScope() {
        String formScope = getParameters().getParameter("xmlform-scope",
                               null);

        if (formScope==null) {
            // default to request scope
            formScope = Form.SCOPE_REQUEST;
        }

        return formScope;
    }

    /**
     * Recycle this component.
     */
    public void recycle() {
        redirector_ = null;
        resolver_ = null;
        objectModel_ = null;
        params_ = null;
        src_ = null;
        command_ = null;
    }
}
TOP

Related Classes of org.apache.cocoon.acting.AbstractXMLFormAction

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.