All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.primefaces.extensions.component.sheet.SheetColumn Maven / Gradle / Ivy

There is a newer version: 14.0.7.1
Show newest version
/*
 * Copyright (c) 2011-2023 PrimeFaces Extensions
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */
package org.primefaces.extensions.component.sheet;

import java.util.Collection;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

/**
 * JSF Component used to represent a column in the Sheet component.
 *
 * @author Mark Lassiter / Melloware
 * @since 6.2
 */
public class SheetColumn extends UIInput implements ClientBehaviorHolder {

    public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.SheetColumn";
    public static final String COMPONENT_FAMILY = "org.primefaces.extensions.component";
    private static final String MESSAGE_REQUIRED = "A valid value for this column is required.";

    /**
     * Properties that are tracked by state saving.
     */
    @SuppressWarnings("java:S115")
    enum PropertyKeys {

        /**
         * The width of the column
         */
        colWidth,

        /**
         * The type of the column (text, numeric, etc)
         */
        colType,

        /**
         * The header text to display for the column
         */
        headerText,

        /**
         * Defines whether column should trim the whitespace at the beginning and the end of the cell contents. Default Value: true
         */
        trimWhitespace,

        /**
         * Password mask asterisk * by default
         */
        passwordHashSymbol,

        /**
         * Password fixed length
         */
        passwordHashLength,

        /**
         * Numbers can be formatted to look like currency, percentages, times, or even plain old numbers with decimal places, thousands, and abbreviations.
         */
        numericPattern,

        /**
         * Numbers such as currency can be configured for a Locale. Default to en_us.
         */
        numericLocale,

        /**
         * Moment.js date format for colType="date". Default is "DD/MM/YYYY"
         */
        dateFormat,

        /**
         * JSON config for coltype="date". DatePicker additional options (see https://github.com/dbushell/Pikaday#configuration)
         */
        datePickerConfig,

        /**
         * Moment.js time format for colType="date". Default is "h:mm:ss a"
         */
        timeFormat,

        /**
         * If true, the autocomplete cells will only accept values that are defined in the source array. Default true.
         */
        autoCompleteStrict,

        /**
         * If true, allows manual input of value that does not exist in the source. In this case, the field background highlight becomes red and the selection
         * advances to the next cell.
         */
        autoCompleteAllowInvalid,

        /**
         * Number of rows visible in the autocomplete dropdown.
         */
        autoCompleteVisibleRows,

        /**
         * If true, trims the dropdown to fit the cell size. Default to true.
         */
        autoCompleteTrimDropdown,

        /**
         * List of values to display in colType="dropdown" or "autocomplete".
         */
        selectItems,

        /**
         * Flag indicating whether or not the column is read only
         */
        readOnly,

        /**
         * Flag indicating whether or not a cell is read only
         */
        readonlyCell,

        /**
         * the style class for the cell
         */
        styleClass,

        /**
         * Filter by value expression
         */
        filterBy,

        /**
         * Filter options
         */
        filterOptions,

        /**
         * The filter match mode: startsWith, endsWith, contains, exact
         */
        filterMatchMode,

        /**
         * The submitted filtered value
         */
        filterValue,
        /**
         * Controls the visibilty of the column, default is true.
         */
        visible,
        /**
         * When set to true, the text of the cell content is wrapped if it does not fit in the fixed column width.
         */
        wordWrap,
        /**
         * A Javascript function, regular expression or a string, which will be used in the process of cell validation. If a function is used, be sure to
         * execute the callback argument with either true (callback(true)) if the validation passed or with false (callback(false)), if the validation failed.
         * Note, that this in the function points to the cellProperties object.
         */
        onvalidate
    }

    private Object localValue;

    /**
     * Sheet reference. Updated on decode.
     */
    private Sheet sheet;

    /**
     * Default constructor
     */
    public SheetColumn() {
        setRendererType(null);
    }

    /*
     * (non-Javadoc)
     * @see javax.faces.component.UIComponent#getFamily()
     */
    @Override
    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    /**
     * Updates the fixed columns count.
     *
     * @param value
     */
    public void setHeaderText(final String value) {
        getStateHelper().put(PropertyKeys.headerText, value);
    }

