org.omnifaces.validator.RequiredCheckboxValidator Maven / Gradle / Ivy
/*
* 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.validator;
import static java.lang.String.format;
import static org.omnifaces.util.Components.getLabel;
import static org.omnifaces.util.FacesLocal.getMessageBundle;
import static org.omnifaces.util.Messages.createError;
import java.util.ResourceBundle;
import jakarta.faces.component.UIComponent;
import jakarta.faces.component.UIInput;
import jakarta.faces.component.UISelectBoolean;
import jakarta.faces.context.FacesContext;
import jakarta.faces.validator.FacesValidator;
import jakarta.faces.validator.Validator;
import jakarta.faces.validator.ValidatorException;
/**
*
* The omnifaces.RequiredCheckboxValidator
is intented to solve a peculiar problem with
* required="true"
attribute of {@link UISelectBoolean} components like
* <h:selectBooleanCheckbox>
. If you want to require the user to tick the desired checkbox, you would
* expect that setting required="true"
is sufficient. But it is not, the validation wil always pass.
*
* As for every other {@link UIInput} component the default required="true"
validator would
* only check if the value is actually filled and been sent to the server side, i.e. the value is not null nor empty.
* In case of a <h:selectBooleanCheckbox>
, which accepts Boolean
or boolean
* properties only, EL will coerce the unchecked value to Boolean.FALSE
during apply request values phase
* right before validations phase. This value is not null
nor empty! Thus, the required attribute of the
* <h:selectBooleanCheckbox>
is fairly pointless. It would always pass the validation and thus never
* display the desired required message in case of an unticked checkbox.
*
*
Usage
*
* This validator is available by validator ID omnifaces.RequiredCheckboxValidator
. Just specify it as
* <f:validator>
of the boolean selection component:
*
* <h:selectBooleanCheckbox id="agree" value="#{bean.agree}" requiredMessage="You must agree!">
* <f:validator validatorId="omnifaces.RequiredCheckboxValidator" />
* </h:selectBooleanCheckbox>
*
*
* The validator will use the message as specified in requiredMessage
. If it's absent, then it will use
* the default required message as specified in custom <message-bundle>
in
* faces-config.xml
. If it's absent, then it will default to
*
{0}: a tick is required"
*
* @author Bauke Scholtz
*/
@FacesValidator("omnifaces.RequiredCheckboxValidator")
public class RequiredCheckboxValidator implements Validator {
// Constants ------------------------------------------------------------------------------------------------------
private static final String DEFAULT_REQUIRED_MESSAGE = "{0}: a tick is required";
private static final String ERROR_WRONG_COMPONENT = "RequiredCheckboxValidator must be registered on a component"
+ " of type UISelectBoolean. Encountered component of type '%s'.";
// Actions --------------------------------------------------------------------------------------------------------
@Override
public void validate(FacesContext context, UIComponent component, Boolean value) {
if (!(component instanceof UISelectBoolean)) {
throw new IllegalArgumentException(format(ERROR_WRONG_COMPONENT, component.getClass().getName()));
}
if (!Boolean.TRUE.equals(value)) {
String requiredMessage = ((UIInput) component).getRequiredMessage();
if (requiredMessage == null) {
ResourceBundle messageBundle = getMessageBundle(context);
if (messageBundle != null) {
requiredMessage = messageBundle.getString(UIInput.REQUIRED_MESSAGE_ID);
}
}
if (requiredMessage == null) {
requiredMessage = DEFAULT_REQUIRED_MESSAGE;
}
throw new ValidatorException(createError(requiredMessage, getLabel(component)));
}
}
}