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

com.sun.faces.component.validator.ComponentValidators Maven / Gradle / Ivy

Go to download

Jakarta Faces defines an MVC framework for building user interfaces for web applications, including UI components, state management, event handing, input validation, page navigation, and support for internationalization and accessibility.

There is a newer version: 4.1.2
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.faces.component.validator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sun.faces.facelets.tag.faces.ComponentSupport;
import com.sun.faces.util.RequestStateManager;

import jakarta.faces.application.Application;
import jakarta.faces.component.EditableValueHolder;
import jakarta.faces.context.FacesContext;
import jakarta.faces.validator.Validator;
import jakarta.faces.view.facelets.FaceletContext;
import jakarta.faces.view.facelets.ValidatorHandler;

/**
 * 

* This class is responsible for adding default validators and/or validators that wrap multiple * EditableValueHolder instances within the view. *

*/ public class ComponentValidators { /** * Key within the FacesContext's attribute map under which a single ComponentValidators * instance will be stored. */ private static final String COMPONENT_VALIDATORS = "jakarta.faces.component.ComponentValidators"; /** * Stack of ValidatorInfo instances. Each instance represents * a particular nesting level within the view. As a nesting level is encountered, * a ValidatorInfo will be pushed to the stack and all EditableValueHolder instances will be * configured based on all ValidatorInfos on the stack. When the current nesting level is closed, the * ValidatorInfo instance will be popped and thus have no impact on other * EditableValueHolders. */ private LinkedList validatorStack = null; // ------------------------------------------------------------ Constructors public ComponentValidators() { validatorStack = new LinkedList<>(); } // ---------------------------------------------------------- Public Methods /** * @param context the FacesContext for the current request * @param createIfNull flag indicating whether or not a ComponentValidators instance should be created or * not * @return a ComponentValidators instance for processing a view request. If createIfNull is * false and no ComponentValidators has been created, this method will return * null */ public static ComponentValidators getValidators(FacesContext context, boolean createIfNull) { Map attrs = context.getAttributes(); ComponentValidators componentValidators = (ComponentValidators) attrs.get(COMPONENT_VALIDATORS); if (componentValidators == null && createIfNull) { componentValidators = new ComponentValidators(); attrs.put(COMPONENT_VALIDATORS, componentValidators); } return componentValidators; } /** *

* Creates and installs default validators, if any, into the argument EditableValueHolder. This method is * merely a utility method to be called when there is no ComponentValidators available, or there are no * ValidatorInfo instances on the stack. *

* * @param ctx the FacesContext for the current request * @param editableValueHolder the component receiving the Validators */ @SuppressWarnings({ "unchecked" }) public static void addDefaultValidatorsToComponent(FacesContext ctx, EditableValueHolder editableValueHolder) { if (ComponentSupport.isBuildingNewComponentTree(ctx)) { Set keySet = ctx.getApplication().getDefaultValidatorInfo().keySet(); List validatorIds = new ArrayList<>(keySet.size()); Set disabledValidatorIds = (Set) RequestStateManager.remove(ctx, RequestStateManager.DISABLED_VALIDATORS); for (String key : keySet) { if (disabledValidatorIds != null && disabledValidatorIds.contains(key)) { continue; } validatorIds.add(key); } addValidatorsToComponent(ctx, validatorIds, editableValueHolder, null); } } /** *

* Based on the ValidatorInfo instances present on the stack, configure the argument * EditableValueHolder with Validators created from the available info. *

* * @param ctx the FacesContext for the current request * @param editableValueHolder the component receiving the Validators */ @SuppressWarnings({ "unchecked" }) public void addValidators(FacesContext ctx, EditableValueHolder editableValueHolder) { if (validatorStack == null || validatorStack.isEmpty()) { addDefaultValidatorsToComponent(ctx, editableValueHolder); return; } Application application = ctx.getApplication(); Map defaultValidatorInfo = application.getDefaultValidatorInfo(); Set keySet = defaultValidatorInfo.keySet(); List validatorIds = new ArrayList<>(keySet.size()); validatorIds.addAll(keySet); Set disabledIds = (Set) RequestStateManager.remove(ctx, RequestStateManager.DISABLED_VALIDATORS); int count = validatorStack.size(); for (int i = count - 1; i >= 0; i--) { ValidatorInfo info = validatorStack.get(i); if (!info.isEnabled() || disabledIds != null && disabledIds.contains(info.getValidatorId())) { validatorIds.remove(info.getValidatorId()); } else { if (!validatorIds.contains(info.getValidatorId())) { validatorIds.add(info.getValidatorId()); } } } // add the validators to the EditableValueHolder. addValidatorsToComponent(ctx, validatorIds, editableValueHolder, validatorStack == null || validatorStack.isEmpty() ? null : validatorStack); } /** *

* Pushes the provided ValidatorInfo onto the stack. *

* * @param info validator info */ public void pushValidatorInfo(ValidatorInfo info) { validatorStack.add(info); } /** *

* Pops the last ValidatorInfo instance from the stack. *

*/ public void popValidatorInfo() { if (validatorStack.size() > 0) { validatorStack.removeLast(); } } // --------------------------------------------------------- Private Methods /** *

* Install the validators, if not already present on the component, using the IDs included in validatorIds. *

* * @param ctx the FacesContext for the current request * @param validatorIds the validator IDs to be added to the EditableValueHolder * @param editableValueHolder the target component to which the validators installed * @param validatorStack current stack of ValidatorInfo instances */ private static void addValidatorsToComponent(FacesContext ctx, Collection validatorIds, EditableValueHolder editableValueHolder, LinkedList validatorStack) { if (validatorIds == null || validatorIds.isEmpty()) { return; } Application application = ctx.getApplication(); Map defaultValidatorInfo = application.getDefaultValidatorInfo(); Validator[] validators = editableValueHolder.getValidators(); // check to make sure that Validator instances haven't already // been added. for (Map.Entry defaultValidator : defaultValidatorInfo.entrySet()) { for (Validator validator : validators) { if (defaultValidator.getValue().equals(validator.getClass().getName())) { validatorIds.remove(defaultValidator.getKey()); break; } } } // we now have the complete List of Validator IDs to add to the // target EditablValueHolder for (String id : validatorIds) { Validator v = application.createValidator(id); // work backwards up the stack of ValidatorInfo to find the // nearest matching ValidatorInfo to apply attributes if (validatorStack != null) { for (int i = validatorStack.size() - 1; i >= 0; i--) { ValidatorInfo info = validatorStack.get(i); if (id.equals(info.getValidatorId())) { info.applyAttributes(v); break; } } } editableValueHolder.addValidator(v); } } // ---------------------------------------------------------- Nested Classes /** * Generic information container for a validator at a particular nesting Level. */ public static class ValidatorInfo { private final String validatorId; private final boolean enabled; private final ValidatorHandler owner; private final FaceletContext ctx; // ------------------------------------------------------------ Constructors public ValidatorInfo(FaceletContext ctx, ValidatorHandler owner) { this.owner = owner; this.ctx = ctx; validatorId = owner.getValidatorId(ctx); enabled = !owner.isDisabled(ctx); } // ------------------------------------------------------------------------- public String getValidatorId() { return validatorId; } public boolean isEnabled() { return enabled; } public void applyAttributes(Validator v) { owner.setAttributes(ctx, v); } } // END ValidatorInfo }