org.apache.cocoon.forms.formmodel.BooleanField.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cocoon.forms.formmodel.BooleanField.java

Source

/*
 * Copyright 1999-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.forms.formmodel;

import java.util.Locale;

import org.apache.cocoon.forms.FormsConstants;
import org.apache.cocoon.forms.FormContext;
import org.apache.cocoon.forms.event.*;
import org.apache.cocoon.xml.AttributesImpl;
import org.apache.cocoon.xml.XMLUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.cocoon.forms.validation.ValidationErrorAware;
import org.apache.cocoon.forms.validation.ValidationError;
import org.apache.commons.lang.BooleanUtils;

/**
 * A widget to select a boolean value. Usually rendered as a checkbox.
 *
 * <p>You may wonder why we don't use a {@link Field} widget with an associated
 * Boolean Datatype instead. The reason is that many of the features of the Field
 * widget are overkill for a Boolean: validation is unnecessary (if the field is
 * not true it is false), the selectionlist associated with a Datatype also
 * has no purpose here (there would always be only 2 choices: true or false),
 * and the manner in which the request parameter of this widget is interpreted
 * is different (missing or empty request parameter means 'false', rather than null value).
 *
 * @version $Id: BooleanField.java 328140 2005-10-24 19:22:55Z sylvain $
 */
public class BooleanField extends AbstractWidget implements ValidationErrorAware, ValueChangedListenerEnabled {

    private static final String BOOLEAN_FIELD_EL = "booleanfield";
    private static final String VALUE_EL = "value";
    private static final String VALIDATION_MSG_EL = "validation-message";

    // FIXME(SW) : should the initial value be false or null ? This would allow
    // event listeners to be triggered at bind time.
    private Boolean value = Boolean.FALSE;
    private final BooleanFieldDefinition definition;
    /** Additional listeners to those defined as part of the widget definition (if any). */
    private ValueChangedListener listener;
    protected ValidationError validationError;

    public BooleanField(BooleanFieldDefinition definition) {
        super(definition);
        this.definition = definition;
        this.listener = definition.getValueChangedListener();
    }

    public WidgetDefinition getDefinition() {
        return this.definition;
    }

    public void initialize() {
        Boolean value = this.definition.getInitialValue();
        if (value != null) {
            setValue(value);
        }
        super.initialize();
    }

    public void readFromRequest(FormContext formContext) {
        if (!getCombinedState().isAcceptingInputs()) {
            return;
        }

        validationError = null;
        Object oldValue = value;
        String param = formContext.getRequest().getParameter(getRequestParameterName());

        value = BooleanUtils.toBooleanObject(definition.getTrueParamValue().equals(param));

        if (!value.equals(oldValue)) {
            getForm().addWidgetEvent(new ValueChangedEvent(this, oldValue, value));
        }
    }

    /**
     * Returns the validation error, if any. There will always be a validation error in case the
     * {@link #validate()} method returned false.
     */
    public ValidationError getValidationError() {
        return validationError;
    }

    /**
     * Set a validation error on this field. This allows fields to be externally marked as invalid by
     * application logic.
     *
     * @param error the validation error
     */
    public void setValidationError(ValidationError error) {
        this.validationError = error;
        getForm().addWidgetUpdate(this);
    }

    /**
     * @return "booleanfield"
     */
    public String getXMLElementName() {
        return BOOLEAN_FIELD_EL;
    }

    protected AttributesImpl getXMLElementAttributes() {
        AttributesImpl attrs = super.getXMLElementAttributes();
        // Add the parameter value for true
        attrs.addCDATAAttribute("true-value", definition.getTrueParamValue());
        return attrs;
    }

    public void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
        // value element
        contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUE_EL,
                FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL, XMLUtils.EMPTY_ATTRIBUTES);

        String stringValue = BooleanUtils.toBoolean(value) ? definition.getTrueParamValue() : "false";

        contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length());
        contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL,
                FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
        // validation message element: only present if the value is not valid
        if (validationError != null) {
            contentHandler.startElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL,
                    FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL, XMLUtils.EMPTY_ATTRIBUTES);
            validationError.generateSaxFragment(contentHandler);
            contentHandler.endElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL,
                    FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL);
        }
    }

    public Object getValue() {
        return value;
    }

    /**
     * Sets value of the field. If value is null, it is considered to be false
     * (see class comment).
     */
    public void setValue(Object object) {
        if (object == null) {
            object = Boolean.FALSE;
        }

        if (!(object instanceof Boolean)) {
            throw new RuntimeException("Cannot set value of boolean field \"" + getRequestParameterName()
                    + "\" to a non-Boolean value.");
        }

        Object oldValue = value;
        value = (Boolean) object;
        if (!value.equals(oldValue)) {
            Form form = getForm();
            if (hasValueChangedListeners() || this.getForm().hasFormHandler()) {
                form.addWidgetEvent(new ValueChangedEvent(this, oldValue, value));
            }
            form.addWidgetUpdate(this);
        }
    }

    /**
     * Adds a ValueChangedListener to this widget instance. Listeners defined
     * on the widget instance will be executed in addtion to any listeners
     * that might have been defined in the widget definition.
     */
    public void addValueChangedListener(ValueChangedListener listener) {
        this.listener = WidgetEventMulticaster.add(this.listener, listener);
    }

    public void removeValueChangedListener(ValueChangedListener listener) {
        this.listener = WidgetEventMulticaster.remove(this.listener, listener);
    }

    public boolean hasValueChangedListeners() {
        return this.listener != null;
    }

    public void broadcastEvent(WidgetEvent event) {
        if (event instanceof ValueChangedEvent) {
            if (this.listener != null) {
                this.listener.valueChanged((ValueChangedEvent) event);
            }
        } else {
            // Other kinds of events
            super.broadcastEvent(event);
        }
    }
}