| /** * apply constraints on a bean instance and return all the failures. */ public InvalidValue[] getInvalidValues(T bean) { return this .getInvalidValues( bean, new IdentitySet() ); } /** * apply constraints on a bean instance and return all the failures. */ protected InvalidValue[] getInvalidValues(T bean, Set<Object> circularityState) { if ( circularityState.contains( bean ) ) { // 该if else 是和Hibernate Core由关的, return EMPTY_INVALID_VALUE_ARRAY; //Avoid circularity } else { circularityState.add( bean ); } if ( !beanClass.isInstance( bean ) ) { // 如果beanClass不是该bean的实例,则抛出异常 throw new IllegalArgumentException( "not an instance of: " + bean.getClass() ); } List<InvalidValue> results = new ArrayList<InvalidValue>(); for ( int i = 0 ; i < beanValidators.size() ; i++ ) { // 验证类级别的约束 Validator validator = beanValidators.get( i ); if ( !validator.isValid( bean ) ) { //调用isValid方法,如果没有通过则添加到list<InvalidValue>中 //如果是自定义约束则isValid方法 由你来实现 results.add( new InvalidValue( messages.get( validator ), beanClass, null, bean, bean ) ); } } for ( int i = 0 ; i < memberValidators.size() ; i++ ) { //验证方法级别的约束 Member getter = memberGetters.get( i ); if ( Hibernate.isPropertyInitialized(bean, getter.getName() ) ) { // ? 检查该属性是否已初始化 Object value = getMemberValue( bean, getter ); //利用反射 取得该属性的值 Validator validator = memberValidators.get( i ); //取得该约束的验证实现类 if ( !validator.isValid( value ) ) { //调用isValid方法,如果没有通过则添加到list<InvalidValue>中 String propertyName = getPropertyName( getter ); results.add( new InvalidValue( messages.get( validator ), beanClass, propertyName, value, bean ) ); } } } for ( int i = 0 ; i < childGetters.size() ; i++ ) { // 处理子类类 Member getter = childGetters.get( i ); if ( Hibernate.isPropertyInitialized(bean, getter.getName() ) ) { //检查该属性是否已初始化 Object value = getMemberValue( bean, getter ); if ( value != null && Hibernate.isInitialized( value ) ) { String propertyName = getPropertyName( getter ); InvalidValue[] invalidValues = getClassValidator( value ) .getInvalidValues( value, circularityState ); // 通过参数value 得到 Class, 然后由Class作为key //在childClassValidators map中得到其ClassValidator //如果不存在 则创建新的 ,然后再调用ClassValidator的getInvalidValues方法 // 注意在调用getInvalidValues方法时 用到了circularityState 参数, 当调用循环一周时 返回(递归结束) for ( InvalidValue invalidValue : invalidValues ) { invalidValue.addParentBean( bean, propertyName ); results.add( invalidValue ); //添加的结果中 } } } } return results.toArray( new InvalidValue[results.size()] ); //返回InvalidValue数组 } /** * 通过参数value 得到 Class, 然后由Class作为key 在childClassValidators map中得到其ClassValidator * 如果不存在 则创建新的 然后返回 * @param value * @return */ private ClassValidator getClassValidator(Object value) { Class clazz = value.getClass(); ClassValidator validator = childClassValidators.get( clazz ); if ( validator == null ) { //handles polymorphism validator = new ClassValidator( clazz ); } return validator; } /** * Apply constraints of a particular property on a bean instance and return all the failures. * Note this is not recursive. * 验证单个属性的约束. */ //TODO should it be recursive ? public InvalidValue[] getInvalidValues(T bean, String propertyName) { List<InvalidValue> results = new ArrayList<InvalidValue>(); for ( int i = 0 ; i < memberValidators.size() ; i++ ) { Member getter = memberGetters.get( i ); if ( getPropertyName( getter ).equals( propertyName ) ) { // 验证该属性的约束 Object value = getMemberValue( bean, getter ); Validator validator = memberValidators.get( i ); if ( !validator.isValid( value ) ) { results.add( new InvalidValue( messages.get( validator ), beanClass, propertyName, value, bean ) ); } } } return results.toArray( new InvalidValue[results.size()] ); } /** * Apply constraints of a particular property value of a bean type and return all the failures. * The InvalidValue objects returns return null for InvalidValue#getBean() and InvalidValue#getRootBean() * Note this is not recursive. * 验证 value 是否满足当前属性的约束. */ //TODO should it be recursive? public InvalidValue[] getPotentialInvalidValues(String propertyName, Object value) { List<InvalidValue> results = new ArrayList<InvalidValue>(); for ( int i = 0 ; i < memberValidators.size() ; i++ ) { Member getter = memberGetters.get( i ); if ( getPropertyName( getter ).equals( propertyName ) ) { Validator validator = memberValidators.get( i ); if ( !validator.isValid( value ) ) { results.add( new InvalidValue( messages.get( validator ), beanClass, propertyName, value, null ) ); } } } return results.toArray( new InvalidValue[results.size()] ); } private Object getMemberValue(T bean, Member getter) { Object value; try { value = getValue( getter, bean ); } catch (Exception e) { throw new IllegalStateException( "Could not get property value" , e ); } return value; } private Object getValue(Member member, T bean) throws IllegalAccessException, InvocationTargetException { if ( member instanceof Field ) { return ( (Field) member ).get( bean ); } else if ( member instanceof Method ) { return ( (Method) member ).invoke( bean ); } else { throw new AssertionFailure( "Unexpected member: " + member.getClass().getName() ); } } public String getPropertyName(Member member) { //Do no try to cache the result in a map, it's actually much slower (2.x time) String propertyName; if ( member instanceof Field ) { propertyName = member.getName(); } else if ( member instanceof Method ) { propertyName = member.getName(); if ( propertyName.startsWith( "is" ) ) { propertyName = Introspector.decapitalize( propertyName.substring( 2 ) ); } else if ( propertyName.startsWith( "get" ) ) { propertyName = Introspector.decapitalize( propertyName.substring( 3 ) ); } //do nothing for non getter method, in case someone want to validate a PO Method } else { throw new AssertionFailure( "Unexpected member: " + member.getClass().getName() ); } return propertyName; } private String replace(String message, Annotation parameters) { StringTokenizer tokens = new StringTokenizer( message, "{}" , true ); StringBuilder buf = new StringBuilder( 30 ); boolean escaped = false ; while ( tokens.hasMoreTokens() ) { String token = tokens.nextToken(); if ( "{" .equals( token ) ) { escaped = true ; } else if ( "}" .equals( token ) ) { escaped = false ; } else if ( !escaped ) { buf.append( token ); } else { Method member; try { member = parameters.getClass().getMethod( token, (Class[]) null ); } catch (NoSuchMethodException nsfme) { member = null ; } if ( member != null ) { try { buf.append( member.invoke( parameters ) ); } catch (Exception e) { throw new IllegalArgumentException( "could not render message" , e ); } } else if ( messageBundle != null ) { String string = messageBundle.getString( token ); if ( string != null ) buf.append( replace( string, parameters ) ); } } } return buf.toString(); } /** * apply the registred constraints rules on the Hibernate metadata (to be applied on DB schema...) * 该方法是与实体类绑定的 不推荐使用 有兴趣的读者可以自己研究一下 * @param persistentClass Hibernate metadata */ public void apply(PersistentClass persistentClass) { //源代码省略 } /** * 断言该bean 是否符合所有约束. 负责抛出异常 * @param bean */ public void assertValid(T bean) { InvalidValue[] values = getInvalidValues( bean ); if ( values.length > 0 ) { throw new InvalidStateException( values ); } } /** * 该方法应该是序列化ResourceBundle的 为private方法 但并没有用到, 不知道为什么 可能以后会有用 * @param oos * @throws IOException */ private void writeObject(ObjectOutputStream oos) throws IOException { ResourceBundle rb = messageBundle; if ( rb != null && ! ( rb instanceof Serializable ) ) { messageBundle = null ; if ( ! defaultResourceBundle ) log.warn( "Serializing a ClassValidator with a not serializable ResourceBundle: ResourceBundle ignored" ); } oos.defaultWriteObject(); oos.writeObject( messageBundle ); messageBundle = rb; } /** * 该方法应该是读取序列化的ResourceBundle的 为private方法 但并没有用到,不知道为什么 可能以后会有用 * @param ois * @throws IOException * @throws ClassNotFoundException */ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); ResourceBundle rb = (ResourceBundle) ois.readObject(); if (rb == null ) rb = getDefaultResourceBundle(); initValidator( beanClass, new HashMap<Class, ClassValidator>(), rb ); } } |