Package org.apache.cocoon.woody.formmodel

Source Code of org.apache.cocoon.woody.formmodel.MultiValueField

/*
* 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.
*/
package org.apache.cocoon.woody.formmodel;

import org.apache.cocoon.woody.datatype.SelectionList;
import org.apache.cocoon.woody.validation.ValidationError;
import org.apache.cocoon.woody.validation.ValidationErrorAware;
import org.apache.cocoon.woody.event.WidgetEvent;
import org.apache.cocoon.woody.event.ValueChangedEvent;
import org.apache.cocoon.woody.Constants;
import org.apache.cocoon.woody.FormContext;
import org.apache.cocoon.woody.util.I18nMessage;
import org.apache.cocoon.xml.AttributesImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

import java.util.Locale;

/**
* A MultiValueField is mostly the same as a normal {@link Field}, but can
* hold multiple values. A MultiValueField should have a Datatype which
* has a SelectionList, because the user will always select the values
* from a list. A MultiValueField has no concept of "required", you should
* instead use the ValueCountValidationRule to check how many items the user
* has selected.
*
* <p>A MultiValueField also has a {@link org.apache.cocoon.woody.datatype.Datatype Datatype}
* associated with it. In case of MultiValueFields, this Datatype will always be an array
* type, thus {@link org.apache.cocoon.woody.datatype.Datatype#isArrayType()} will
* always return true, and this in return has an influence on the kind of validation rules that
* can be used with the Datatype (see {@link org.apache.cocoon.woody.datatype.Datatype Datatype}
* description for more information).
*
* @version $Id: MultiValueField.java,v 1.20 2004/03/09 13:53:55 reinhard Exp $
*/
public class MultiValueField extends AbstractWidget implements ValidationErrorAware, SelectableWidget {
    private SelectionList selectionList;
    private MultiValueFieldDefinition fieldDefinition;
    private String[] enteredValues;
    private Object[] values;
    private ValidationError validationError;

    public MultiValueField(MultiValueFieldDefinition definition) {
        super.setDefinition(definition);
        this.fieldDefinition = definition;
        setLocation(definition.getLocation());
    }

    public String getId() {
        return definition.getId();
    }

    public void readFromRequest(FormContext formContext) {
        enteredValues = formContext.getRequest().getParameterValues(getFullyQualifiedId());
        validationError = null;
        values = null;

        boolean conversionFailed = false;
        if (enteredValues != null) {
            // Normally, for MultiValueFields, the user selects the values from
            // a SelectionList, and the values in a SelectionList are garanteed to
            // be valid, so the conversion from String to native datatype should
            // never fail. But it could fail if users start messing around with
            // request parameters.
            Object[] tempValues = new Object[enteredValues.length];
            for (int i = 0; i < enteredValues.length; i++) {
                String param = enteredValues[i];
                tempValues[i] = fieldDefinition.getDatatype().convertFromString(param, formContext.getLocale());
                if (tempValues[i] == null) {
                    conversionFailed = true;
                    break;
                }
            }

            if (!conversionFailed)
                values = tempValues;
            else
                values = null;
        } else {
            values = new Object[0];
        }
    }

    public boolean validate(FormContext formContext) {
        if (values != null)
            validationError = fieldDefinition.getDatatype().validate(values, new ExpressionContextImpl(this));
        else
            validationError = new ValidationError(new I18nMessage("multivaluefield.conversionfailed", Constants.I18N_CATALOGUE));


        return validationError == null ? super.validate(formContext) : false;
    }

    private static final String MULTIVALUEFIELD_EL = "multivaluefield";
    private static final String VALUES_EL = "values";
    private static final String VALUE_EL = "value";
    private static final String VALIDATION_MSG_EL = "validation-message";

    public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
        AttributesImpl attrs = new AttributesImpl();
        attrs.addCDATAAttribute("id", getFullyQualifiedId());
        contentHandler.startElement(Constants.WI_NS, MULTIVALUEFIELD_EL, Constants.WI_PREFIX_COLON + MULTIVALUEFIELD_EL, attrs);

        contentHandler.startElement(Constants.WI_NS, VALUES_EL, Constants.WI_PREFIX_COLON + VALUES_EL, Constants.EMPTY_ATTRS);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                contentHandler.startElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL, Constants.EMPTY_ATTRS);
                String value = fieldDefinition.getDatatype().getPlainConvertor().convertToString(values[i], locale, null);
                contentHandler.characters(value.toCharArray(), 0, value.length());
                contentHandler.endElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL);
            }
        } else if (enteredValues != null) {
            for (int i = 0; i < enteredValues.length; i++) {
                contentHandler.startElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL, Constants.EMPTY_ATTRS);
                String value = fieldDefinition.getDatatype().getPlainConvertor().convertToString(enteredValues[i], locale, null);
                contentHandler.characters(value.toCharArray(), 0, value.length());
                contentHandler.endElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL);
            }
        }
        contentHandler.endElement(Constants.WI_NS, VALUES_EL, Constants.WI_PREFIX_COLON + VALUES_EL);

        // generate label, help, hint, etc.
        definition.generateDisplayData(contentHandler);

        // the selection list (a MultiValueField has per definition always a SelectionList)
        if (this.selectionList != null) {
            this.selectionList.generateSaxFragment(contentHandler, locale);
        } else {
            fieldDefinition.getSelectionList().generateSaxFragment(contentHandler, locale);
        }

        // validation message element
        if (validationError != null) {
            contentHandler.startElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL, Constants.EMPTY_ATTRS);
            validationError.generateSaxFragment(contentHandler);
            contentHandler.endElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL);
        }

        contentHandler.endElement(Constants.WI_NS, MULTIVALUEFIELD_EL, Constants.WI_PREFIX_COLON + MULTIVALUEFIELD_EL);
    }

    public void generateLabel(ContentHandler contentHandler) throws SAXException {
        definition.generateLabel(contentHandler);
    }

    public Object getValue() {
        return values;
    }

    public void setValue(Object value) {
        if (value == null) {
            setValues(new Object[0]);
        } else if (value.getClass().isArray()) {
            setValues((Object[])value);
        } else {
            throw new RuntimeException("Cannot set value of field \"" + getFullyQualifiedId() + "\" with an object of type " + value.getClass().getName());
        }
    }

    public void setValues(Object[] values) {
        // check that all the objects in the array correspond to the datatype
        for (int i = 0; i < values.length; i++) {
            if (!fieldDefinition.getDatatype().getTypeClass().isAssignableFrom(values[i].getClass()))
                throw new RuntimeException("Cannot set value of field \"" + getFullyQualifiedId() + "\" with an object of type " + values[i].getClass().getName());
        }
        this.values = values;
    }

    /**
     * Set this field's selection list.
     * @param selectionList The new selection list.
     */
    public void setSelectionList(SelectionList selectionList) {
        if (selectionList != null &&
            selectionList.getDatatype() != null &&
            selectionList.getDatatype() != fieldDefinition.getDatatype()) {

            throw new RuntimeException("Tried to assign a SelectionList that is not associated with this widget's datatype.");
        }
        this.selectionList = selectionList;
    }

    /**
     * Read this field's selection list from an external source.
     * All Cocoon-supported protocols can be used.
     * The format of the XML produced by the source should be the
     * same as in case of inline specification of the selection list,
     * thus the root element should be a <code>wd:selection-list</code>
     * element.
     * @param uri The URI of the source.
     */
    public void setSelectionList(String uri) {
        setSelectionList(this.fieldDefinition.buildSelectionList(uri));
    }

    /**
     * Set this field's selection list using values from an in-memory
     * object. The <code>object</code> parameter should point to a collection
     * (Java collection or array, or Javascript array) of objects. Each object
     * belonging to the collection should have a <em>value</em> property and a
     * <em>label</em> property, whose values are used to specify the <code>value</code>
     * attribute and the contents of the <code>wd:label</code> child element
     * of every <code>wd:item</code> in the list.
     * <p>Access to the values of the above mentioned properties is done
     * via <a href="http://jakarta.apache.org/commons/jxpath/users-guide.html">XPath</a> expressions.
     * @param model The collection used as a model for the selection list.
     * @param valuePath An XPath expression referring to the attribute used
     * to populate the values of the list's items.
     * @param labelPath An XPath expression referring to the attribute used
     * to populate the labels of the list's items.
     */
    public void setSelectionList(Object model, String valuePath, String labelPath) {
        setSelectionList(this.fieldDefinition.buildSelectionListFromModel(model, valuePath, labelPath));
    }

    public void broadcastEvent(WidgetEvent event) {
        this.fieldDefinition.fireValueChangedEvent((ValueChangedEvent)event);
    }

    public ValidationError getValidationError() {
        return this.validationError;
    }

    public void setValidationError(ValidationError error) {
        this.validationError = error;
    }
}
TOP

Related Classes of org.apache.cocoon.woody.formmodel.MultiValueField

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.