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

org.omnifaces.component.validator.ValidateOrder Maven / Gradle / Ivy

There is a newer version: 4.5.1
Show newest version
/*
 * Copyright OmniFaces
 *
 * 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
 *
 *     https://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.omnifaces.component.validator;

import static java.lang.String.format;
import static java.util.Arrays.asList;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;

import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

import org.omnifaces.util.Callback;
import org.omnifaces.util.State;
import org.omnifaces.validator.MultiFieldValidator;

/**
 * 

* The <o:validateOrder> validates if the values of the given {@link UIInput} components as specified * in the components attribute are in the order as specified by the type attribute which * accepts the following values: *

    *
  • lt (default): from least to greatest, without duplicates.
  • *
  • lte: from least to greatest, allowing duplicates (equal values next to each other).
  • *
  • gt: from greatest to least, without duplicates.
  • *
  • gte: from greatest to least, allowing duplicates (equal values next to each other).
  • *
*

* This validator has the additional requirement that the to-be-validated values must implement {@link Comparable}. * This validator throws an {@link IllegalArgumentException} when one or more of the values do not implement it. Note * that when this validator is placed before all of the components, then it will only compare the raw * unconverted submitted string values, not the converted object values. If you need to compare by the converted object * values, then you need to place this validator after all of the components. *

* The default message is *

{0}: Please fill out the values of all those fields in order
*

* For general usage instructions, refer {@link ValidateMultipleFields} documentation. * * @author Bauke Scholtz * @see ValidateMultipleFields * @see ValidatorFamily * @see MultiFieldValidator */ @FacesComponent(ValidateOrder.COMPONENT_TYPE) @SuppressWarnings({ "unchecked", "rawtypes" }) // We don't care about the actual Comparable type. public class ValidateOrder extends ValidateMultipleFields { // Public constants ----------------------------------------------------------------------------------------------- /** The standard component type. */ public static final String COMPONENT_TYPE = "org.omnifaces.component.validator.ValidateOrder"; // Private constants ---------------------------------------------------------------------------------------------- private enum Type { LT(values -> new ArrayList<>(new TreeSet<>(values)).equals(values)), LTE(values -> { List sortedValues = new ArrayList<>(values); Collections.sort(sortedValues); return sortedValues.equals(values); }), GT(values -> { List sortedValues = new ArrayList<>(new TreeSet<>(values)); Collections.reverse(sortedValues); return sortedValues.equals(values); }), GTE(values -> { List sortedValues = new ArrayList<>(values); Collections.sort(sortedValues, Collections.reverseOrder()); return sortedValues.equals(values); }); private Callback.ReturningWithArgument> callback; private Type(Callback.ReturningWithArgument> callback) { this.callback = callback; } public boolean validateOrder(List values) { return callback.invoke(values); } } private static final String DEFAULT_TYPE = Type.LT.name(); private static final String ERROR_INVALID_TYPE = "Invalid type '%s'. Only 'lt', 'lte', 'gt' and 'gte' are allowed."; private static final String ERROR_VALUES_NOT_COMPARABLE = "All values must implement java.lang.Comparable."; private enum PropertyKeys { // Cannot be uppercased. They have to exactly match the attribute names. type; } // Variables ------------------------------------------------------------------------------------------------------ private final State state = new State(getStateHelper()); // Actions -------------------------------------------------------------------------------------------------------- /** * Validate if all values are in specified order. */ @Override public boolean validateValues(FacesContext context, List components, List values) { try { Object tmp = values; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=158870 List comparableValues = new ArrayList<>((List) tmp); comparableValues.removeAll(asList(null, "")); // Empty checking job is up to required="true". return Type.valueOf(getType().toUpperCase()).validateOrder(comparableValues); } catch (ClassCastException e) { throw new IllegalArgumentException(ERROR_VALUES_NOT_COMPARABLE, e); } } // Getters/setters ------------------------------------------------------------------------------------------------ /** * Returns the ordering type to be used. * @return The ordering type to be used. */ public String getType() { return state.get(PropertyKeys.type, DEFAULT_TYPE); } /** * Sets the ordering type to be used. * @param type The ordering type to be used. */ public void setType(String type) { try { Type.valueOf(type.toUpperCase()); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(format(ERROR_INVALID_TYPE, type), e); } state.put(PropertyKeys.type, type); } }