@Override public List<Constraint> resolveForProperty(String property, Class<?> clazz) { List<Constraint> constraints = new ArrayList<>(); String[] properties = property.split("\\."); Class<?> clazzforLoop = clazz; for (int i = 0; i < properties.length; i++) { String propertyForLoop = properties[i]; propertyForLoop = propertyForLoop.replace("[]", ""); BeanDescriptor beanDescriptor = this.validator.getConstraintsForClass(clazzforLoop); PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty( propertyForLoop); if (propertyDescriptor != null) { if (isLastElement(properties, i)) { collectConstraints(constraints, propertyDescriptor); } clazzforLoop = getFollowUpClass(propertyDescriptor, clazzforLoop); } else { break; } } return constraints; }
/** * Return the validation descriptors of given bean. * * @param className * the class to describe. * @return the validation descriptors of given bean. * @throws ClassNotFoundException * when the bean is not found. */ @GET public Map<String, List<String>> describe(final String className) throws ClassNotFoundException { final Class<?> beanClass = Class.forName(className); final Map<String, List<String>> result = new HashMap<>(); for (final PropertyDescriptor property : validator.getValidator().getConstraintsForClass(beanClass).getConstrainedProperties()) { final List<String> list = new ArrayList<>(); result.put(property.getPropertyName(), list); for (final ConstraintDescriptor<?> constraint : property.getConstraintDescriptors()) { // Since constraints are annotation, get the annotation class (interface) list.add(constraint.getAnnotation().getClass().getInterfaces()[0].getName()); } } return result; }
private Annotation getAnnotation(final PropertyDescriptor ppropertyDescription, final boolean useField, final Class<? extends Annotation> expectedAnnotationClass) { Annotation annotation = null; if (useField) { final JField field = this.beanType.findField(ppropertyDescription.getPropertyName()); if (field.getEnclosingType().equals(this.beanType)) { annotation = field.getAnnotation(expectedAnnotationClass); } } else { final JMethod method = this.beanType.findMethod(asGetter(ppropertyDescription), NO_ARGS); if (method.getEnclosingType().equals(this.beanType)) { annotation = method.getAnnotation(expectedAnnotationClass); } } return annotation; }
private boolean isPropertyConstrained(final PropertyDescriptor ppropertyDescription, final boolean useField) { // cascaded counts as constrained // we must know if the @Valid annotation is on a field or a getter final JClassType jClass = this.beanHelper.getJClass(); if (useField && jClass.findField(ppropertyDescription.getPropertyName()) .isAnnotationPresent(Valid.class)) { return true; } else if (!useField && jClass.findMethod(asGetter(ppropertyDescription), NO_ARGS) .isAnnotationPresent(Valid.class)) { return true; } // for non-cascaded properties for (final ConstraintDescriptor<?> constraint : ppropertyDescription .getConstraintDescriptors()) { final org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl<?> constraintHibernate = (org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl<?>) constraint; if (constraintHibernate .getElementType() == (useField ? ElementType.FIELD : ElementType.METHOD)) { return true; } } return false; }
private void writeValidateAllNonInheritedProperties(final SourceWriter sw) { // private <T> void validateAllNonInheritedProperties( sw.println("private <T> void validateAllNonInheritedProperties("); sw.indent(); sw.indent(); // GwtValidationContext<T> context, BeanType object, // Set<ConstraintViolation<T>> violations, Class<?>... groups) { sw.println("GwtValidationContext<T> context,"); sw.println(this.beanHelper.getTypeCanonicalName() + " object,"); sw.println("Set<ConstraintViolation<T>> violations,"); sw.println("Class<?>... groups) {"); sw.outdent(); for (final PropertyDescriptor p : this.beanHelper.getBeanDescriptor() .getConstrainedProperties()) { this.writeValidatePropertyCall(sw, p, false, true); } sw.outdent(); sw.println("}"); }
/** * get association type. * * @param ppropertyDescriptor property description * @param puseField use field * @return JClassType */ public JClassType getAssociationType(final PropertyDescriptor ppropertyDescriptor, final boolean puseField) { final JType type = this.getElementType(ppropertyDescriptor, puseField); if (type == null) { return null; } final JArrayType jarray = type.isArray(); if (jarray != null) { return jarray.getComponentType().isClassOrInterface(); } final JParameterizedType jptype = type.isParameterized(); JClassType[] typeArgs; if (jptype == null) { final JRawType jrtype = type.isRawType(); typeArgs = jrtype.getGenericType().getTypeParameters(); } else { typeArgs = jptype.getTypeArgs(); } // it is either a Iterable or a Map use the last type arg. return typeArgs[typeArgs.length - 1].isClassOrInterface(); }
JType getElementType(final PropertyDescriptor ppropertyDescriptor, final boolean puseField) { if (puseField) { final JField field = this.findRecursiveField(this.jclass, ppropertyDescriptor.getPropertyName()); if (field == null) { return null; } return field.getType(); } else { final JMethod method = this.findRecursiveMethod(this.jclass, GwtSpecificValidatorCreator.asGetter(ppropertyDescriptor), GwtSpecificValidatorCreator.NO_ARGS); if (method == null) { return null; } return method.getReturnType(); } }
/** * @return PropertyDescriptor may be null when JavaBean do not have any Bean Validation * annotations. */ private PropertyDescriptor getPropertyDescriptor() throws JspException { String path = getBindStatus().getPath(); int dotPos = path.indexOf('.'); if (dotPos == -1) { return null; } String beanName = path.substring(0, dotPos); String expression = path.substring(dotPos + 1); Map<String, Object> model = getRequestContext().getModel(); Object bean = getBean(beanName, model); Validator validator = getRequestContext().getWebApplicationContext().getBean(Validator.class); BeanDescriptor constraints = validator.getConstraintsForClass(bean.getClass()); return constraints.getConstraintsForProperty(expression); }
private static void applyDDL( String prefix, PersistentClass persistentClass, Class<?> clazz, ValidatorFactory factory, Set<Class<?>> groups, boolean activateNotNull, Dialect dialect) { final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz ); //no bean level constraints can be applied, go to the properties for ( PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties() ) { Property property = findPropertyByName( persistentClass, prefix + propertyDesc.getPropertyName() ); boolean hasNotNull; if ( property != null ) { hasNotNull = applyConstraints( propertyDesc.getConstraintDescriptors(), property, propertyDesc, groups, activateNotNull, dialect ); if ( property.isComposite() && propertyDesc.isCascaded() ) { Class<?> componentClass = ( (Component) property.getValue() ).getComponentClass(); /* * we can apply not null if the upper component let's us activate not null * and if the property is not null. * Otherwise, all sub columns should be left nullable */ final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull; applyDDL( prefix + propertyDesc.getPropertyName() + ".", persistentClass, componentClass, factory, groups, canSetNotNullOnColumns, dialect ); } //FIXME add collection of components } } }
private static boolean applyConstraints( Set<ConstraintDescriptor<?>> constraintDescriptors, Property property, PropertyDescriptor propertyDesc, Set<Class<?>> groups, boolean canApplyNotNull, Dialect dialect) { boolean hasNotNull = false; for ( ConstraintDescriptor<?> descriptor : constraintDescriptors ) { if ( groups != null && Collections.disjoint( descriptor.getGroups(), groups ) ) { continue; } if ( canApplyNotNull ) { hasNotNull = hasNotNull || applyNotNull( property, descriptor ); } // apply bean validation specific constraints applyDigits( property, descriptor ); applySize( property, descriptor, propertyDesc ); applyMin( property, descriptor, dialect ); applyMax( property, descriptor, dialect ); // apply hibernate validator specific constraints - we cannot import any HV specific classes though! // no need to check explicitly for @Range. @Range is a composed constraint using @Min and @Max which // will be taken care later applyLength( property, descriptor, propertyDesc ); // pass an empty set as composing constraints inherit the main constraint and thus are matching already hasNotNull = hasNotNull || applyConstraints( descriptor.getComposingConstraints(), property, propertyDesc, null, canApplyNotNull, dialect ); } return hasNotNull; }
private static void applySize(Property property, ConstraintDescriptor<?> descriptor, PropertyDescriptor propertyDescriptor) { if ( Size.class.equals( descriptor.getAnnotation().annotationType() ) && String.class.equals( propertyDescriptor.getElementClass() ) ) { @SuppressWarnings("unchecked") ConstraintDescriptor<Size> sizeConstraint = (ConstraintDescriptor<Size>) descriptor; int max = sizeConstraint.getAnnotation().max(); Column col = (Column) property.getColumnIterator().next(); if ( max < Integer.MAX_VALUE ) { col.setLength( max ); } } }
private static void applyLength(Property property, ConstraintDescriptor<?> descriptor, PropertyDescriptor propertyDescriptor) { if ( "org.hibernate.validator.constraints.Length".equals( descriptor.getAnnotation().annotationType().getName() ) && String.class.equals( propertyDescriptor.getElementClass() ) ) { @SuppressWarnings("unchecked") int max = (Integer) descriptor.getAttributes().get( "max" ); Column col = (Column) property.getColumnIterator().next(); if ( max < Integer.MAX_VALUE ) { col.setLength( max ); } } }
@Override public <T> Set<ConstraintViolation<T>> validate(final T object, final Class<?>... groups) { final MinijaxConstraintValidatorContext<T> context = new MinijaxConstraintValidatorContext<>(object); final BeanDescriptor descriptor = getConstraintsForClass(object.getClass()); for (final PropertyDescriptor propertyDescriptor : descriptor.getConstrainedProperties()) { final Object value = ((MinijaxPropertyDescriptor) propertyDescriptor).getValue(object); validateProperty(context, propertyDescriptor, value); } return context.getResult(); }
@Override public <T> Set<ConstraintViolation<T>> validateProperty(final T object, final String propertyName, final Class<?>... groups) { final MinijaxConstraintValidatorContext<T> context = new MinijaxConstraintValidatorContext<>(object); final BeanDescriptor descriptor = getConstraintsForClass(object.getClass()); final PropertyDescriptor propertyDescriptor = descriptor.getConstraintsForProperty(propertyName); final Object value = ((MinijaxPropertyDescriptor) propertyDescriptor).getValue(object); validateProperty(context, propertyDescriptor, value); return context.getResult(); }
@Override public <T> Set<ConstraintViolation<T>> validateValue(final Class<T> beanType, final String propertyName, final Object value, final Class<?>... groups) { final MinijaxConstraintValidatorContext<T> context = new MinijaxConstraintValidatorContext<>(null); final PropertyDescriptor property = getConstraintsForClass(beanType).getConstraintsForProperty(propertyName); validateProperty(context, property, value); return context.getResult(); }
private <T> void validateProperty( final MinijaxConstraintValidatorContext<T> context, final PropertyDescriptor property, final Object value) { context.push(property); validatePropertyConstraints(context, property, value); validatePropertyElementConstraints(context, property, value); context.pop(); }
@SuppressWarnings({ "rawtypes", "unchecked" }) private <T> void validatePropertyConstraints( final MinijaxConstraintValidatorContext<T> context, final PropertyDescriptor property, final Object value) { for (final ConstraintDescriptor constraint : property.getConstraintDescriptors()) { final ConstraintValidator validator = ((MinijaxConstraintDescriptor) constraint).getValidator(); if (!validator.isValid(value, context)) { context.buildViolation(constraint, value); } } }
@SuppressWarnings("rawtypes") private <T> void validatePropertyElementConstraints( final MinijaxConstraintValidatorContext<T> context, final PropertyDescriptor property, final Object value) { for (final ContainerElementTypeDescriptor descriptor : property.getConstrainedContainerElementTypes()) { for (final ConstraintDescriptor constraint : descriptor.getConstraintDescriptors()) { final ConstraintValidator validator = ((MinijaxConstraintDescriptor) constraint).getValidator(); if (value instanceof List) { validateList(context, constraint, validator, (List) value); } else if (value instanceof Iterable) { validateIterable(context, constraint, validator, (Iterable) value); } else if (value instanceof Map && descriptor.getTypeArgumentIndex() == 0) { validateMapKeys(context, constraint, validator, (Map<?, ?>) value); } else if (value instanceof Map) { validateMapValues(context, constraint, validator, (Map<?, ?>) value); } else if (value instanceof Optional) { validateOptional(context, constraint, validator, (Optional) value); } } } }
@Override public PropertyDescriptor getConstraintsForProperty(final String propertyName) { for (final PropertyDescriptor propertyDescriptor : constrainedProperties) { if (propertyDescriptor.getPropertyName().equals(propertyName)) { return propertyDescriptor; } } return null; }
private static Set<PropertyDescriptor> buildProperties(final Class<?> c) { final Set<PropertyDescriptor> results = new HashSet<>(); Class<?> currClass = c; while (currClass != null) { buildFields(results, currClass); buildGetters(results, currClass); currClass = currClass.getSuperclass(); } return results; }
private static void buildFields(final Set<PropertyDescriptor> results, final Class<?> currClass) { for (final Field field : currClass.getDeclaredFields()) { final MinijaxFieldDescriptor fieldDescriptor = new MinijaxFieldDescriptor(field); if (fieldDescriptor.hasConstraints()) { field.setAccessible(true); results.add(fieldDescriptor); } } }
private static void buildGetters(final Set<PropertyDescriptor> results, final Class<?> currClass) { for (final Method method : currClass.getDeclaredMethods()) { if (method.getName().startsWith("get") && method.getParameterCount() == 0) { final MinijaxGetterDescriptor getterDescriptor = new MinijaxGetterDescriptor(method); if (getterDescriptor.hasConstraints()) { method.setAccessible(true); results.add(getterDescriptor); } } } }
private void collectConstraints(List<Constraint> constraints, PropertyDescriptor propertyDescriptor) { for (ConstraintDescriptor<?> constraintDescriptor : propertyDescriptor .getConstraintDescriptors()) { constraints.add(new Constraint(constraintDescriptor.getAnnotation() .annotationType() .getName(), constraintDescriptor.getAttributes())); } }
private Class<?> getFollowUpClass(PropertyDescriptor propertyDescriptor, Class<?> clazzBefore) { Class<?> clazz = propertyDescriptor.getElementClass(); if (Collection.class.isAssignableFrom(clazz)) { final Predicate<? super Field> predicate = f -> f.getName().equals(propertyDescriptor .getPropertyName()); @SuppressWarnings("unchecked") Set<Field> field = ReflectionUtils.getAllFields(clazzBefore, predicate); Type typeArgument = ((ParameterizedType) field.iterator().next().getGenericType()) .getActualTypeArguments()[0]; return (Class<?>) typeArgument; } else { return clazz; } }
@Override public Set<PropertyDescriptor> getConstrainedProperties() { final Collection<PropertyDescriptorImpl> props = this.descriptorMap.values(); for (final PropertyDescriptorImpl prop : props) { prop.setValidationGroupsMetadata(this.validationGroupsMetadata); } return new HashSet<>(props); }
@Override public PropertyDescriptor getConstraintsForProperty(final String propertyName) { final PropertyDescriptorImpl propDesc = this.descriptorMap.get(propertyName); if (propDesc != null) { propDesc.setValidationGroupsMetadata(this.validationGroupsMetadata); } return propDesc; }
private boolean hasMatchingAnnotation(final PropertyDescriptor ppropertyDescription, final boolean useField, final ConstraintDescriptor<?> constraint) throws UnableToCompleteException { final Annotation expectedAnnotation = constraint.getAnnotation(); final Class<? extends Annotation> expectedAnnotationClass = expectedAnnotation.annotationType(); if (expectedAnnotation .equals(this.getAnnotation(ppropertyDescription, useField, expectedAnnotationClass))) { return true; } return this.hasMatchingAnnotation(expectedAnnotation, this.getAnnotations(ppropertyDescription, useField)); }
private boolean isPropertyConstrained(final BeanHelper helper, final PropertyDescriptor ppropertyDescription) { final Set<PropertyDescriptor> propertyDescriptors = helper.getBeanDescriptor().getConstrainedProperties(); final Predicate<PropertyDescriptor> nameMatches = this.newPropertyNameMatches(ppropertyDescription); return Iterables.any(propertyDescriptors, nameMatches); }
private void writePropertyValidators(final SourceWriter sw) throws UnableToCompleteException { for (final PropertyDescriptor p : this.beanHelper.getBeanDescriptor() .getConstrainedProperties()) { if (this.beanHelper.hasField(p)) { this.writeValidatePropertyMethod(sw, p, true); sw.println(); } if (this.beanHelper.hasGetter(p)) { this.writeValidatePropertyMethod(sw, p, false); sw.println(); } } }
private void writeValidateConstraint(final SourceWriter sw, final PropertyDescriptor ppropertyDescription, final Class<?> elementClass, final ConstraintDescriptor<?> constraint, final String constraintDescriptorVar) throws UnableToCompleteException { this.writeValidateConstraint(sw, ppropertyDescription, elementClass, constraint, constraintDescriptorVar, DEFAULT_VIOLATION_VAR); }
private void writeValidateFieldCall(final SourceWriter sw, final PropertyDescriptor ppropertyDescription, final boolean useValue, final boolean honorValid) { final String propertyName = ppropertyDescription.getPropertyName(); // validateProperty_<<field>>(context, sw.print(this.validateMethodFieldName(ppropertyDescription)); sw.print("(context, "); sw.print("violations, "); // null, (MyType) value, // or // object, object.getLastName(), if (useValue) { sw.print("null, "); sw.print("("); sw.print(this.getQualifiedSourceNonPrimitiveType( this.beanHelper.getElementType(ppropertyDescription, true))); sw.print(") value"); } else { sw.print("object, "); final JField field = this.beanType.getField(propertyName); if (field.isPublic()) { sw.print("object."); sw.print(propertyName); } else { this.fieldsToWrap.add(field); sw.print(this.toWrapperName(field) + "(object)"); } } sw.print(", "); // honorValid, groups); sw.print(Boolean.toString(honorValid)); sw.println(", groups);"); }
private void writeValidateGetterCall(final SourceWriter sw, final PropertyDescriptor ppropertyDescription, final boolean useValue, final boolean honorValid) { // validateProperty_get<<field>>(context, violations, sw.print(this.validateMethodGetterName(ppropertyDescription)); sw.print("(context, "); sw.print("violations, "); // object, object.getMyProp(), // or // null, (MyType) value, if (useValue) { sw.print("null, "); sw.print("("); sw.print(this.getQualifiedSourceNonPrimitiveType( this.beanHelper.getElementType(ppropertyDescription, false))); sw.print(") value"); } else { sw.print("object, "); final JMethod method = this.beanType.findMethod(asGetter(ppropertyDescription), NO_ARGS); if (method.isPublic()) { sw.print("object."); sw.print(asGetter(ppropertyDescription)); sw.print("()"); } else { this.gettersToWrap.add(method); sw.print(this.toWrapperName(method) + "(object)"); } } sw.print(", "); // honorValid, groups); sw.print(Boolean.toString(honorValid)); sw.println(", groups);"); }
private void writeValidateInheritance(final SourceWriter sw, final Class<?> clazz, final Stage stage, final PropertyDescriptor property, final boolean expandDefaultGroupSequence, final String groupsVarName) throws UnableToCompleteException { this.writeValidateInterfaces(sw, clazz, stage, property, expandDefaultGroupSequence, groupsVarName); final Class<?> superClass = clazz.getSuperclass(); if (superClass != null) { this.writeValidatorCall(sw, superClass, stage, property, expandDefaultGroupSequence, groupsVarName); } }
private void writeValidateInterfaces(final SourceWriter sw, final Class<?> clazz, final Stage stage, final PropertyDescriptor ppropertyDescription, final boolean expandDefaultGroupSequence, final String groupsVarName) throws UnableToCompleteException { for (final Class<?> type : clazz.getInterfaces()) { this.writeValidatorCall(sw, type, stage, ppropertyDescription, expandDefaultGroupSequence, groupsVarName); this.writeValidateInterfaces(sw, type, stage, ppropertyDescription, expandDefaultGroupSequence, groupsVarName); } }
private void writeValidatePropertyGroups(final SourceWriter sw) throws UnableToCompleteException { // public <T> void validatePropertyGroups( sw.println("public <T> void validatePropertyGroups("); // GwtValidationContext<T> context, BeanType object, String propertyName, // Set<ConstraintViolation<T>> violations, Class<?>... groups) throws ValidationException { sw.indent(); sw.indent(); sw.println("GwtValidationContext<T> context,"); sw.println(this.beanHelper.getTypeCanonicalName() + " object,"); sw.println("String propertyName,"); sw.println("Set<ConstraintViolation<T>> violations,"); sw.println("Class<?>... groups) throws ValidationException {"); sw.outdent(); for (final PropertyDescriptor property : this.beanHelper.getBeanDescriptor() .getConstrainedProperties()) { // if (propertyName.equals(myPropety)) { sw.print("if (propertyName.equals(\""); sw.print(property.getPropertyName()); sw.println("\")) {"); sw.indent(); this.writeValidatePropertyCall(sw, property, false, false); // validate all super classes and interfaces this.writeValidateInheritance(sw, this.beanHelper.getClazz(), Stage.PROPERTY, property); // } sw.outdent(); sw.print("} else "); } this.writeIfPropertyNameNotFound(sw); // } sw.outdent(); sw.println("}"); }
private BeanHelper doCreateHelper(final Class<?> clazz, final JClassType beanType, final TreeLogger logger, final GeneratorContext context) throws UnableToCompleteException { BeanHelper helper = this.getBean(beanType); if (helper == null) { BeanDescriptor bean; try { bean = this.serverSideValidator.getConstraintsForClass(clazz); } catch (final ValidationException e) { logger.log(TreeLogger.ERROR, "Unable to create a validator for " + clazz.getCanonicalName() + " because " + e.getMessage(), e); throw new UnableToCompleteException(); // NOPMD } helper = new BeanHelper(beanType, clazz, bean); this.cache.put(helper.getJClass(), helper); this.writeInterface(context, logger, helper); // now recurse on all Cascaded elements for (final PropertyDescriptor p : bean.getConstrainedProperties()) { // TODO(idol) only bother creating objects for properties that have constrains in the groups // specified in @GwtValidation, but not others if (p.isCascaded()) { this.doCreateHelperForProp(p, helper, logger, context); } } } return helper; }
boolean hasGetter(final PropertyDescriptor ppropertyDescriptor) { final JType[] paramTypes = new JType[] {}; try { this.jclass.getMethod(GwtSpecificValidatorCreator.asGetter(ppropertyDescriptor), paramTypes); return true; } catch (final NotFoundException e) { return false; } }
private Map<String, PropertyDescriptor> getConstrainedPropertiesAsDescriptors() { Map<String, PropertyDescriptor> theValue = newHashMap(); for (Entry<String, PropertyMetaData> entry : propertyMetaDataMap.entrySet()) { if (entry.getValue().isConstrained() && entry.getValue().getName() != null) { theValue.put(entry.getKey(), entry.getValue().asDescriptor(defaultGroupSequenceIsRedefined(), getDefaultGroupSequence(null))); } } return theValue; }
public Validator<?> buildValidator(Class<?> beanClass, String propertyName) { javax.validation.Validator beanValidator = getDefaultValidator(); if (beanValidator != null) { BeanDescriptor descriptor = beanValidator.getConstraintsForClass(beanClass); PropertyDescriptor propDescriptor = descriptor.getConstraintsForProperty(propertyName); if (propDescriptor != null && propDescriptor.hasConstraints()) { return new JSR303BeanValidator(beanClass, propertyName); } } return null; }
@Override protected int writeTagContent(TagWriter tagWriter) throws JspException { PropertyDescriptor propertyDescriptor = getPropertyDescriptor(); if ((propertyDescriptor != null) && !propertyDescriptor.getConstraintDescriptors().isEmpty()) { annotations = constrainteByAnnotationType(propertyDescriptor); } valueType = getBindStatus().getValueType(); return super.writeTagContent(tagWriter); }