    /**
     * The fixed column count.
     *
     * @return
     */
    public String getHeaderText() {
        final Object result = getStateHelper().eval(PropertyKeys.headerText, null);
        if (result == null) {
            return null;
        }
        return result.toString();
    }

    /**
     * Updates the readOnly property
     *
     * @param value
     */
    public void setReadOnly(final boolean value) {
        getStateHelper().put(PropertyKeys.readOnly, value);
    }

    /**
     * Flag indicating whether this column is read only.
     *
     * @return true if read only, otherwise false
     */
    public boolean isReadOnly() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.readOnly, Boolean.FALSE).toString());
    }

    /**
     * Updates the readOnly property of the cell
     *
     * @param value
     */
    public void setReadonlyCell(final boolean value) {
        getStateHelper().put(PropertyKeys.readonlyCell, value);
    }

    /**
     * Flag indicating whether this cell is read only. the var reference will be available.
     *
     * @return true if read only, otherwise false
     */
    public boolean isReadonlyCell() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.readonlyCell, Boolean.FALSE).toString());
    }

    /**
     * Updates the column width
     *
     * @param value
     */
    public void setColWidth(final Integer value) {
        getStateHelper().put(PropertyKeys.colWidth, value);
    }

    /**
     * The column width
     *
     * @return
     */
    public Integer getColWidth() {
        final Object result = getStateHelper().eval(PropertyKeys.colWidth, null);
        if (result == null) {
            return null;
        }
        return Integer.valueOf(result.toString());
    }

    /**
     * Updates the column type. Possible values are: text, numeric, date, checkbox, autocomplete, handsontable.
     *
     * @param value
     */
    public void setColType(final String value) {
        getStateHelper().put(PropertyKeys.colType, value);
    }

    /**
     * the Handsontable column type.
     */
    public String getColType() {
        return getStateHelper().eval(PropertyKeys.colType, "text").toString();
    }

    public boolean isAutoCompleteAllowInvalid() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.autoCompleteAllowInvalid, Boolean.FALSE).toString());
    }

    public void setAutoCompleteAllowInvalid(final boolean value) {
        getStateHelper().put(PropertyKeys.autoCompleteAllowInvalid, value);
    }

    public boolean isAutoCompleteStrict() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.autoCompleteStrict, Boolean.TRUE).toString());
    }

    public void setAutoCompleteStrict(final boolean value) {
        getStateHelper().put(PropertyKeys.autoCompleteStrict, value);
    }

    public boolean isAutoCompleteTrimDropdown() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.autoCompleteTrimDropdown, Boolean.TRUE).toString());
    }

    public void setAutoCompleteTrimDropdown(final boolean value) {
        getStateHelper().put(PropertyKeys.autoCompleteTrimDropdown, value);
    }

    public void setAutoCompleteVisibleRows(final Integer value) {
        getStateHelper().put(PropertyKeys.autoCompleteVisibleRows, value);
    }

    public Integer getAutoCompleteVisibleRows() {
        return (Integer) getStateHelper().eval(PropertyKeys.autoCompleteVisibleRows, null);
    }

    public Object getSelectItems() {
        return getStateHelper().eval(PropertyKeys.selectItems, null);
    }

    public void setSelectItems(final Object selectItems) {
        getStateHelper().put(PropertyKeys.selectItems, selectItems);
    }

    public Integer getPasswordHashLength() {
        return (Integer) getStateHelper().eval(PropertyKeys.passwordHashLength, null);
    }

    public void setPasswordHashLength(final Integer _passwordHashLength) {
        getStateHelper().put(PropertyKeys.passwordHashLength, _passwordHashLength);
    }

    public void setPasswordHashSymbol(final String _passwordHashSymbol) {
        getStateHelper().put(PropertyKeys.passwordHashSymbol, _passwordHashSymbol);
    }

    public String getPasswordHashSymbol() {
        return (String) getStateHelper().eval(PropertyKeys.passwordHashSymbol, "*");
    }

    public void setNumericPattern(final String _numericPattern) {
        getStateHelper().put(PropertyKeys.numericPattern, _numericPattern);
    }

    public String getNumericPattern() {
        return (String) getStateHelper().eval(PropertyKeys.numericPattern, "0 a");
    }

    public String getNumericLocale() {
        return (String) getStateHelper().eval(PropertyKeys.numericLocale, "en-US");
    }

    public void setNumericLocale(final String locale) {
        getStateHelper().put(PropertyKeys.numericLocale, locale);
    }

    public void setDateFormat(final String _dateFormat) {
        getStateHelper().put(PropertyKeys.dateFormat, _dateFormat);
    }

    public String getDateFormat() {
        return (String) getStateHelper().eval(PropertyKeys.dateFormat, "DD/MM/YYYY");
    }

    public void setDatePickerConfig(final String _datePickerConfig) {
        getStateHelper().put(PropertyKeys.datePickerConfig, _datePickerConfig);
    }

    public String getDatePickerConfig() {
        return (String) getStateHelper().eval(PropertyKeys.datePickerConfig, null);
    }

    public void setTimeFormat(final String _timeFormat) {
        getStateHelper().put(PropertyKeys.timeFormat, _timeFormat);
    }

    public String getTimeFormat() {
        return (String) getStateHelper().eval(PropertyKeys.timeFormat, "h:mm:ss a");
    }

    public void setOnvalidate(final String _onvalidate) {
        getStateHelper().put(PropertyKeys.onvalidate, _onvalidate);
    }

    public String getOnvalidate() {
        return (String) getStateHelper().eval(PropertyKeys.onvalidate, null);
    }

    public void setVisible(final boolean value) {
        getStateHelper().put(PropertyKeys.visible, value);
    }

    public boolean isVisible() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.visible, Boolean.TRUE).toString());
    }

    public void setWordWrap(final boolean value) {
        getStateHelper().put(PropertyKeys.wordWrap, value);
    }

    public Boolean isWordWrap() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.wordWrap, Boolean.TRUE).toString());
    }

    public void setTrimWhitespace(final boolean value) {
        getStateHelper().put(PropertyKeys.trimWhitespace, value);
    }

    public Boolean isTrimWhitespace() {
        return Boolean.valueOf(getStateHelper().eval(PropertyKeys.trimWhitespace, Boolean.TRUE).toString());
    }

    /**
     * Update the style class for the cell.
     *
     * @param value
     */
    public void setStyleClass(final String value) {
        getStateHelper().put(PropertyKeys.styleClass, value);
    }

    /**
     * The style class for the cell.
     *
     * @return
     */
    public String getStyleClass() {
        final Object result = getStateHelper().eval(PropertyKeys.styleClass, null);
        if (result == null) {
            return null;
        }
        return result.toString();
    }

    /**
     * The filterBy expression
     *
     * @return
     */
    public Object getFilterBy() {
        return getStateHelper().eval(PropertyKeys.filterBy, null);
    }

    /**
     * Update the filter by field
     *
     * @param filterBy
     */
    public void setFilterBy(final Object filterBy) {
        getStateHelper().put(PropertyKeys.filterBy, filterBy);
    }

    /**
     * The filter value submitted by the user
     *
     * @return
     */
    public String getFilterValue() {
        return (String) getStateHelper().eval(PropertyKeys.filterValue);
    }

    /**
     * Update the filter value for this column
     *
     * @param filterValue
     */
    public void setFilterValue(final String filterValue) {
        getStateHelper().put(PropertyKeys.filterValue, filterValue);
    }

    /**
     * The filter match mode submitted by the user
     *
     * @return
     */
    public String getFilterMatchMode() {
        return (String) getStateHelper().eval(PropertyKeys.filterMatchMode);
    }

    /**
     * Update the filter match mode for this column
     *
     * @param filterMatchMode
     */
    public void setFilterMatchMode(final String filterMatchMode) {
        getStateHelper().put(PropertyKeys.filterMatchMode, filterMatchMode);
    }

    /**
     * The filterOptions expression
     *
     * @return
     */
    public Collection getFilterOptions() {
        return (Collection) getStateHelper().eval(PropertyKeys.filterOptions, null);
    }

    /**
     * Update the filterOptions field
     */
    public void setFilterOptions(final Collection filterOptions) {
        getStateHelper().put(PropertyKeys.filterOptions, filterOptions);
    }

    /**
     * Get the parent sheet
     *
     * @return
     */
    public Sheet getSheet() {
        if (sheet != null) {
            return sheet;
        }

        UIComponent parent = getParent();
        while (parent != null && !(parent instanceof Sheet)) {
            parent = parent.getParent();
        }
        return (Sheet) parent;
    }

    /**
     * Updates the sheet reference to work around getParent sometimes returning null.
     *
     * @param sheet the owning sheet
     */
    public void setSheet(final Sheet sheet) {
        this.sheet = sheet;
    }

    /**
     * --------------------------------------------------
     * 

* Override UIInput methods */ /** * Ignore attempts to set the local value for this column, again done by parent. */ @Override public void setValue(final Object value) { localValue = value; setLocalValueSet(true); } /** * When asked for the value, return the local value if available, otherwise the sheet value. */ @Override public Object getValue() { return localValue; } /** * We are valid if the sheet is valid, we do not track at the individual column. */ @Override public boolean isValid() { return getSheet().isValid(); } /** * when we become valid, invalidate the whole sheet. */ @Override public void setValid(final boolean valid) { getSheet().setValid(valid); } /** * Sheet handles decoding of all submitted values */ @Override public void processDecodes(final FacesContext context) { // do nothing, done for us by sheet } /** * Sheet handles updating of model */ @Override public void processUpdates(final FacesContext context) { // do nothing, done for us by sheet } /** * Reset the local value. No submitted value tracked here. Validity not tracked here. */ @Override public void resetValue() { setValue(null); setLocalValueSet(false); } /** * Don't do anything when called by inherited behavior. Sheet will call validate directly */ @Override public void processValidators(final FacesContext context) { // do nothing, sheet will call validate directly } /** * Process all validators (skip normal UIInput behavior) */ @Override public void validate(final FacesContext context) { if (context == null) { throw new NullPointerException(); } final Validator[] validators = getValidators(); final Object value = getValue(); if (!validateRequired(context, value)) { return; } if (validators == null) { return; } for (final Validator validator : validators) { try { validator.validate(context, this, value); } catch (final ValidatorException ve) { // If the validator throws an exception, we're // invalid, and we need to add a message setValid(false); final FacesMessage message; final String validatorMessageString = getValidatorMessage(); if (null != validatorMessageString) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, validatorMessageString, validatorMessageString); message.setSeverity(FacesMessage.SEVERITY_ERROR); } else { final Collection messages = ve.getFacesMessages(); if (null != messages) { message = null; final String cid = getClientId(context); for (final FacesMessage m : messages) { context.addMessage(cid, m); } } else { message = ve.getFacesMessage(); } } if (message != null) { final Sheet current = getSheet(); if (current == null) { return; } context.addMessage(getClientId(context), message); current.getInvalidUpdates().add( new SheetInvalidUpdate(current.getRowKeyValue(context), current.getColumns().indexOf(this), this, value, message.getDetail())); } } } } /** * Validates the value against the required flags on this column. * * @param context the FacesContext * @param newValue the new value for this column * @return true if passes validation, otherwise valse */ protected boolean validateRequired(final FacesContext context, final Object newValue) { // If our value is valid, enforce the required property if present if (isValid() && isRequired() && UIInput.isEmpty(newValue)) { final String requiredMessageStr = getRequiredMessage(); final FacesMessage message; if (null != requiredMessageStr) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, requiredMessageStr, requiredMessageStr); } else { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, MESSAGE_REQUIRED, MESSAGE_REQUIRED); } context.addMessage(getClientId(context), message); final Sheet current = getSheet(); if (current != null) { current.getInvalidUpdates().add( new SheetInvalidUpdate(current.getRowKeyValue(context), current.getColumns().indexOf(this), this, newValue, message.getDetail())); } setValid(false); return false; } return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy