private void initMethodConstraints( Class<?> clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { final Method[] declaredMethods = ReflectionHelper.getDeclaredMethods(clazz); for (Method method : declaredMethods) { // HV-172; ignoring synthetic methods (inserted by the compiler), as they can't have any // constraints // anyway and possibly hide the actual method with the same signature in the built meta model if (Modifier.isStatic(method.getModifiers()) || annotationIgnores.isIgnoreAnnotations(method) || method.isSynthetic()) { continue; } // try to get meta data from cache, otherwise retrieve it from the class MethodMetaData methodMetaData = getFromCache(clazz, method, beanMetaDataCache); if (methodMetaData == null) { methodMetaData = findMethodMetaData(method); } addMethodMetaConstraint(clazz, methodMetaData); } }
/** * 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; }