/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you 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.myfaces.extensions.validator.beanval.util; | |
import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationEntry; | |
import org.apache.myfaces.extensions.validator.beanval.ExtValBeanValidationContext; | |
import org.apache.myfaces.extensions.validator.core.el.ELHelper; | |
import org.apache.myfaces.extensions.validator.core.property.PropertyDetails; | |
import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder; | |
import org.apache.myfaces.extensions.validator.internal.UsageCategory; | |
import org.apache.myfaces.extensions.validator.internal.UsageInformation; | |
import org.apache.myfaces.extensions.validator.util.ExtValUtils; | |
import javax.faces.application.FacesMessage; | |
import javax.faces.component.UIComponent; | |
import javax.faces.context.FacesContext; | |
import javax.faces.validator.ValidatorException; | |
import javax.validation.ConstraintViolation; | |
import javax.validation.ValidatorFactory; | |
import javax.validation.Validation; | |
import javax.validation.metadata.ElementDescriptor; | |
import javax.validation.metadata.PropertyDescriptor; | |
import javax.validation.metadata.BeanDescriptor; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.Map; | |
import java.util.Collections; | |
import java.util.logging.Logger; | |
/** | |
* @since x.x.3 | |
*/ | |
@UsageInformation(UsageCategory.INTERNAL) | |
public class BeanValidationUtils | |
{ | |
private static final Logger LOGGER = Logger.getLogger(BeanValidationUtils.class.getName()); | |
private static ELHelper elHelper = ExtValUtils.getELHelper(); | |
private static ExtValBeanValidationMetaDataInternals bvmi = | |
new ExtValBeanValidationMetaDataInternals(LOGGER, elHelper); | |
private static final String VALIDATOR_FACTORY_KEY = "javax.faces.validator.beanValidator.ValidatorFactory"; | |
@SuppressWarnings({"unchecked"}) | |
public static Set<ConstraintViolation<Object>> validate(Class baseClass, | |
String propertyName, | |
Object objectToValidate, | |
Class[] groups, | |
boolean cascadedValidation) | |
{ | |
ValidatorFactory validatorFactory = ExtValBeanValidationContext.getCurrentInstance().getValidatorFactory(); | |
Set<ConstraintViolation<Object>> result = | |
validatorFactory.usingContext() | |
.messageInterpolator(ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator()) | |
.constraintValidatorFactory(validatorFactory.getConstraintValidatorFactory()) | |
.traversableResolver(validatorFactory.getTraversableResolver()) | |
.getValidator() | |
.validateValue(baseClass, propertyName, objectToValidate, groups); | |
if(result.isEmpty() && cascadedValidation && objectToValidate != null) | |
{ | |
result = processCascadedValidation(validatorFactory, baseClass, propertyName, objectToValidate, groups); | |
} | |
return result; | |
} | |
private static Set<ConstraintViolation<Object>> processCascadedValidation(ValidatorFactory validatorFactory, | |
Class baseBeanClass, | |
String propertyName, | |
Object objectToValidate, | |
Class[] groups) | |
{ | |
ElementDescriptor elementDescriptor = getElementDescriptor(baseBeanClass, propertyName); | |
if(elementDescriptor instanceof PropertyDescriptor && ((PropertyDescriptor)elementDescriptor).isCascaded()) | |
{ | |
return validatorFactory.usingContext() | |
.messageInterpolator(ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator()) | |
.constraintValidatorFactory(validatorFactory.getConstraintValidatorFactory()) | |
.traversableResolver(validatorFactory.getTraversableResolver()) | |
.getValidator() | |
.validate(objectToValidate, groups); | |
} | |
return Collections.emptySet(); | |
} | |
public static ElementDescriptor getElementDescriptor(Class targetClass, String property) | |
{ | |
BeanDescriptor beanDescriptor = ExtValBeanValidationContext.getCurrentInstance().getValidatorFactory() | |
.getValidator().getConstraintsForClass(targetClass); | |
return beanDescriptor.getConstraintsForProperty(property); | |
} | |
public static void addMetaDataToContext( | |
UIComponent component, PropertyDetails propertyDetails, boolean processMetaDataForValidation) | |
{ | |
String[] key = propertyDetails.getKey().split("\\."); | |
Object firstBean = elHelper.getBean(key[0]); | |
List<Class> foundGroupsForPropertyValidation = new ArrayList<Class>(); | |
List<Class> restrictedGroupsForPropertyValidation = new ArrayList<Class>(); | |
List<ModelValidationEntry> modelValidationEntryList = new ArrayList<ModelValidationEntry>(); | |
List<Class> restrictedGroupsForModelValidation = new ArrayList<Class>(); | |
String activeViewId = FacesContext.getCurrentInstance().getViewRoot().getViewId(); | |
bvmi.extractExtValBeanValidationMetaData(propertyDetails, | |
processMetaDataForValidation, | |
key, | |
firstBean, | |
foundGroupsForPropertyValidation, | |
restrictedGroupsForPropertyValidation, | |
modelValidationEntryList, | |
restrictedGroupsForModelValidation, | |
activeViewId); | |
bvmi.processExtValBeanValidationMetaData(component, | |
propertyDetails, | |
foundGroupsForPropertyValidation, | |
restrictedGroupsForPropertyValidation, | |
modelValidationEntryList, | |
restrictedGroupsForModelValidation, | |
activeViewId); | |
} | |
public static void processConstraintViolations(FacesContext facesContext, | |
UIComponent uiComponent, | |
Object convertedObject, | |
Set<ConstraintViolation<Object>> violations) | |
{ | |
List<FacesMessageHolder> facesMessageHolderList = new ArrayList<FacesMessageHolder>(); | |
FacesMessage facesMessage; | |
for (ConstraintViolation<Object> violation : violations) | |
{ | |
facesMessage = createFacesMessageForConstraintViolation(uiComponent, convertedObject, violation); | |
if (facesMessage == null) | |
{ | |
continue; | |
} | |
bvmi.processFacesMessage(facesContext, uiComponent, facesMessageHolderList, facesMessage); | |
} | |
processViolationMessages(facesMessageHolderList); | |
} | |
public static FacesMessage createFacesMessageForConstraintViolation(UIComponent uiComponent, | |
Object convertedObject, | |
ConstraintViolation<Object> violation) | |
{ | |
String violationMessage = violation.getMessage(); | |
String labeledMessageSummary = bvmi.createLabeledMessage(violationMessage, false); | |
String labeledMessageDetail = bvmi.createLabeledMessage(violationMessage, true); | |
FacesMessage.Severity severity = bvmi.calcSeverity(violation); | |
ValidatorException validatorException = bvmi | |
.createValidatorException(labeledMessageSummary, labeledMessageDetail, severity); | |
if (!bvmi.executeAfterThrowingInterceptors(uiComponent, convertedObject, validatorException)) | |
{ | |
return null; | |
} | |
if (bvmi.isMessageTextUnchanged(validatorException, labeledMessageSummary, labeledMessageDetail)) | |
{ | |
return ExtValUtils.createFacesMessage(severity, violationMessage, violationMessage); | |
} | |
else | |
{ | |
return ExtValUtils.createFacesMessage(severity, | |
validatorException.getFacesMessage().getSummary(), | |
validatorException.getFacesMessage().getDetail()); | |
} | |
} | |
public static void processViolationMessages(List<FacesMessageHolder> violationMessageHolderList) | |
{ | |
if (violationMessageHolderList == null || violationMessageHolderList.isEmpty()) | |
{ | |
return; | |
} | |
List<FacesMessageHolder> facesMessageListWithLowSeverity = | |
bvmi.getFacesMessageListWithLowSeverity(violationMessageHolderList); | |
List<FacesMessageHolder> facesMessageListWithHighSeverity = | |
bvmi.getFacesMessageListWithHighSeverity(violationMessageHolderList); | |
bvmi.addMessages(facesMessageListWithHighSeverity); | |
bvmi.addMessages(facesMessageListWithLowSeverity); | |
} | |
public static ValidatorFactory getDefaultValidatorFactory() | |
{ | |
Map<String, Object> applicationMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap(); | |
ValidatorFactory validatorFactory = null; | |
if (applicationMap.containsKey(VALIDATOR_FACTORY_KEY)) | |
{ | |
if (applicationMap.get(VALIDATOR_FACTORY_KEY) instanceof ValidatorFactory) | |
{ | |
validatorFactory = (ValidatorFactory) applicationMap.get(VALIDATOR_FACTORY_KEY); | |
} | |
} | |
if (validatorFactory == null) | |
{ | |
validatorFactory = Validation.buildDefaultValidatorFactory(); | |
applicationMap.put(VALIDATOR_FACTORY_KEY, validatorFactory); | |
} | |
return validatorFactory; | |
} | |
} |