private void initClassConstraints( Class<?> clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { if (annotationIgnores.isIgnoreAnnotations(clazz)) { return; } // HV-262 BeanMetaDataImpl<?> cachedMetaData = beanMetaDataCache.getBeanMetaData(clazz); List<ConstraintDescriptorImpl<?>> classMetaData; if (cachedMetaData != null && cachedMetaData.getMetaConstraintsAsMap().get(clazz) != null) { classMetaData = new ArrayList<ConstraintDescriptorImpl<?>>(); for (MetaConstraint<?> metaConstraint : cachedMetaData.getMetaConstraintsAsMap().get(clazz)) { ConstraintDescriptorImpl<?> descriptor = metaConstraint.getDescriptor(); if (descriptor.getElementType() == ElementType.TYPE) { classMetaData.add(descriptor); } } } else { classMetaData = findClassLevelConstraints(clazz); } for (ConstraintDescriptorImpl<?> constraintDescription : classMetaData) { BeanMetaConstraint<?> metaConstraint = createBeanMetaConstraint(clazz, null, constraintDescription); addMetaConstraint(clazz, metaConstraint); } }
private void initFieldConstraints( Class<?> clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { final Field[] fields = ReflectionHelper.getDeclaredFields(clazz); for (Field field : fields) { addToPropertyNameList(field); // HV-172 if (Modifier.isStatic(field.getModifiers())) { continue; } if (annotationIgnores.isIgnoreAnnotations(field)) { continue; } // HV-262 BeanMetaDataImpl<?> cachedMetaData = beanMetaDataCache.getBeanMetaData(clazz); boolean metaDataCached = cachedMetaData != null; List<ConstraintDescriptorImpl<?>> fieldMetaData; if (metaDataCached && cachedMetaData.getMetaConstraintsAsMap().get(clazz) != null) { fieldMetaData = new ArrayList<ConstraintDescriptorImpl<?>>(); for (BeanMetaConstraint<?> metaConstraint : cachedMetaData.getMetaConstraintsAsMap().get(clazz)) { ConstraintDescriptorImpl<?> descriptor = metaConstraint.getDescriptor(); if (descriptor.getElementType() == ElementType.FIELD && metaConstraint .getLocation() .getPropertyName() .equals(ReflectionHelper.getPropertyName(field))) { fieldMetaData.add(descriptor); } } } else { fieldMetaData = findConstraints(field, ElementType.FIELD); } for (ConstraintDescriptorImpl<?> constraintDescription : fieldMetaData) { ReflectionHelper.setAccessibility(field); BeanMetaConstraint<?> metaConstraint = createBeanMetaConstraint(clazz, field, constraintDescription); addMetaConstraint(clazz, metaConstraint); } // HV-433 Make sure the field is marked as cascaded in case it was configured via // xml/programmatic API or // it hosts the @Valid annotation boolean isCascadedField = metaDataCached && cachedMetaData.getCascadedMembers().contains(field); if (isCascadedField || field.isAnnotationPresent(Valid.class)) { addCascadedMember(field); } } }
private void addMethodMetaConstraint(Class<?> clazz, MethodMetaData methodMetaData) { addToBuilder(methodMetaData); if (ReflectionHelper.isGetterMethod(methodMetaData.getMethod())) { addToPropertyNameList(methodMetaData.getMethod()); ReflectionHelper.setAccessibility(methodMetaData.getMethod()); for (MethodMetaConstraint<?> metaConstraint : methodMetaData) { addMetaConstraint( clazz, getAsBeanMetaConstraint(metaConstraint, methodMetaData.getMethod())); } if (methodMetaData.isCascading()) { addCascadedMember(methodMetaData.getMethod()); } } }
/** * Constructor used when creating a bean meta data instance via the xml or programmatic API. In * this case additional metadata (the already configured constraints, cascaded members, etc) are * passed as well. * * @param beanClass The bean type for which to create the meta data * @param constraintHelper constraint helper * @param defaultGroupSequence programmatic/xml configured default group sequence (overrides * annotations) * @param defaultGroupSequenceProvider programmatic configured default group sequence provider * class (overrides annotations) * @param constraints programmatic/xml configured constraints * @param methodMetaDatas programmatic configured method constraints * @param cascadedMembers programmatic/xml configured cascaded members * @param annotationIgnores in xml configured ignores for annotations * @param beanMetaDataCache the cache of already configured meta data instances */ public BeanMetaDataImpl( Class<T> beanClass, ConstraintHelper constraintHelper, List<Class<?>> defaultGroupSequence, Class<? extends DefaultGroupSequenceProvider<?>> defaultGroupSequenceProvider, Map<Class<?>, List<BeanMetaConstraint<?>>> constraints, Set<AggregatedMethodMetaData> methodMetaDatas, Set<Member> cascadedMembers, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { this.beanClass = beanClass; this.constraintHelper = constraintHelper; this.defaultGroupSequenceProvider = null; for (Member member : cascadedMembers) { addCascadedMember(member); } classHierarchyWithoutInterfaces = ReflectionHelper.computeClassHierarchy(beanClass, false); // start the annotation discovery phase (look for annotations in the whole class hierarchy) createMetaData(annotationIgnores, beanMetaDataCache); // set the default explicitly specified default group sequence after the discovery process is // complete if (!defaultGroupSequence.isEmpty()) { setDefaultGroupSequence(defaultGroupSequence); } // set the default explicitly specified default group sequence provider after the discovery // process is complete if (defaultGroupSequenceProvider != null) { this.defaultGroupSequenceProvider = newGroupSequenceProviderInstance(defaultGroupSequenceProvider); } // validates that programmatic/xml definition of default group sequence or default group // sequence provider // doesn't introduce illegal default group sequence definition. if (hasDefaultGroupSequenceProvider() && this.defaultGroupSequence.size() > 1) { throw new GroupDefinitionException( "Default group sequence and default group sequence provider cannot be defined at the same time"); } // add the explicitly configured constraints for (Map.Entry<Class<?>, List<BeanMetaConstraint<?>>> entry : constraints.entrySet()) { Class<?> clazz = entry.getKey(); // will hold the method constraints (getter and non-getter) of the given class keyed by method Map<Method, List<MethodMetaConstraint<?>>> constraintsByMethod = newHashMap(); for (BeanMetaConstraint<?> constraint : entry.getValue()) { if (constraint.getDescriptor().getElementType() == ElementType.METHOD) { List<MethodMetaConstraint<?>> constraintsForMethod = constraintsByMethod.get(constraint.getLocation().getMember()); if (constraintsForMethod == null) { constraintsForMethod = newArrayList(); constraintsByMethod.put( (Method) constraint.getLocation().getMember(), constraintsForMethod); } constraintsForMethod.add(getAsMethodMetaConstraint(constraint)); } // register non-method constraints else { addMetaConstraint(clazz, constraint); } } // register the constraints for each method in methodMetaConstraints. Constraints at getters // will also registered in metaConstraints for (Entry<Method, List<MethodMetaConstraint<?>>> methodAndConstraints : constraintsByMethod.entrySet()) { MethodMetaData methodMetaData = new MethodMetaData( methodAndConstraints.getKey(), methodAndConstraints.getValue(), cascadedMembers.contains(methodAndConstraints.getKey())); addMethodMetaConstraint(clazz, methodMetaData); } } allMetaConstraints = buildAllConstraintSets(); directMetaConstraints = buildDirectConstraintSets(); // add the explicitly configured method constraints, here we need to merge the programmatic and // discovered // metadata built with the "automatic" discovering. if (!methodMetaDatas.isEmpty()) { for (AggregatedMethodMetaData aggregatedMethodMetaData : methodMetaDatas) { for (MethodMetaData methodMetaData : aggregatedMethodMetaData.getAllMethodMetaData()) { Method method = methodMetaData.getMethod(); addMethodMetaConstraint(method.getDeclaringClass(), methodMetaData); } } } this.methodMetaData = Collections.unmodifiableMap(buildMethodMetaData()); // reset class members we don't need any longer this.methodMetaDataBuilders = null; this.constraintHelper = null; }