├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── fluent-validator-demo ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── baidu │ │ │ └── unbiz │ │ │ └── fluentvalidator │ │ │ └── demo │ │ │ ├── Application.java │ │ │ ├── callback │ │ │ └── ValidateCarCallback.java │ │ │ ├── dto │ │ │ ├── Car.java │ │ │ ├── Garage.java │ │ │ └── Owner.java │ │ │ ├── error │ │ │ ├── CarError.java │ │ │ └── GarageError.java │ │ │ ├── exception │ │ │ ├── CarException.java │ │ │ └── RpcException.java │ │ │ ├── rpc │ │ │ ├── ManufacturerService.java │ │ │ └── impl │ │ │ │ └── ManufacturerServiceImpl.java │ │ │ ├── service │ │ │ ├── GarageService.java │ │ │ ├── GarageService2.java │ │ │ └── impl │ │ │ │ ├── GarageServiceImpl.java │ │ │ │ └── GarageServiceImpl2.java │ │ │ └── validator │ │ │ ├── CarLicensePlateValidator.java │ │ │ ├── CarManufacturerValidator.java │ │ │ ├── CarNotExceedLimitValidator.java │ │ │ ├── CarSeatCountValidator.java │ │ │ ├── CarValidator.java │ │ │ ├── GarageCarNotExceedLimitValidator.java │ │ │ └── NotEmptyValidator.java │ └── resources │ │ ├── ValidationMessages.properties │ │ ├── ValidationMessages_zh_CN.properties │ │ ├── error-message.properties │ │ ├── error-message_zh_CN.properties │ │ └── log4j.properties │ └── test │ ├── java │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ └── demo │ │ └── service │ │ └── impl │ │ ├── GarageServiceImpl2Test.java │ │ └── GarageServiceImplTest.java │ └── resources │ └── applicationContext.xml ├── fluent-validator-jsr303 ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ └── jsr303 │ │ ├── ConstraintViolationTransformer.java │ │ ├── DefaultConstraintViolationTransformer.java │ │ └── HibernateSupportedValidator.java │ └── test │ ├── java │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ ├── dto │ │ ├── BaseObject.java │ │ ├── Company.java │ │ ├── CompanyBuilder.java │ │ └── Department.java │ │ ├── error │ │ └── ErrorMsg.java │ │ ├── exception │ │ └── MyException.java │ │ ├── grouping │ │ ├── AddCompany.java │ │ ├── GroupingCheck.java │ │ └── GroupingCheck2.java │ │ ├── jsr303 │ │ ├── FluentHibernateValidatorTest.java │ │ └── HiberateSupportedValidatorTest.java │ │ ├── util │ │ └── DateUtil.java │ │ └── validator │ │ └── CompanyCustomValidator.java │ └── resources │ └── log4j.properties ├── fluent-validator-spring ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ ├── interceptor │ │ └── FluentValidateInterceptor.java │ │ ├── registry │ │ └── impl │ │ │ └── SpringApplicationContextRegistry.java │ │ ├── support │ │ ├── FluentValidatorPostProcessor.java │ │ ├── MessageSupport.java │ │ └── MethodNameFluentValidatorPostProcessor.java │ │ ├── util │ │ └── LocaleUtil.java │ │ └── validator │ │ └── NotNullValidator.java │ └── test │ ├── java │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ ├── dto │ │ └── Car.java │ │ ├── error │ │ └── CarError.java │ │ ├── exception │ │ └── CarException.java │ │ ├── groups │ │ └── Add.java │ │ ├── interceptor │ │ ├── FluentValidateInterceptorTest.java │ │ ├── MockInterceptor.java │ │ └── ValidateCarCallback.java │ │ ├── registry │ │ └── impl │ │ │ ├── Application.java │ │ │ └── SpringApplicationContextRegistryTest.java │ │ ├── rpc │ │ ├── ManufacturerService.java │ │ └── impl │ │ │ └── ManufacturerServiceImpl.java │ │ ├── service │ │ ├── CarService.java │ │ └── impl │ │ │ └── CarServiceImpl.java │ │ └── validator │ │ ├── CarLicensePlateValidator.java │ │ ├── CarManufacturerValidator.java │ │ ├── CarNotNullValidator.java │ │ ├── CarSeatCountValidator.java │ │ └── SizeValidator.java │ └── resources │ ├── applicationContext.xml │ ├── error-message.properties │ ├── error-message_zh_CN.properties │ └── log4j.properties ├── fluent-validator ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ ├── AnnotationValidator.java │ │ ├── AnnotationValidatorCache.java │ │ ├── Closure.java │ │ ├── ClosureHandler.java │ │ ├── ComplexResult.java │ │ ├── ComplexResult2.java │ │ ├── Composable.java │ │ ├── Const.java │ │ ├── DefaultValidateCallback.java │ │ ├── FluentValidator.java │ │ ├── GenericResult.java │ │ ├── QuickValidator.java │ │ ├── Result.java │ │ ├── ResultCollector.java │ │ ├── ResultCollectors.java │ │ ├── ValidateCallback.java │ │ ├── ValidationError.java │ │ ├── ValidationResult.java │ │ ├── Validator.java │ │ ├── ValidatorChain.java │ │ ├── ValidatorContext.java │ │ ├── ValidatorHandler.java │ │ ├── able │ │ ├── ListAble.java │ │ ├── ToStringable.java │ │ ├── TransformTo.java │ │ └── Valuable.java │ │ ├── annotation │ │ ├── FluentValid.java │ │ ├── FluentValidate.java │ │ ├── NotThreadSafe.java │ │ ├── Stateful.java │ │ └── ThreadSafe.java │ │ ├── exception │ │ ├── ClassInstantiationException.java │ │ └── RuntimeValidateException.java │ │ ├── registry │ │ ├── Registry.java │ │ └── impl │ │ │ └── SimpleRegistry.java │ │ ├── support │ │ ├── Computable.java │ │ ├── ConcurrentCache.java │ │ └── GroupingHolder.java │ │ ├── util │ │ ├── ArrayUtil.java │ │ ├── ClassUtil.java │ │ ├── CollectionUtil.java │ │ ├── Decorator.java │ │ ├── Function.java │ │ ├── Preconditions.java │ │ ├── PrimitiveWrapperArray.java │ │ ├── ReflectionUtil.java │ │ └── Supplier.java │ │ └── validator │ │ └── element │ │ ├── IterableValidatorElement.java │ │ ├── MultiValidatorElement.java │ │ ├── ValidatorElement.java │ │ ├── ValidatorElementComposite.java │ │ └── ValidatorElementList.java │ └── test │ ├── java │ └── com │ │ └── baidu │ │ └── unbiz │ │ └── fluentvalidator │ │ ├── FluentValidatorAnnotationBasedTest.java │ │ ├── FluentValidatorCascadeTest.java │ │ ├── FluentValidatorClassTest.java │ │ ├── FluentValidatorOnEachTest.java │ │ ├── FluentValidatorPropertyTest.java │ │ ├── FluentValidatorStringTest.java │ │ ├── QuickValidatorTest.java │ │ ├── dto │ │ ├── Car.java │ │ ├── CollectionWrapper.java │ │ ├── Garage.java │ │ ├── Person.java │ │ └── Person2.java │ │ ├── error │ │ └── CarError.java │ │ ├── exception │ │ └── CustomException.java │ │ ├── group │ │ └── CheckManufacturer.java │ │ ├── rpc │ │ ├── ManufacturerService.java │ │ └── impl │ │ │ └── ManufacturerServiceImpl.java │ │ ├── sample │ │ └── AnnotationClass.java │ │ ├── support │ │ └── ConcurrentCacheTest.java │ │ ├── util │ │ ├── ArrayUtilTest.java │ │ ├── ClassUtilTest.java │ │ ├── PreconditionsTest.java │ │ └── ReflectionUtilTest.java │ │ └── validator │ │ ├── CarLicensePlateValidator.java │ │ ├── CarManufacturerValidator.java │ │ ├── CarSeatCountValidator.java │ │ ├── CarValidator.java │ │ ├── CarValidator2.java │ │ ├── CarValidator3.java │ │ ├── NotNullValidator.java │ │ └── StringValidator.java │ └── resources │ └── log4j.properties ├── pom.xml └── run_unittest.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Idea 2 | *.iml 3 | *.idea 4 | 5 | */target 6 | 7 | */.settings 8 | .settings 9 | 10 | */.classpath 11 | 12 | */.project 13 | .project 14 | 15 | */.vscode 16 | .vscode 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - openjdk8 5 | 6 | after_success: 7 | - mvn jacoco:report coveralls:report -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/Application.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo; 2 | 3 | import java.util.Arrays; 4 | import java.util.Locale; 5 | 6 | import javax.validation.Validation; 7 | import javax.validation.Validator; 8 | import javax.validation.ValidatorFactory; 9 | 10 | import org.aspectj.lang.ProceedingJoinPoint; 11 | import org.aspectj.lang.annotation.Around; 12 | import org.aspectj.lang.annotation.Aspect; 13 | import org.aspectj.lang.annotation.Pointcut; 14 | import org.springframework.boot.SpringApplication; 15 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 16 | import org.springframework.boot.autoconfigure.SpringBootApplication; 17 | import org.springframework.context.ApplicationContext; 18 | import org.springframework.context.MessageSource; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.ComponentScan; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.context.support.ResourceBundleMessageSource; 23 | 24 | import com.baidu.unbiz.fluentvalidator.exception.RuntimeValidateException; 25 | import com.baidu.unbiz.fluentvalidator.registry.impl.SpringApplicationContextRegistry; 26 | import com.baidu.unbiz.fluentvalidator.support.MessageSupport; 27 | 28 | /** 29 | * @author zhangxu 30 | */ 31 | @SpringBootApplication 32 | @ComponentScan(value = "com.baidu.unbiz") 33 | @EnableAutoConfiguration 34 | @Configuration 35 | @Aspect 36 | public class Application { 37 | 38 | @Bean 39 | MessageSource messageSource() { 40 | ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource(); 41 | resourceBundleMessageSource.setBasename("error-message"); 42 | return resourceBundleMessageSource; 43 | } 44 | 45 | @Bean 46 | MessageSupport messageSupport(MessageSource messageSource) { 47 | MessageSupport messageSupport = new MessageSupport(); 48 | messageSupport.setLocale("zh_CN"); 49 | messageSupport.setMessageSource(messageSource); 50 | return messageSupport; 51 | } 52 | 53 | @Bean 54 | SpringApplicationContextRegistry springApplicationContextRegistry(ApplicationContext applicationContext) { 55 | SpringApplicationContextRegistry s = new SpringApplicationContextRegistry(); 56 | s.setApplicationContext(applicationContext); 57 | return s; 58 | } 59 | 60 | @Around("execution(* com.baidu.unbiz.fluentvalidator.demo.service.*.*(..))") 61 | public Object validateInterceptor(ProceedingJoinPoint pjp) throws Throwable { 62 | try { 63 | return pjp.proceed(); 64 | } catch (RuntimeValidateException e) { 65 | throw e.getCause(); 66 | } 67 | } 68 | 69 | @Bean 70 | public Validator hibernateValidator() { 71 | Locale.setDefault(Locale.US); 72 | ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 73 | return factory.getValidator(); 74 | } 75 | 76 | public static void main(String[] args) { 77 | ApplicationContext ctx = SpringApplication.run(Application.class, args); 78 | 79 | System.out.println("Let's inspect the beans provided by Spring Boot:"); 80 | 81 | String[] beanNames = ctx.getBeanDefinitionNames(); 82 | Arrays.sort(beanNames); 83 | for (String beanName : beanNames) { 84 | System.out.println(beanName); 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/callback/ValidateCarCallback.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.callback; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.DefaultValidateCallback; 6 | import com.baidu.unbiz.fluentvalidator.ValidateCallback; 7 | import com.baidu.unbiz.fluentvalidator.ValidationError; 8 | import com.baidu.unbiz.fluentvalidator.Validator; 9 | import com.baidu.unbiz.fluentvalidator.demo.exception.CarException; 10 | import com.baidu.unbiz.fluentvalidator.validator.element.ValidatorElementList; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class ValidateCarCallback extends DefaultValidateCallback implements ValidateCallback { 16 | 17 | @Override 18 | public void onFail(ValidatorElementList validatorElementList, List errors) { 19 | throw new CarException(errors.get(0).getErrorMsg()); 20 | } 21 | 22 | @Override 23 | public void onSuccess(ValidatorElementList validatorElementList) { 24 | System.out.println("Everything works fine!"); 25 | } 26 | 27 | @Override 28 | public void onUncaughtException(Validator validator, Exception e, Object target) throws Exception { 29 | throw new CarException(e); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/dto/Car.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.dto; 2 | 3 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 4 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarLicensePlateValidator; 5 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarManufacturerValidator; 6 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarSeatCountValidator; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class Car { 12 | 13 | @FluentValidate({CarManufacturerValidator.class}) 14 | private String manufacturer; 15 | 16 | @FluentValidate({CarLicensePlateValidator.class}) 17 | private String licensePlate; 18 | 19 | @FluentValidate({CarSeatCountValidator.class}) 20 | private int seatCount; 21 | 22 | @Override 23 | public String toString() { 24 | return "Car{" + 25 | "licensePlate='" + licensePlate + '\'' + 26 | ", manufacturer='" + manufacturer + '\'' + 27 | ", seatCount=" + seatCount + 28 | '}'; 29 | } 30 | 31 | public Car(String manufacturer, String licencePlate, int seatCount) { 32 | this.manufacturer = manufacturer; 33 | this.licensePlate = licencePlate; 34 | this.seatCount = seatCount; 35 | } 36 | 37 | public int getSeatCount() { 38 | return seatCount; 39 | } 40 | 41 | public void setSeatCount(int seatCount) { 42 | this.seatCount = seatCount; 43 | } 44 | 45 | public String getManufacturer() { 46 | return manufacturer; 47 | } 48 | 49 | public void setManufacturer(String manufacturer) { 50 | this.manufacturer = manufacturer; 51 | } 52 | 53 | public String getLicensePlate() { 54 | return licensePlate; 55 | } 56 | 57 | public void setLicensePlate(String licensePlate) { 58 | this.licensePlate = licensePlate; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/dto/Garage.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.dto; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | import javax.validation.constraints.NotNull; 7 | import javax.validation.constraints.Pattern; 8 | 9 | import org.hibernate.validator.constraints.Length; 10 | 11 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValid; 12 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 13 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarNotExceedLimitValidator; 14 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarValidator; 15 | import com.baidu.unbiz.fluentvalidator.demo.validator.NotEmptyValidator; 16 | 17 | /** 18 | * @author zhangxu 19 | */ 20 | public class Garage { 21 | 22 | @NotNull 23 | private Integer garageId; 24 | 25 | @NotNull 26 | @Pattern(regexp = "[0-9a-zA-Z]+") 27 | @Length(message = "{garage.name.length}", min = 5) 28 | private String name; 29 | 30 | @Valid 31 | private Owner owner; 32 | 33 | @NotNull 34 | @FluentValidate({CarNotExceedLimitValidator.class}) 35 | @FluentValid 36 | private List carList; 37 | 38 | @Override 39 | public String toString() { 40 | return "Garage{" + 41 | "carList=" + carList + 42 | ", garageId=" + garageId + 43 | ", name='" + name + '\'' + 44 | ", owner=" + owner + 45 | '}'; 46 | } 47 | 48 | public List getCarList() { 49 | return carList; 50 | } 51 | 52 | public void setCarList(List carList) { 53 | this.carList = carList; 54 | } 55 | 56 | public Integer getGarageId() { 57 | return garageId; 58 | } 59 | 60 | public void setGarageId(Integer garageId) { 61 | this.garageId = garageId; 62 | } 63 | 64 | public String getName() { 65 | return name; 66 | } 67 | 68 | public void setName(String name) { 69 | this.name = name; 70 | } 71 | 72 | public Owner getOwner() { 73 | return owner; 74 | } 75 | 76 | public void setOwner(Owner owner) { 77 | this.owner = owner; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/dto/Owner.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.dto; 2 | 3 | import javax.validation.constraints.Max; 4 | import javax.validation.constraints.Min; 5 | import javax.validation.constraints.NotNull; 6 | 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class Owner { 13 | 14 | @Min(1) 15 | @Max(100) 16 | private long id; 17 | 18 | @NotNull 19 | @Length(min = 5, max = 20) 20 | private String name; 21 | 22 | public Owner(long id, String name) { 23 | this.id = id; 24 | this.name = name; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "Owner{" + 30 | "id=" + id + 31 | ", name='" + name + '\'' + 32 | '}'; 33 | } 34 | 35 | public long getId() { 36 | return id; 37 | } 38 | 39 | public void setId(long id) { 40 | this.id = id; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/error/CarError.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.error; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public enum CarError { 7 | 8 | MANUFACTURER_ERROR(100, "Manufacturer is not valid, invalid value=%s"), 9 | LICENSEPLATE_ERROR(200, "License is not valid, invalid value=%s"), 10 | SEATCOUNT_ERROR(300, "Seat count is not valid, invalid value=%s"); 11 | 12 | CarError(int code, String msg) { 13 | this.code = code; 14 | this.msg = msg; 15 | } 16 | 17 | private int code; 18 | 19 | private String msg; 20 | 21 | public String msg() { 22 | return msg; 23 | } 24 | 25 | public int code() { 26 | return code; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/error/GarageError.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.error; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public enum GarageError { 7 | 8 | CAR_NUM_EXCEED_LIMIT(900, "car.size.exceed"); 9 | 10 | GarageError(int code, String msg) { 11 | this.code = code; 12 | this.msg = msg; 13 | } 14 | 15 | private int code; 16 | 17 | private String msg; 18 | 19 | public String msg() { 20 | return msg; 21 | } 22 | 23 | public int code() { 24 | return code; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/exception/CarException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.exception; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class CarException extends RuntimeException { 7 | 8 | public CarException() { 9 | } 10 | 11 | public CarException(String message) { 12 | super(message); 13 | } 14 | 15 | public CarException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public CarException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/exception/RpcException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.exception; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class RpcException extends RuntimeException { 7 | 8 | public RpcException() { 9 | } 10 | 11 | public RpcException(String message) { 12 | super(message); 13 | } 14 | 15 | public RpcException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public RpcException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/rpc/ManufacturerService.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.rpc; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhangxu 7 | */ 8 | public interface ManufacturerService { 9 | 10 | List getAllManufacturers(); 11 | 12 | void setIsMockFail(boolean isMockFail); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/rpc/impl/ManufacturerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.rpc.impl; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.baidu.unbiz.fluentvalidator.demo.exception.RpcException; 10 | import com.baidu.unbiz.fluentvalidator.demo.rpc.ManufacturerService; 11 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 12 | 13 | /** 14 | * @author zhangxu 15 | */ 16 | @Service 17 | public class ManufacturerServiceImpl implements ManufacturerService { 18 | 19 | private static final Logger LOGGER = LoggerFactory.getLogger(ManufacturerServiceImpl.class); 20 | 21 | private boolean isMockFail = false; 22 | 23 | @Override 24 | public List getAllManufacturers() { 25 | LOGGER.info("Call rpc to get all manufacturers..."); 26 | if (isMockFail) { 27 | isMockFail = false; 28 | throw new RpcException("Get all manufacturers failed"); 29 | } 30 | List ret = CollectionUtil.createArrayList(3); 31 | ret.add("BMW"); 32 | ret.add("Benz"); 33 | ret.add("Chevrolet"); 34 | return ret; 35 | } 36 | 37 | @Override 38 | public void setIsMockFail(boolean isMockFail) { 39 | this.isMockFail = isMockFail; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/service/GarageService.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.service; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.ComplexResult; 6 | import com.baidu.unbiz.fluentvalidator.Result; 7 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 8 | import com.baidu.unbiz.fluentvalidator.demo.dto.Garage; 9 | import com.baidu.unbiz.fluentvalidator.demo.exception.CarException; 10 | 11 | /** 12 | * @author zhangxu 13 | */ 14 | public interface GarageService { 15 | 16 | ComplexResult buildGarage(Garage garage); 17 | 18 | Result addCar(Car cars); 19 | 20 | Result addCars(List cars); 21 | 22 | Result addCarsThrowException(List cars); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/service/GarageService2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.service; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.ComplexResult; 6 | import com.baidu.unbiz.fluentvalidator.Result; 7 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 8 | import com.baidu.unbiz.fluentvalidator.demo.dto.Garage; 9 | 10 | /** 11 | * @author zhangxu 12 | */ 13 | public interface GarageService2 { 14 | 15 | Garage buildGarage(Garage garage); 16 | 17 | Car addCar(Car cars); 18 | 19 | List addCars(List cars); 20 | 21 | List addCarsThrowException(List cars); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/service/impl/GarageServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.service.impl; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toComplex; 4 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 5 | 6 | import java.util.List; 7 | 8 | import javax.annotation.Resource; 9 | 10 | import org.springframework.stereotype.Service; 11 | 12 | import com.baidu.unbiz.fluentvalidator.ComplexResult; 13 | import com.baidu.unbiz.fluentvalidator.DefaultValidateCallback; 14 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 15 | import com.baidu.unbiz.fluentvalidator.Result; 16 | import com.baidu.unbiz.fluentvalidator.ValidationError; 17 | import com.baidu.unbiz.fluentvalidator.Validator; 18 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 19 | import com.baidu.unbiz.fluentvalidator.demo.dto.Garage; 20 | import com.baidu.unbiz.fluentvalidator.demo.exception.CarException; 21 | import com.baidu.unbiz.fluentvalidator.demo.service.GarageService; 22 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarLicensePlateValidator; 23 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarManufacturerValidator; 24 | import com.baidu.unbiz.fluentvalidator.demo.validator.CarSeatCountValidator; 25 | import com.baidu.unbiz.fluentvalidator.demo.validator.GarageCarNotExceedLimitValidator; 26 | import com.baidu.unbiz.fluentvalidator.jsr303.HibernateSupportedValidator; 27 | import com.baidu.unbiz.fluentvalidator.registry.Registry; 28 | import com.baidu.unbiz.fluentvalidator.util.Preconditions; 29 | import com.baidu.unbiz.fluentvalidator.validator.element.ValidatorElementList; 30 | 31 | /** 32 | * @author zhangxu 33 | */ 34 | @Service 35 | public class GarageServiceImpl implements GarageService { 36 | 37 | @Resource 38 | private Registry springApplicationContextRegistry; 39 | 40 | @Resource 41 | private javax.validation.Validator hibernateValidator; 42 | 43 | @Override 44 | public Result addCars(List cars) { 45 | Preconditions.checkNotNull(cars, "car should not be null"); 46 | Result result = FluentValidator.checkAll() 47 | .configure(springApplicationContextRegistry) 48 | .onEach(cars) 49 | .doValidate(new DefaultValidateCallback() { 50 | @Override 51 | public void onFail(ValidatorElementList validatorElementList, List errors) { 52 | throw new CarException(errors.get(0).getErrorMsg()); 53 | } 54 | 55 | @Override 56 | public void onUncaughtException(Validator validator, Exception e, Object target) throws Exception { 57 | throw new CarException(e); 58 | } 59 | }) 60 | .result(toSimple()); 61 | return result; 62 | } 63 | 64 | @Override 65 | public Result addCarsThrowException(List cars) { 66 | return addCars(cars); 67 | } 68 | 69 | @Override 70 | public Result addCar(Car car) { 71 | Preconditions.checkNotNull(car, "car should not be null"); 72 | Result result = FluentValidator.checkAll().failOver() 73 | .on(car.getManufacturer(), new CarManufacturerValidator()) 74 | .on(car.getSeatCount(), new CarSeatCountValidator()) 75 | .on(car.getLicensePlate(), new CarLicensePlateValidator()) 76 | .doValidate().result(toSimple()); 77 | return result; 78 | } 79 | 80 | @Override 81 | public ComplexResult buildGarage(Garage garage) { 82 | Preconditions.checkNotNull(garage, "garage should not be null"); 83 | ComplexResult result = FluentValidator.checkAll() 84 | .configure(springApplicationContextRegistry) 85 | .on(garage, new HibernateSupportedValidator().setHiberanteValidator(hibernateValidator)) 86 | .on(garage, new GarageCarNotExceedLimitValidator()) 87 | .onEach(garage.getCarList()) 88 | .doValidate().result(toComplex()); 89 | return result; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/service/impl/GarageServiceImpl2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.service.impl; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.Resource; 6 | import javax.validation.constraints.NotNull; 7 | import javax.validation.constraints.Size; 8 | 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValid; 12 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 13 | import com.baidu.unbiz.fluentvalidator.demo.dto.Garage; 14 | import com.baidu.unbiz.fluentvalidator.demo.rpc.ManufacturerService; 15 | import com.baidu.unbiz.fluentvalidator.demo.service.GarageService2; 16 | import com.baidu.unbiz.fluentvalidator.demo.validator.NotEmptyValidator; 17 | 18 | /** 19 | * 使用拦截器做验证 20 | * 21 | * @author zhangxu 22 | */ 23 | @Service 24 | public class GarageServiceImpl2 implements GarageService2 { 25 | 26 | @Override 27 | public List addCars(@FluentValid(NotEmptyValidator.class) List cars) { 28 | System.out.println(cars); 29 | return cars; 30 | } 31 | 32 | @Override 33 | public List addCarsThrowException(@FluentValid List cars) { 34 | System.out.println(cars); 35 | return cars; 36 | } 37 | 38 | @Override 39 | public Car addCar(@FluentValid Car car) { 40 | System.out.println(car); 41 | return car; 42 | } 43 | 44 | @Override 45 | public Garage buildGarage(@FluentValid Garage garage) { 46 | System.out.println(garage); 47 | return garage; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/CarLicensePlateValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.ValidationError; 4 | import com.baidu.unbiz.fluentvalidator.Validator; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 7 | import com.baidu.unbiz.fluentvalidator.demo.error.CarError; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class CarLicensePlateValidator extends ValidatorHandler implements Validator { 13 | 14 | @Override 15 | public boolean validate(ValidatorContext context, String t) { 16 | if (t.startsWith("NYC") || t.startsWith("LA") || t.startsWith("BJ")) { 17 | return true; 18 | } 19 | context.addError(ValidationError.create(String.format(CarError.LICENSEPLATE_ERROR.msg(), t)) 20 | .setErrorCode(CarError.LICENSEPLATE_ERROR.code()) 21 | .setField("licensePlate") 22 | .setInvalidValue(t)); 23 | return false; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/CarManufacturerValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import javax.annotation.Resource; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.baidu.unbiz.fluentvalidator.ValidationError; 8 | import com.baidu.unbiz.fluentvalidator.Validator; 9 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 10 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 11 | import com.baidu.unbiz.fluentvalidator.demo.error.CarError; 12 | import com.baidu.unbiz.fluentvalidator.demo.rpc.ManufacturerService; 13 | import com.baidu.unbiz.fluentvalidator.demo.rpc.impl.ManufacturerServiceImpl; 14 | 15 | /** 16 | * @author zhangxu 17 | */ 18 | @Component 19 | public class CarManufacturerValidator extends ValidatorHandler implements Validator { 20 | 21 | @Resource 22 | private ManufacturerService manufacturerService = new ManufacturerServiceImpl(); 23 | 24 | @Override 25 | public boolean validate(ValidatorContext context, String t) { 26 | Boolean ignoreManufacturer = context.getAttribute("ignoreManufacturer", Boolean.class); 27 | if (ignoreManufacturer != null && ignoreManufacturer) { 28 | return true; 29 | } 30 | 31 | if (!manufacturerService.getAllManufacturers().contains(t)) { 32 | context.addError(ValidationError.create(String.format(CarError.MANUFACTURER_ERROR.msg(), t)) 33 | .setErrorCode(CarError.MANUFACTURER_ERROR.code()) 34 | .setField("manufacturer") 35 | .setInvalidValue(t)); 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/CarNotExceedLimitValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.ValidationError; 6 | import com.baidu.unbiz.fluentvalidator.Validator; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 8 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 9 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 10 | import com.baidu.unbiz.fluentvalidator.demo.error.GarageError; 11 | import com.baidu.unbiz.fluentvalidator.support.MessageSupport; 12 | 13 | /** 14 | * @author zhangxu 15 | */ 16 | public class CarNotExceedLimitValidator extends ValidatorHandler> implements Validator> { 17 | 18 | public static final int MAX_CAR_NUM = 50; 19 | 20 | @Override 21 | public boolean validate(ValidatorContext context, List cars) { 22 | if (cars.size() > MAX_CAR_NUM) { 23 | context.addError( 24 | ValidationError.create(MessageSupport.getText(GarageError.CAR_NUM_EXCEED_LIMIT.msg(), 25 | MAX_CAR_NUM)) 26 | .setErrorCode(GarageError.CAR_NUM_EXCEED_LIMIT.code()) 27 | .setField("garage.cars") 28 | .setInvalidValue(cars.size())); 29 | return false; 30 | } 31 | return true; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/CarSeatCountValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.demo.error.CarError; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class CarSeatCountValidator extends ValidatorHandler implements Validator { 12 | 13 | @Override 14 | public boolean validate(ValidatorContext context, Integer t) { 15 | if (t < 2) { 16 | context.addErrorMsg(String.format(CarError.SEATCOUNT_ERROR.msg(), t)); 17 | return false; 18 | } 19 | return true; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/CarValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toComplex; 4 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 5 | 6 | import java.util.List; 7 | 8 | import javax.annotation.Resource; 9 | 10 | import org.springframework.stereotype.Component; 11 | 12 | import com.baidu.unbiz.fluentvalidator.ComplexResult; 13 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 14 | import com.baidu.unbiz.fluentvalidator.Result; 15 | import com.baidu.unbiz.fluentvalidator.ValidationError; 16 | import com.baidu.unbiz.fluentvalidator.Validator; 17 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 18 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 19 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 20 | import com.baidu.unbiz.fluentvalidator.demo.error.CarError; 21 | import com.baidu.unbiz.fluentvalidator.demo.error.GarageError; 22 | import com.baidu.unbiz.fluentvalidator.registry.impl.SpringApplicationContextRegistry; 23 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 24 | 25 | /** 26 | * @author zhangxu 27 | */ 28 | @Component 29 | public class CarValidator extends ValidatorHandler> implements Validator> { 30 | 31 | public static final int MAX_CAR_NUM = 50; 32 | 33 | @Resource 34 | private SpringApplicationContextRegistry registry; 35 | 36 | @Override 37 | public boolean validate(ValidatorContext context, List cars) { 38 | ComplexResult result = FluentValidator.checkAll().configure(registry) 39 | .onEach(cars) 40 | .doValidate() 41 | .result(toComplex()); 42 | if (!result.isSuccess()) { 43 | ValidationError error = result.getErrors().get(0); 44 | context.addError(error); 45 | return false; 46 | } 47 | 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/GarageCarNotExceedLimitValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.ValidationError; 4 | import com.baidu.unbiz.fluentvalidator.Validator; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 7 | import com.baidu.unbiz.fluentvalidator.demo.dto.Garage; 8 | import com.baidu.unbiz.fluentvalidator.demo.error.GarageError; 9 | import com.baidu.unbiz.fluentvalidator.support.MessageSupport; 10 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class GarageCarNotExceedLimitValidator extends ValidatorHandler implements Validator { 16 | 17 | public static final int MAX_CAR_NUM = 50; 18 | 19 | @Override 20 | public boolean validate(ValidatorContext context, Garage t) { 21 | if (!CollectionUtil.isEmpty(t.getCarList())) { 22 | if (t.getCarList().size() > MAX_CAR_NUM) { 23 | context.addError( 24 | ValidationError.create(MessageSupport.getText(GarageError.CAR_NUM_EXCEED_LIMIT.msg(), 25 | MAX_CAR_NUM)) 26 | .setErrorCode(GarageError.CAR_NUM_EXCEED_LIMIT.code()) 27 | .setField("garage.cars") 28 | .setInvalidValue(t.getCarList().size())); 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/java/com/baidu/unbiz/fluentvalidator/demo/validator/NotEmptyValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.demo.validator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Validator; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 8 | import com.baidu.unbiz.fluentvalidator.demo.dto.Car; 9 | import com.baidu.unbiz.fluentvalidator.demo.error.CarError; 10 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class NotEmptyValidator extends ValidatorHandler> implements Validator> { 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, List cars) { 19 | if (CollectionUtil.isEmpty(cars)) { 20 | context.addErrorMsg("Cars is empty"); 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/resources/ValidationMessages.properties: -------------------------------------------------------------------------------- 1 | garage.name.length=garage name length is invalid -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/resources/ValidationMessages_zh_CN.properties: -------------------------------------------------------------------------------- 1 | garage.name.length=\u8f66\u5e93\u540d\u79f0\u957f\u5ea6\u975e\u6cd5 -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/resources/error-message.properties: -------------------------------------------------------------------------------- 1 | car.size.exceed=Car number exceeds limit, max available num is {0} -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/resources/error-message_zh_CN.properties: -------------------------------------------------------------------------------- 1 | car.size.exceed=\u6c7d\u8f66\u6570\u91cf\u8d85\u8fc7\u9650\u5236\uff0c\u6700\u591a\u5141\u8bb8{0}\u4e2a -------------------------------------------------------------------------------- /fluent-validator-demo/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | 3 | # navi log 4 | log4j.logger.com.baidu.unbiz=DEBUG 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.encoding=gbk 8 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.console.layout.ConversionPattern=[%p]\t%d\t[%t]\t%c{3}\t(%F:%L)\t-%m%n 10 | -------------------------------------------------------------------------------- /fluent-validator-demo/src/test/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | error-message 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | *arageServiceImpl2 42 | 43 | 44 | 45 | 46 | fluentValidateInterceptor 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/main/java/com/baidu/unbiz/fluentvalidator/jsr303/ConstraintViolationTransformer.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.jsr303; 2 | 3 | import javax.validation.ConstraintViolation; 4 | 5 | import com.baidu.unbiz.fluentvalidator.ValidationError; 6 | 7 | /** 8 | * {@link ConstraintViolation}到{@link ValidationError}的转换器 9 | * 10 | * @author zhangxu 11 | */ 12 | public interface ConstraintViolationTransformer { 13 | 14 | /** 15 | * {@link ConstraintViolation}到{@link ValidationError}的转换 16 | * 17 | * @param constraintViolation hibernate的错误 18 | * 19 | * @return fluent-validator框架的错误ValidationError 20 | */ 21 | ValidationError toValidationError(ConstraintViolation constraintViolation); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/main/java/com/baidu/unbiz/fluentvalidator/jsr303/DefaultConstraintViolationTransformer.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.jsr303; 2 | 3 | import javax.validation.ConstraintViolation; 4 | 5 | import com.baidu.unbiz.fluentvalidator.ValidationError; 6 | 7 | /** 8 | * 默认的{@link ConstraintViolation}到{@link ValidationError}的转换器 9 | * 10 | * @author zhangxu 11 | */ 12 | public class DefaultConstraintViolationTransformer implements ConstraintViolationTransformer { 13 | 14 | @Override 15 | public ValidationError toValidationError(ConstraintViolation constraintViolation) { 16 | return ValidationError.create(constraintViolation.getMessage()) 17 | .setField(constraintViolation.getPropertyPath().toString()) 18 | .setInvalidValue(constraintViolation.getInvalidValue()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/main/java/com/baidu/unbiz/fluentvalidator/jsr303/HibernateSupportedValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.jsr303; 2 | 3 | import java.util.Set; 4 | 5 | import javax.validation.ConstraintViolation; 6 | 7 | import com.baidu.unbiz.fluentvalidator.ValidationError; 8 | import com.baidu.unbiz.fluentvalidator.annotation.NotThreadSafe; 9 | import com.baidu.unbiz.fluentvalidator.Validator; 10 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 11 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 12 | import com.baidu.unbiz.fluentvalidator.support.GroupingHolder; 13 | import com.baidu.unbiz.fluentvalidator.util.ArrayUtil; 14 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 15 | 16 | /** 17 | * 定制JSR303的实现Hibernate Validator验证器 18 | * 19 | * @author zhangxu 20 | */ 21 | @NotThreadSafe 22 | public class HibernateSupportedValidator extends ValidatorHandler implements Validator { 23 | 24 | /** 25 | * A Validator instance is thread-safe and may be reused multiple times. It thus can safely be stored in a static 26 | * field and be used in the test methods to validate the different Car instances. 27 | */ 28 | private static javax.validation.Validator HIBERNATE_VALIDATOR; 29 | 30 | /** 31 | * hibernate默认的错误码 32 | */ 33 | private int hibernateDefaultErrorCode; 34 | 35 | /** 36 | * {@link ConstraintViolation}到{@link ValidationError}的转换器 37 | */ 38 | private ConstraintViolationTransformer constraintViolationTransformer = new DefaultConstraintViolationTransformer(); 39 | 40 | @Override 41 | public boolean accept(ValidatorContext context, T t) { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean validate(ValidatorContext context, T t) { 47 | Class[] groups = GroupingHolder.getGrouping(); 48 | Set> constraintViolations; 49 | if (ArrayUtil.isEmpty(groups)) { 50 | constraintViolations = HIBERNATE_VALIDATOR.validate(t); 51 | } else { 52 | constraintViolations = HIBERNATE_VALIDATOR.validate(t, groups); 53 | } 54 | if (CollectionUtil.isEmpty(constraintViolations)) { 55 | return true; 56 | } else { 57 | for (ConstraintViolation constraintViolation : constraintViolations) { 58 | context.addError(constraintViolationTransformer.toValidationError(constraintViolation) 59 | .setErrorCode(hibernateDefaultErrorCode)); 60 | } 61 | return false; 62 | } 63 | } 64 | 65 | @Override 66 | public void onException(Exception e, ValidatorContext context, T t) { 67 | 68 | } 69 | 70 | public javax.validation.Validator getHiberanteValidator() { 71 | return HIBERNATE_VALIDATOR; 72 | } 73 | 74 | /** 75 | * This is typo method, should use {@link #setHibernateValidator(javax.validation.Validator)} 76 | */ 77 | @Deprecated 78 | public HibernateSupportedValidator setHiberanteValidator(javax.validation.Validator validator) { 79 | HibernateSupportedValidator.HIBERNATE_VALIDATOR = validator; 80 | return this; 81 | } 82 | 83 | public HibernateSupportedValidator setHibernateValidator(javax.validation.Validator validator) { 84 | HibernateSupportedValidator.HIBERNATE_VALIDATOR = validator; 85 | return this; 86 | } 87 | 88 | public HibernateSupportedValidator setHibernateDefaultErrorCode(int hibernateDefaultErrorCode) { 89 | this.hibernateDefaultErrorCode = hibernateDefaultErrorCode; 90 | return this; 91 | } 92 | } -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/dto/BaseObject.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | /** 4 | * ClassName: BaseObject
5 | * Function: 测试用继承的基类,模拟主键id 6 | * 7 | * @author Zhang Xu 8 | */ 9 | public class BaseObject { 10 | 11 | private int id; 12 | 13 | public int getId() { 14 | return id; 15 | } 16 | 17 | public void setId(int id) { 18 | this.id = id; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Company.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import javax.validation.Valid; 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Pattern; 9 | import javax.validation.constraints.Size; 10 | 11 | import org.apache.commons.lang.builder.ToStringBuilder; 12 | import org.apache.commons.lang.builder.ToStringStyle; 13 | import org.hibernate.validator.constraints.Length; 14 | import org.hibernate.validator.constraints.NotEmpty; 15 | 16 | import com.baidu.unbiz.fluentvalidator.grouping.AddCompany; 17 | 18 | /** 19 | * 公司DTO 20 | * 21 | * @author zhangxu 22 | */ 23 | public class Company extends BaseObject { 24 | 25 | @NotEmpty 26 | @Pattern(regexp = "[0-9a-zA-Z\4e00-\u9fa5]+") 27 | private String name; 28 | 29 | @NotNull 30 | private Date establishTime; 31 | 32 | @NotNull 33 | @Size(min = 0, max = 10) 34 | @Valid 35 | private List departmentList; 36 | 37 | @Length(message = "Company CEO is not valid", min = 10, groups = {AddCompany.class}) 38 | private String ceo; 39 | 40 | public Company() { 41 | super(); 42 | } 43 | 44 | public Company(int id, String name, Date establishTime, List departmentList, String ceo) { 45 | super(); 46 | this.setId(id); 47 | this.name = name; 48 | this.establishTime = establishTime; 49 | this.departmentList = departmentList; 50 | this.ceo = ceo; 51 | } 52 | 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | public void setName(String name) { 58 | this.name = name; 59 | } 60 | 61 | public List getDepartmentList() { 62 | return departmentList; 63 | } 64 | 65 | public void setDepartmentList(List departmentList) { 66 | this.departmentList = departmentList; 67 | } 68 | 69 | public Date getEstablishTime() { 70 | return establishTime; 71 | } 72 | 73 | public void setEstablishTime(Date establishTime) { 74 | this.establishTime = establishTime; 75 | } 76 | 77 | public String toString() { 78 | return new ToStringBuilder(this, ToStringStyle.DEFAULT_STYLE).append("id", this.getId()) 79 | .append("name", name).append("establishTime", establishTime) 80 | .append("departmentList", departmentList).toString(); 81 | } 82 | 83 | public String getCeo() { 84 | return ceo; 85 | } 86 | 87 | public void setCeo(String ceo) { 88 | this.ceo = ceo; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/dto/CompanyBuilder.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import java.text.DateFormat; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class CompanyBuilder { 10 | 11 | private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 12 | 13 | public static Company buildSimple() { 14 | try { 15 | Department department101 = new Department(101, "R&D"); 16 | Department department102 = new Department(102, "程序化广告交易工程平台技术部"); 17 | Department department103 = new Department(103, "市场部"); 18 | Department department104 = new Department(104, "Sales"); 19 | List departmentList1 = new ArrayList(); 20 | departmentList1.add(department101); 21 | departmentList1.add(department102); 22 | departmentList1.add(department103); 23 | departmentList1.add(department104); 24 | 25 | Company company = new Company(88, "百度时代网络技术有限公司", dateFormat.parse("2000-11-11"), 26 | departmentList1, "Robin Li"); 27 | return company; 28 | } catch (ParseException e) { 29 | e.printStackTrace(); 30 | return null; 31 | } 32 | } 33 | 34 | public static List buildMulti() { 35 | try { 36 | List ret = new ArrayList(); 37 | 38 | Department department101 = new Department(101, "R&D"); 39 | Department department102 = new Department(102, "程序化广告交易工程平台技术部"); 40 | Department department103 = new Department(103, "市场部"); 41 | Department department104 = new Department(104, "Sales"); 42 | List departmentList1 = new ArrayList(); 43 | departmentList1.add(department101); 44 | departmentList1.add(department102); 45 | departmentList1.add(department103); 46 | departmentList1.add(department104); 47 | 48 | Department department201 = new Department(201, "行政部"); 49 | Department department202 = new Department(202, "SaaS云"); 50 | List departmentList2 = new ArrayList(); 51 | departmentList2.add(department201); 52 | departmentList2.add(department202); 53 | 54 | Company company1 = new Company(88, "百度时代网络技术有限公司", dateFormat.parse("2000-11-11"), 55 | departmentList1, "Robin Li"); 56 | Company company2 = new Company(99, "IBM China", dateFormat.parse("1956-5-6"), 57 | departmentList2, "Tom"); 58 | 59 | ret.add(company1); 60 | ret.add(company2); 61 | 62 | return ret; 63 | } catch (ParseException e) { 64 | e.printStackTrace(); 65 | return null; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Department.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import javax.validation.constraints.NotNull; 4 | 5 | import org.apache.commons.lang.builder.ToStringBuilder; 6 | import org.apache.commons.lang.builder.ToStringStyle; 7 | import org.hibernate.validator.constraints.Length; 8 | import org.hibernate.validator.constraints.NotEmpty; 9 | 10 | /** 11 | * 部门DTO 12 | * 13 | * @author zhangxu 14 | */ 15 | public class Department { 16 | 17 | @NotNull 18 | private Integer id; 19 | 20 | @Length(max = 30) 21 | private String name; 22 | 23 | public Department() { 24 | 25 | } 26 | 27 | public Department(Integer id, String name) { 28 | super(); 29 | this.id = id; 30 | this.name = name; 31 | } 32 | 33 | public Integer getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Integer id) { 38 | this.id = id; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void setName(String name) { 46 | this.name = name; 47 | } 48 | 49 | public String toString() { 50 | return new ToStringBuilder(this, ToStringStyle.DEFAULT_STYLE).append("id", id) 51 | .append("name", name).toString(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/error/ErrorMsg.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.error; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public enum ErrorMsg { 7 | 8 | COMPANY_ID_INVALID("Company id is not valid, invalid value=%s"), 9 | COMPANY_DATE_INVALID("Company date is not valid, invalid value=%s"), 10 | COMPANY_CEO_INVALID("Company CEO is not valid"); 11 | 12 | ErrorMsg(String msg) { 13 | this.msg = msg; 14 | } 15 | 16 | private String msg; 17 | 18 | public String msg() { 19 | return msg; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/exception/MyException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.exception; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class MyException extends RuntimeException { 7 | 8 | public MyException() { 9 | } 10 | 11 | public MyException(String message) { 12 | super(message); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/grouping/AddCompany.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.grouping; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public interface AddCompany { 7 | } 8 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/grouping/GroupingCheck.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.grouping; 2 | 3 | import javax.validation.GroupSequence; 4 | import javax.validation.groups.Default; 5 | 6 | /** 7 | * If at least one constraint fails in a sequenced group none of the constraints of the following groups in the 8 | * sequence get validated. 9 | * 10 | * @author zhangxu 11 | */ 12 | @GroupSequence({AddCompany.class, Default.class}) 13 | public interface GroupingCheck { 14 | } 15 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/grouping/GroupingCheck2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.grouping; 2 | 3 | import javax.validation.GroupSequence; 4 | import javax.validation.groups.Default; 5 | 6 | /** 7 | * If at least one constraint fails in a sequenced group none of the constraints of the following groups in the 8 | * sequence get validated. 9 | * 10 | * @author zhangxu 11 | */ 12 | @GroupSequence({Default.class, AddCompany.class}) 13 | public interface GroupingCheck2 { 14 | } 15 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/jsr303/FluentHibernateValidatorTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.jsr303; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 4 | import static org.hamcrest.core.Is.is; 5 | import static org.junit.Assert.assertThat; 6 | 7 | import java.util.Locale; 8 | 9 | import javax.validation.Validation; 10 | import javax.validation.Validator; 11 | import javax.validation.ValidatorFactory; 12 | import javax.validation.groups.Default; 13 | 14 | import org.junit.BeforeClass; 15 | import org.junit.Test; 16 | 17 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 18 | import com.baidu.unbiz.fluentvalidator.Result; 19 | import com.baidu.unbiz.fluentvalidator.dto.Company; 20 | import com.baidu.unbiz.fluentvalidator.dto.CompanyBuilder; 21 | import com.baidu.unbiz.fluentvalidator.grouping.AddCompany; 22 | import com.baidu.unbiz.fluentvalidator.grouping.GroupingCheck; 23 | import com.baidu.unbiz.fluentvalidator.grouping.GroupingCheck2; 24 | import com.baidu.unbiz.fluentvalidator.validator.CompanyCustomValidator; 25 | 26 | /** 27 | * @author zhangxu 28 | */ 29 | public class FluentHibernateValidatorTest { 30 | 31 | private static Validator validator; 32 | 33 | @BeforeClass 34 | public static void setUpValidator() { 35 | Locale.setDefault(Locale.ENGLISH); 36 | ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 37 | validator = factory.getValidator(); 38 | } 39 | 40 | @Test 41 | public void testCompany() { 42 | Company company = CompanyBuilder.buildSimple(); 43 | 44 | Result ret = FluentValidator.checkAll() 45 | .on(company, new HibernateSupportedValidator().setHibernateValidator(validator)) 46 | .on(company, new CompanyCustomValidator()) 47 | .doValidate().result(toSimple()); 48 | System.out.println(ret); 49 | assertThat(ret.isSuccess(), is(true)); 50 | } 51 | 52 | @Test 53 | public void testCompanyGrouping() { 54 | Company company = CompanyBuilder.buildSimple(); 55 | company.setName("$%^$%^$%"); 56 | 57 | Result ret = FluentValidator.checkAll(AddCompany.class) 58 | .on(company, new HibernateSupportedValidator().setHibernateValidator(validator)) 59 | .on(company, new CompanyCustomValidator()) 60 | .doValidate().result(toSimple()); 61 | System.out.println(ret); 62 | assertThat(ret.isSuccess(), is(false)); 63 | assertThat(ret.getErrorNumber(), is(1)); 64 | assertThat(ret.getErrors().get(0), is("Company CEO is not valid")); 65 | } 66 | 67 | @Test 68 | public void testCompanyMultiGrouping() { 69 | Company company = CompanyBuilder.buildSimple(); 70 | company.setName("$%^$%^$%"); 71 | 72 | Result ret = FluentValidator.checkAll(Default.class, AddCompany.class) 73 | .on(company, new HibernateSupportedValidator().setHibernateValidator(validator)) 74 | .on(company, new CompanyCustomValidator()) 75 | .doValidate().result(toSimple()); 76 | System.out.println(ret); 77 | assertThat(ret.isSuccess(), is(false)); 78 | assertThat(ret.getErrorNumber(), is(2)); 79 | } 80 | 81 | @Test 82 | public void testCompanyGroupSequence() { 83 | Company company = CompanyBuilder.buildSimple(); 84 | company.setName("$%^$%^$%"); 85 | 86 | Result ret = FluentValidator.checkAll(GroupingCheck.class) 87 | .on(company, new HibernateSupportedValidator().setHibernateValidator(validator)) 88 | .on(company, new CompanyCustomValidator()) 89 | .doValidate().result(toSimple()); 90 | System.out.println(ret); 91 | assertThat(ret.isSuccess(), is(false)); 92 | assertThat(ret.getErrorNumber(), is(1)); 93 | assertThat(ret.getErrors().get(0), is("Company CEO is not valid")); 94 | } 95 | 96 | @Test 97 | public void testCompanyGroupSequence2() { 98 | Company company = CompanyBuilder.buildSimple(); 99 | company.setName("$%^$%^$%"); 100 | 101 | Result ret = FluentValidator.checkAll(GroupingCheck2.class) 102 | .on(company, new HibernateSupportedValidator().setHibernateValidator(validator)) 103 | .on(company, new CompanyCustomValidator()) 104 | .doValidate().result(toSimple()); 105 | System.out.println(ret); 106 | assertThat(ret.isSuccess(), is(false)); 107 | assertThat(ret.getErrorNumber(), is(1)); 108 | assertThat(ret.getErrors().get(0).startsWith("must match \"[0-9a-zA-Z"), is(true)); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.util.Date; 4 | import java.util.GregorianCalendar; 5 | 6 | /** 7 | * @author zhangxu 8 | */ 9 | public class DateUtil { 10 | 11 | /** 12 | * 生成java.util.Date类型的对象 13 | * 14 | * @param year int 年 15 | * @param month int 月 16 | * @param day int 日 17 | * 18 | * @return Date java.util.Date类型的对象 19 | */ 20 | public static Date getDate(int year, int month, int day) { 21 | GregorianCalendar d = new GregorianCalendar(year, month - 1, day); 22 | return d.getTime(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CompanyCustomValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import java.util.Date; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Validator; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 8 | import com.baidu.unbiz.fluentvalidator.dto.Company; 9 | import com.baidu.unbiz.fluentvalidator.error.ErrorMsg; 10 | import com.baidu.unbiz.fluentvalidator.util.DateUtil; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class CompanyCustomValidator extends ValidatorHandler implements Validator { 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, Company company) { 19 | if (company.getId() <= 0) { 20 | context.addErrorMsg(String.format(ErrorMsg.COMPANY_ID_INVALID.msg(), company.getId())); 21 | return false; 22 | } 23 | Date date = company.getEstablishTime(); 24 | 25 | // company established time must before 2010-1-1 26 | if (date.after(DateUtil.getDate(2010, 1, 1))) { 27 | context.addErrorMsg(String.format(ErrorMsg.COMPANY_DATE_INVALID.msg(), date)); 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /fluent-validator-jsr303/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | 3 | # navi log 4 | log4j.logger.com.baidu.unbiz=DEBUG 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.encoding=gbk 8 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.console.layout.ConversionPattern=[%p]\t%d\t[%t]\t%c{3}\t(%F:%L)\t-%m%n 10 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/registry/impl/SpringApplicationContextRegistry.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.registry.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.BeansException; 10 | import org.springframework.beans.factory.BeanFactoryUtils; 11 | import org.springframework.context.ApplicationContext; 12 | import org.springframework.context.ApplicationContextAware; 13 | 14 | import com.baidu.unbiz.fluentvalidator.registry.Registry; 15 | 16 | /** 17 | * {@link Registry}的一种利用SpringIoC容器查找bean的实现 18 | * 19 | * @author zhangxu 20 | */ 21 | public class SpringApplicationContextRegistry implements Registry, ApplicationContextAware { 22 | 23 | private static final Logger LOGGER = LoggerFactory.getLogger(SpringApplicationContextRegistry.class); 24 | 25 | /** 26 | * ApplicationContext 27 | */ 28 | private ApplicationContext applicationContext; 29 | 30 | /** 31 | * 默认的简单查找,当SpringIoC容器找不到时候,利用简单的方式获取 32 | */ 33 | private Registry simpleRegistry = new SimpleRegistry(); 34 | 35 | @Override 36 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 37 | this.applicationContext = applicationContext; 38 | } 39 | 40 | @Override 41 | public List findByType(Class type) { 42 | Map map = findByTypeWithName(type); 43 | if (map == null || map.isEmpty()) { 44 | LOGGER.warn("Not found from Spring IoC container for " + type.getSimpleName() + ", and try to init by " 45 | + "calling newInstance."); 46 | return simpleRegistry.findByType(type); 47 | } 48 | return new ArrayList(map.values()); 49 | } 50 | 51 | /** 52 | * 调用Spring工具类获取bean 53 | * 54 | * @param type 类类型 55 | * 56 | * @return 容器托管的bean字典 57 | */ 58 | public Map findByTypeWithName(Class type) { 59 | return BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, type); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/support/FluentValidatorPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import org.aopalliance.intercept.MethodInvocation; 4 | 5 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 6 | 7 | /** 8 | * 配合{@link com.baidu.unbiz.fluentvalidator.interceptor.FluentValidateInterceptor}使用, 9 | * 在内部初始化FluentValidator时候,需要额外的一些初始化工作。 10 | * 11 | * @author zhangxu 12 | */ 13 | public interface FluentValidatorPostProcessor { 14 | 15 | /** 16 | * 新建FluentValidator实例后,未做doValidate方法前植入一些调用的hook 17 | * 18 | * @param fluentValidator FluentValidator,还未执行doValidate方法 19 | * @param methodInvocation 拦截器拦截的执行的方法 20 | * 21 | * @return FluentValidator 22 | */ 23 | FluentValidator postProcessBeforeDoValidate(FluentValidator fluentValidator, MethodInvocation methodInvocation); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/support/MessageSupport.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import java.util.Locale; 4 | 5 | import javax.annotation.PostConstruct; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.context.MessageSource; 10 | 11 | import com.baidu.unbiz.fluentvalidator.util.LocaleUtil; 12 | import com.baidu.unbiz.fluentvalidator.util.Preconditions; 13 | 14 | /** 15 | * 国际化使用的错误消息辅助类 16 | *

17 | * 使用{@link MessageSource}来作为delegate,利用Spring容器加载ResourceBundle,进行语言和国家地区的错误消息支持。 18 | *

19 | * 该类的使用方法如下: 20 | *

21 | * 1)新建一个properties文件,例如文件名为error-message.properties,内容为: 22 | *

 23 |  * car.size.exceed=car size exceeds
 24 |  * 
25 | * 新建中文国际化文件error-message_zh_CN.properties,内容为: 26 | *
 27 |  *     car.size.exceed=\u6c7d\u8f66\u6570\u91cf\u8d85\u9650
 28 |  * 
29 | *

30 | * 2)在{@link com.baidu.unbiz.fluentvalidator.Validator}中的方法可以通过如下API调用获取错误消息: 31 | *

 32 |  *     MessageSupport.getText("car.size.exceed");
 33 |  * 
34 | *

35 | * 3)在Spring的XML配置中加入如下配置即可: 36 | *

 37 |  * <bean id="messageSource"
 38 |  * class="org.springframework.context.support.ResourceBundleMessageSource">
 39 |  * <property name="basenames">
 40 |  * <list>
 41 |  * <value>error-message</value>
 42 |  * </list>
 43 |  * </property>
 44 |  * </bean>
 45 |  *
 46 |  * <bean id="messageSupport"
 47 |  * class="com.baidu.unbiz.fluentvalidator.support.MessageSupport">
 48 |  * <property name="messageSource" ref="messageSource"/>
 49 |  * </bean>
 50 |  * 
51 | * 52 | * @author zhangxu 53 | */ 54 | public class MessageSupport { 55 | 56 | private static final Logger LOGGER = LoggerFactory.getLogger(MessageSupport.class); 57 | 58 | /** 59 | * Spring delegate resource bundle 60 | */ 61 | private static MessageSource messageSource; 62 | 63 | /** 64 | * 语言地区设置 65 | */ 66 | private static String locale; 67 | 68 | /** 69 | * 语言地区缓存 70 | */ 71 | private static Locale localeContext; 72 | 73 | /** 74 | * 如果在Spring容器中初始化,则打印一条消息 75 | */ 76 | @PostConstruct 77 | public void prepare() { 78 | Preconditions.checkNotNull(messageSource, "MessageSource should not be null"); 79 | LOGGER.info(this.getClass().getSimpleName() + " has been initialized properly"); 80 | localeContext = LocaleUtil.parseLocale(locale); 81 | } 82 | 83 | /** 84 | * 获取国际化消息 85 | * 86 | * @param code 消息key 87 | * 88 | * @return 消息 89 | */ 90 | public static String getText(String code) { 91 | return getText(code, null); 92 | } 93 | 94 | /** 95 | * 获取国际化消息 96 | * 97 | * @param code 消息key 98 | * @param args 参数列表 99 | * 100 | * @return 消息 101 | */ 102 | public static String getText(String code, Object... args) { 103 | return getText(code, args, localeContext); 104 | } 105 | 106 | /** 107 | * 获取国际化消息 108 | * 109 | * @param code 消息key 110 | * @param args 参数列表 111 | * @param locale 语言地区 112 | * 113 | * @return 消息 114 | */ 115 | public static String getText(String code, Object[] args, Locale locale) { 116 | Preconditions.checkState(messageSource != null, 117 | "If i18n is enabled, please make sure MessageSource is properly set as a member in " 118 | + "MessageSupport"); 119 | return messageSource.getMessage(code, args, locale); 120 | } 121 | 122 | public void setMessageSource(MessageSource messageSource) { 123 | this.messageSource = messageSource; 124 | } 125 | 126 | public void setLocale(String locale) { 127 | this.locale = locale; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/support/MethodNameFluentValidatorPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import org.aopalliance.intercept.MethodInvocation; 4 | import org.springframework.aop.support.AopUtils; 5 | 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.util.Preconditions; 8 | 9 | /** 10 | * 将拦截器拦截的方法名称注入FluentValidator上下文 11 | * 12 | * @author zhangxu 13 | */ 14 | public class MethodNameFluentValidatorPostProcessor implements FluentValidatorPostProcessor { 15 | 16 | /** 17 | * 拦截的方法名 18 | */ 19 | public static final String KEY_METHOD_NAME = "_method_name"; 20 | 21 | /** 22 | * 拦截的类Class 23 | */ 24 | public static final String KEY_TARGET_CLASS_SIMPLE_NAME = "_target_class_simple_name"; 25 | 26 | @Override 27 | public FluentValidator postProcessBeforeDoValidate(FluentValidator fluentValidator, MethodInvocation 28 | methodInvocation) { 29 | Preconditions.checkNotNull(methodInvocation, "MethodInvocation should not be NULL"); 30 | String methodName = methodInvocation.getMethod().getName(); 31 | Class targetClass = AopUtils.getTargetClass(methodInvocation.getThis()); 32 | fluentValidator.putAttribute2Context(KEY_METHOD_NAME, methodName); 33 | fluentValidator.putAttribute2Context(KEY_TARGET_CLASS_SIMPLE_NAME, targetClass); 34 | return fluentValidator; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/util/LocaleUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * 语言地区工具类 7 | * 8 | * @author zhangxu 9 | */ 10 | public class LocaleUtil { 11 | 12 | /** 13 | * 解析locale字符串。 14 | *

15 | * Locale字符串是符合下列格式:language_country_variant。 16 | *

17 | * 18 | * @param localeString 要解析的字符串 19 | * 20 | * @return Locale对象,如果locale字符串为空,则返回null 21 | */ 22 | public static Locale parseLocale(String localeString) { 23 | if (localeString == null || localeString.length() == 0) { 24 | return Locale.getDefault(); 25 | } 26 | localeString = localeString.trim(); 27 | 28 | if (localeString == null) { 29 | return null; 30 | } 31 | 32 | String language = ""; 33 | String country = ""; 34 | String variant = ""; 35 | 36 | // language 37 | int start = 0; 38 | int index = localeString.indexOf("_"); 39 | 40 | if (index >= 0) { 41 | language = localeString.substring(start, index).trim(); 42 | 43 | // country 44 | start = index + 1; 45 | index = localeString.indexOf("_", start); 46 | 47 | if (index >= 0) { 48 | country = localeString.substring(start, index).trim(); 49 | 50 | // variant 51 | variant = localeString.substring(index + 1).trim(); 52 | } else { 53 | country = localeString.substring(start).trim(); 54 | } 55 | } else { 56 | language = localeString.substring(start).trim(); 57 | } 58 | 59 | return new Locale(language, country, variant); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/main/java/com/baidu/unbiz/fluentvalidator/validator/NotNullValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | 7 | /** 8 | * 默认的不为空验证器 9 | * 10 | * @author zhangxu 11 | */ 12 | public class NotNullValidator extends ValidatorHandler implements Validator { 13 | 14 | @Override 15 | public boolean validate(ValidatorContext context, Object obj) { 16 | if (obj == null) { 17 | context.addErrorMsg("Input should not be NULL"); 18 | return false; 19 | } 20 | return true; 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Car.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import javax.validation.constraints.NotNull; 4 | 5 | import org.hibernate.validator.constraints.NotBlank; 6 | 7 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 8 | import com.baidu.unbiz.fluentvalidator.groups.Add; 9 | import com.baidu.unbiz.fluentvalidator.validator.CarLicensePlateValidator; 10 | import com.baidu.unbiz.fluentvalidator.validator.CarManufacturerValidator; 11 | import com.baidu.unbiz.fluentvalidator.validator.CarSeatCountValidator; 12 | 13 | /** 14 | * @author zhangxu 15 | */ 16 | public class Car { 17 | 18 | @FluentValidate({CarManufacturerValidator.class}) 19 | @NotBlank 20 | private String manufacturer; 21 | 22 | @FluentValidate(value = {CarLicensePlateValidator.class}, groups = {Add.class}) 23 | @NotNull(groups = {Add.class}) 24 | private String licensePlate; 25 | 26 | @FluentValidate({CarSeatCountValidator.class}) 27 | private int seatCount; 28 | 29 | @Override 30 | public String toString() { 31 | return "Car{" + 32 | "licensePlate='" + licensePlate + '\'' + 33 | ", manufacturer='" + manufacturer + '\'' + 34 | ", seatCount=" + seatCount + 35 | '}'; 36 | } 37 | 38 | public Car(String manufacturer, String licencePlate, int seatCount) { 39 | this.manufacturer = manufacturer; 40 | this.licensePlate = licencePlate; 41 | this.seatCount = seatCount; 42 | } 43 | 44 | public int getSeatCount() { 45 | return seatCount; 46 | } 47 | 48 | public void setSeatCount(int seatCount) { 49 | this.seatCount = seatCount; 50 | } 51 | 52 | public String getManufacturer() { 53 | return manufacturer; 54 | } 55 | 56 | public void setManufacturer(String manufacturer) { 57 | this.manufacturer = manufacturer; 58 | } 59 | 60 | public String getLicensePlate() { 61 | return licensePlate; 62 | } 63 | 64 | public void setLicensePlate(String licensePlate) { 65 | this.licensePlate = licensePlate; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/error/CarError.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.error; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public enum CarError { 7 | MANUFACTURER_ERROR("Manufacturer is not valid, invalid value=%s"), 8 | LICENSEPLATE_ERROR("License is not valid, invalid value=%s"), 9 | SEATCOUNT_ERROR("Seat count is not valid, invalid value=%s"), 10 | CAR_NULL("Car should not be null"), 11 | CAR_SIZE_EXCEED("car.size.exceed"); 12 | 13 | CarError(String msg) { 14 | this.msg = msg; 15 | } 16 | 17 | private String msg; 18 | 19 | public String msg() { 20 | return msg; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/exception/CarException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.exception; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class CarException extends RuntimeException { 7 | 8 | public CarException() { 9 | } 10 | 11 | public CarException(String message) { 12 | super(message); 13 | } 14 | 15 | public CarException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public CarException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/groups/Add.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.groups; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public interface Add { 7 | } 8 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/interceptor/MockInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.interceptor; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.aspectj.lang.reflect.MethodSignature; 9 | import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * 默认情况,使用AspectJ AOP,被代理的对象会在BeanNameAutoProxyCreator里面作为一个cglib代理处理过的target而存在 14 | * 15 | * @author zhangxu 16 | */ 17 | @Component 18 | @Aspect 19 | public class MockInterceptor { 20 | 21 | @Around("execution(* com.baidu.unbiz.fluentvalidator.service.impl.CarServiceImpl.*(..))") 22 | public Object validate4AjaxQuery(ProceedingJoinPoint pjp) throws Throwable { 23 | MethodInvocationProceedingJoinPoint methodJoinPoint = (MethodInvocationProceedingJoinPoint) pjp; 24 | MethodSignature methodSignature = (MethodSignature) methodJoinPoint.getSignature(); 25 | System.out.println("here we enter aspectJ interceptor"); 26 | Object[] args = pjp.getArgs(); 27 | System.out.println(Arrays.asList(args)); 28 | System.out.println(methodSignature); 29 | 30 | return pjp.proceed(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/interceptor/ValidateCarCallback.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.interceptor; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.DefaultValidateCallback; 6 | import com.baidu.unbiz.fluentvalidator.ValidateCallback; 7 | import com.baidu.unbiz.fluentvalidator.ValidationError; 8 | import com.baidu.unbiz.fluentvalidator.Validator; 9 | import com.baidu.unbiz.fluentvalidator.exception.CarException; 10 | import com.baidu.unbiz.fluentvalidator.validator.element.ValidatorElementList; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class ValidateCarCallback extends DefaultValidateCallback implements ValidateCallback { 16 | 17 | @Override 18 | public void onFail(ValidatorElementList validatorElementList, List errors) { 19 | throw new CarException(errors.get(0).getErrorMsg()); 20 | } 21 | 22 | @Override 23 | public void onSuccess(ValidatorElementList validatorElementList) { 24 | System.out.println("Everything works fine!"); 25 | } 26 | 27 | @Override 28 | public void onUncaughtException(Validator validator, Exception e, Object target) throws Exception { 29 | throw new CarException(e); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/registry/impl/Application.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.registry.impl; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.ComponentScan; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * @author zhangxu 15 | */ 16 | @SpringBootApplication 17 | @ComponentScan(value = "com.baidu.unbiz") 18 | @EnableAutoConfiguration 19 | public class Application { 20 | 21 | @Bean 22 | SpringApplicationContextRegistry springApplicationContextRegistry(ApplicationContext applicationContext) { 23 | SpringApplicationContextRegistry s = new SpringApplicationContextRegistry(); 24 | s.setApplicationContext(applicationContext); 25 | return s; 26 | } 27 | 28 | public static void main(String[] args) { 29 | ApplicationContext ctx = SpringApplication.run(Application.class, args); 30 | 31 | System.out.println("Let's inspect the beans provided by Spring Boot:"); 32 | 33 | String[] beanNames = ctx.getBeanDefinitionNames(); 34 | Arrays.sort(beanNames); 35 | for (String beanName : beanNames) { 36 | System.out.println(beanName); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/registry/impl/SpringApplicationContextRegistryTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.registry.impl; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 4 | import static org.hamcrest.core.Is.is; 5 | import static org.junit.Assert.assertThat; 6 | 7 | import javax.annotation.Resource; 8 | 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.boot.test.SpringApplicationConfiguration; 12 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 13 | 14 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 15 | import com.baidu.unbiz.fluentvalidator.Result; 16 | import com.baidu.unbiz.fluentvalidator.dto.Car; 17 | import com.baidu.unbiz.fluentvalidator.error.CarError; 18 | import com.baidu.unbiz.fluentvalidator.registry.Registry; 19 | 20 | /** 21 | * @author zhangxu 22 | */ 23 | @RunWith(SpringJUnit4ClassRunner.class) 24 | @SpringApplicationConfiguration(classes = Application.class) 25 | public class SpringApplicationContextRegistryTest { 26 | 27 | @Resource 28 | private Registry springApplicationContextRegistry; 29 | 30 | @Test 31 | public void testCarSeatContErrorFailFast() { 32 | Car car = getValidCar(); 33 | car.setSeatCount(99); 34 | 35 | Result ret = FluentValidator.checkAll().configure(springApplicationContextRegistry) 36 | .on(car) 37 | .doValidate() 38 | .result(toSimple()); 39 | System.out.println(ret); 40 | assertThat(ret.isSuccess(), is(false)); 41 | assertThat(ret.getErrorNumber(), is(1)); 42 | assertThat(ret.getErrors().get(0), is(String.format(CarError.SEATCOUNT_ERROR.msg(), 99))); 43 | } 44 | 45 | private Car getValidCar() { 46 | return new Car("BMW", "LA1234", 5); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/rpc/ManufacturerService.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.rpc; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhangxu 7 | */ 8 | public interface ManufacturerService { 9 | 10 | List getAllManufacturers(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/rpc/impl/ManufacturerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.rpc.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.baidu.unbiz.fluentvalidator.rpc.ManufacturerService; 10 | 11 | /** 12 | * @author zhangxu 13 | */ 14 | public class ManufacturerServiceImpl implements ManufacturerService { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(ManufacturerServiceImpl.class); 17 | 18 | @Override 19 | public List getAllManufacturers() { 20 | LOGGER.info("Get all manufacturers"); 21 | List ret = new ArrayList(); 22 | ret.add("BMW"); 23 | ret.add("Benz"); 24 | ret.add("Chevrolet"); 25 | return ret; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/service/CarService.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.service; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValid; 6 | import com.baidu.unbiz.fluentvalidator.dto.Car; 7 | import com.baidu.unbiz.fluentvalidator.groups.Add; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public interface CarService { 13 | 14 | Car addCar(Car car); 15 | 16 | Car addCar(int x, Car car); 17 | 18 | Car addCar(String x, Long y, Car car); 19 | 20 | List addCars(String x, List cars); 21 | 22 | Car[] addCars(Car[] cars, Double d); 23 | 24 | List addCarsWithAddOnChecks(String x, List cars); 25 | 26 | List addCarsWithGroups(List cars); 27 | 28 | List addCarsWithExcludeGroups(List cars); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/service/impl/CarServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.service.impl; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.stereotype.Service; 6 | 7 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValid; 8 | import com.baidu.unbiz.fluentvalidator.dto.Car; 9 | import com.baidu.unbiz.fluentvalidator.groups.Add; 10 | import com.baidu.unbiz.fluentvalidator.service.CarService; 11 | import com.baidu.unbiz.fluentvalidator.validator.CarNotNullValidator; 12 | import com.baidu.unbiz.fluentvalidator.validator.SizeValidator; 13 | 14 | /** 15 | * @author zhangxu 16 | */ 17 | @Service 18 | public class CarServiceImpl implements CarService { 19 | 20 | @Override 21 | public Car addCar(@FluentValid Car car) { 22 | System.out.println("Come on! " + car); 23 | return car; 24 | } 25 | 26 | @Override 27 | public Car addCar(int x, @FluentValid Car car) { 28 | System.out.println("Come on! " + car); 29 | return car; 30 | } 31 | 32 | @Override 33 | public Car addCar(@FluentValid String x, Long y, @FluentValid Car car) { 34 | System.out.println("Come on! " + car); 35 | return car; 36 | } 37 | 38 | @Override 39 | public List addCars(String x, @FluentValid List cars) { 40 | System.out.println("Come on! " + cars); 41 | return cars; 42 | } 43 | 44 | @Override 45 | public Car[] addCars(@FluentValid Car[] cars, Double d) { 46 | System.out.println("Come on! " + cars); 47 | return cars; 48 | } 49 | 50 | @Override 51 | public List addCarsWithAddOnChecks(String x, @FluentValid({CarNotNullValidator.class, SizeValidator.class}) 52 | List cars) { 53 | System.out.println("Come on! " + cars); 54 | return cars; 55 | } 56 | 57 | @Override 58 | public List addCarsWithGroups(@FluentValid(groups = {Add.class}) List cars) { 59 | System.out.println("Come on! " + cars); 60 | return cars; 61 | } 62 | 63 | @Override 64 | public List addCarsWithExcludeGroups(@FluentValid(excludeGroups = {Add.class}) List cars) { 65 | System.out.println("Come on! " + cars); 66 | return cars; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarLicensePlateValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Validator; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 8 | import com.baidu.unbiz.fluentvalidator.error.CarError; 9 | 10 | /** 11 | * @author zhangxu 12 | */ 13 | @Component 14 | public class CarLicensePlateValidator extends ValidatorHandler implements Validator { 15 | 16 | private MockRpcService normalMockRpcService = new NormalMockRpcService(); 17 | 18 | private MockRpcService abNormalMockRpcService = new AbnormalMockRpcService(); 19 | 20 | @Override 21 | public boolean validate(ValidatorContext context, String t) { 22 | if (t.startsWith("NYC") || t.startsWith("LA") || t.startsWith("BEIJING")) { 23 | if (!normalMockRpcService.isValid(t)) { 24 | context.addErrorMsg(String.format(CarError.LICENSEPLATE_ERROR.msg(), t)); 25 | return false; 26 | } 27 | } else { 28 | return abNormalMockRpcService.isValid(t); 29 | } 30 | return true; 31 | } 32 | 33 | } 34 | 35 | interface MockRpcService { 36 | 37 | boolean isValid(String licensePlate); 38 | 39 | } 40 | 41 | class NormalMockRpcService implements MockRpcService { 42 | 43 | public boolean isValid(String licensePlate) { 44 | if (licensePlate.startsWith("BEIJING")) { 45 | return false; 46 | } 47 | return true; 48 | } 49 | 50 | } 51 | 52 | class AbnormalMockRpcService implements MockRpcService { 53 | 54 | public boolean isValid(String licensePlate) { 55 | throw new RuntimeException("Call Rpc failed"); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarManufacturerValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Validator; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 8 | import com.baidu.unbiz.fluentvalidator.error.CarError; 9 | import com.baidu.unbiz.fluentvalidator.rpc.ManufacturerService; 10 | import com.baidu.unbiz.fluentvalidator.rpc.impl.ManufacturerServiceImpl; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | @Component 16 | public class CarManufacturerValidator extends ValidatorHandler implements Validator { 17 | 18 | private ManufacturerService manufacturerService = new ManufacturerServiceImpl(); 19 | 20 | @Override 21 | public boolean validate(ValidatorContext context, String t) { 22 | Boolean ignoreManufacturer = context.getAttribute("ignoreManufacturer", Boolean.class); 23 | if (ignoreManufacturer != null && ignoreManufacturer) { 24 | return true; 25 | } 26 | if (!manufacturerService.getAllManufacturers().contains(t)) { 27 | context.addErrorMsg(String.format(CarError.MANUFACTURER_ERROR.msg(), t)); 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarNotNullValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.error.CarError; 7 | import com.baidu.unbiz.fluentvalidator.support.MethodNameFluentValidatorPostProcessor; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class CarNotNullValidator extends ValidatorHandler implements Validator { 13 | 14 | @Override 15 | public boolean validate(ValidatorContext context, Object t) { 16 | String methodName = (String) context.getAttribute(MethodNameFluentValidatorPostProcessor.KEY_METHOD_NAME); 17 | System.out.println("MethodName = " + methodName); 18 | if (t == null) { 19 | context.addErrorMsg(CarError.CAR_NULL.msg()); 20 | return false; 21 | } 22 | return true; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarSeatCountValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.error.CarError; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class CarSeatCountValidator extends ValidatorHandler implements Validator { 12 | 13 | @Override 14 | public boolean validate(ValidatorContext context, Integer t) { 15 | if (t != 2 && t != 5 && t != 7) { 16 | context.addErrorMsg(String.format(CarError.SEATCOUNT_ERROR.msg(), t)); 17 | return false; 18 | } 19 | return true; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/java/com/baidu/unbiz/fluentvalidator/validator/SizeValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Validator; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 8 | import com.baidu.unbiz.fluentvalidator.dto.Car; 9 | import com.baidu.unbiz.fluentvalidator.error.CarError; 10 | import com.baidu.unbiz.fluentvalidator.support.MessageSupport; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class SizeValidator extends ValidatorHandler> implements Validator> { 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, List t) { 19 | if (t.size() > 10) { 20 | context.addErrorMsg(MessageSupport.getText(CarError.CAR_SIZE_EXCEED.msg())); 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | error-message 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | *ServiceImpl 44 | 45 | 46 | 47 | 48 | fluentValidateInterceptor 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/resources/error-message.properties: -------------------------------------------------------------------------------- 1 | car.size.exceed=car size exceeds -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/resources/error-message_zh_CN.properties: -------------------------------------------------------------------------------- 1 | car.size.exceed=\u6c7d\u8f66\u6570\u91cf\u8d85\u9650 -------------------------------------------------------------------------------- /fluent-validator-spring/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | 3 | # navi log 4 | log4j.logger.com.baidu.unbiz=DEBUG 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.encoding=gbk 8 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.console.layout.ConversionPattern=[%p]\t%d\t[%t]\t%c{3}\t(%F:%L)\t-%m%n 10 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/AnnotationValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | /** 9 | * 通过注解方式使用验证,利用反射缓存的属性、方法、及其对应的验证器Validator 10 | * 11 | * @author zhangxu 12 | */ 13 | public class AnnotationValidator { 14 | 15 | /** 16 | * 在POJO中定义中待验证的属性名称 17 | */ 18 | private Field field; 19 | 20 | /** 21 | * 在POJO中定义,待验证值的以get或者is前缀的方法 22 | */ 23 | private Method method; 24 | 25 | /** 26 | * 分组标识,在该分组内的才执行验证 27 | */ 28 | private Class[] groups; 29 | 30 | /** 31 | * 是否需要级联到类或者集合、数组泛型内部类做验证 32 | */ 33 | private boolean isCascade; 34 | 35 | /** 36 | * 验证器 37 | */ 38 | private List validators; 39 | 40 | @Override 41 | public String toString() { 42 | return "AnnotationValidator{" + 43 | "field=" + field + 44 | ", method=" + method + 45 | ", groups=" + Arrays.toString(groups) + 46 | ", isCascade=" + isCascade + 47 | ", validators=" + validators + 48 | '}'; 49 | } 50 | 51 | public Field getField() { 52 | return field; 53 | } 54 | 55 | public void setField(Field field) { 56 | this.field = field; 57 | } 58 | 59 | public Method getMethod() { 60 | return method; 61 | } 62 | 63 | public void setMethod(Method method) { 64 | this.method = method; 65 | } 66 | 67 | public List getValidators() { 68 | return validators; 69 | } 70 | 71 | public void setValidators(List validators) { 72 | this.validators = validators; 73 | } 74 | 75 | public Class[] getGroups() { 76 | return groups; 77 | } 78 | 79 | public void setGroups(Class[] groups) { 80 | this.groups = groups; 81 | } 82 | 83 | public boolean isCascade() { 84 | return isCascade; 85 | } 86 | 87 | public void setIsCascade(boolean isCascade) { 88 | this.isCascade = isCascade; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/Closure.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 仿闭包,接口中的 {@link #execute(Object...)} 通过回调模拟闭包。 5 | * 6 | * @author zhangxu 7 | */ 8 | public interface Closure { 9 | 10 | /** 11 | * Performs an action on the specified input object. 12 | * 13 | * @param input the input to execute on 14 | */ 15 | void execute(Object... input); 16 | 17 | /** 18 | * Get result 19 | * 20 | * @return result object 21 | */ 22 | T getResult(); 23 | 24 | /** 25 | * Wrap {@link #execute(Object...)} and {@link #getResult()} 26 | * 27 | * @param input the input to execute on 28 | * 29 | * @return result object 30 | */ 31 | T executeAndGetResult(Object... input); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ClosureHandler.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 仿闭包,接口中的 {@link #execute(Object...)} 通过回调模拟闭包 5 | *

6 | * 在实际应用中,在验证器内部会调用一些比较耗时操作,例如远程rpc或者数据库调用,而实际结果是可以在线程内共享的, 7 | * 并供其他业务逻辑使用的。
8 | * 在调用发起点,构造闭包,延迟调用到验证逻辑中,同时该闭包缓存了结果对象,那么在调用发起点即可通过{@link #getResult()}获取结果对象。 9 | * 10 | * @author zhangxu 11 | */ 12 | public abstract class ClosureHandler implements Closure { 13 | 14 | /** 15 | * 是否完成了一次调用,避免重复调用{@link #execute(Object...)} 16 | */ 17 | private boolean hasExecute = false; 18 | 19 | @Override 20 | public void execute(Object... input) { 21 | if (hasExecute == true) { 22 | return; 23 | } 24 | doExecute(input); 25 | hasExecute = true; 26 | } 27 | 28 | /** 29 | * 实际闭包执行逻辑 30 | * 31 | * @param input the input to execute on 32 | */ 33 | public abstract void doExecute(Object... input); 34 | 35 | @Override 36 | public T executeAndGetResult(Object... input) { 37 | execute(input); 38 | return getResult(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ComplexResult.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 带有全信息的复杂验证结果 5 | * 6 | * @author zhangxu 7 | */ 8 | public class ComplexResult extends GenericResult { 9 | 10 | @Override 11 | public String toString() { 12 | return String.format("Result{isSuccess=%s, errors=%s, timeElapsedInMillis=%s}", isSuccess(), errors, 13 | timeElapsed); 14 | } 15 | 16 | private int timeElapsed; 17 | 18 | public int getTimeElapsed() { 19 | return timeElapsed; 20 | } 21 | 22 | public void setTimeElapsed(int timeElapsed) { 23 | this.timeElapsed = timeElapsed; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ComplexResult2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.Collections; 4 | 5 | /** 6 | * ComplexResult with errors of an empty list not a NULL 7 | * 8 | * @author zhangxu 9 | */ 10 | public class ComplexResult2 extends ComplexResult { 11 | 12 | public ComplexResult2() { 13 | errors = Collections.EMPTY_LIST; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/Composable.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 在Validator中添加额外的验证逻辑,用组合的方式 5 | * 6 | * @author zhangxu 7 | */ 8 | public interface Composable { 9 | 10 | /** 11 | * 切入点,可以织入一些校验逻辑 12 | * 13 | * @param current 当前的FluentValidator实例 14 | * @param context 验证器执行调用中的上下文 15 | * @param t 待验证的对象 16 | */ 17 | void compose(FluentValidator current, ValidatorContext context, T t); 18 | } 19 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/Const.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 一些静态常量 5 | * 6 | * @author zhangxu 7 | */ 8 | public class Const { 9 | 10 | /** 11 | * 默认初始容器大小 12 | */ 13 | public static final int INITIAL_CAPACITY = 4; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/DefaultValidateCallback.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.validator.element.ValidatorElementList; 6 | 7 | /** 8 | * 默认验证回调 9 | *

10 | * 如果不想实现{@link ValidateCallback}所有方法,可以使用这个默认实现,仅覆盖自己需要实现的方法 11 | * 12 | * @author zhangxu 13 | * @see ValidateCallback 14 | */ 15 | public class DefaultValidateCallback implements ValidateCallback { 16 | 17 | @Override 18 | public void onSuccess(ValidatorElementList validatorElementList) { 19 | } 20 | 21 | @Override 22 | public void onFail(ValidatorElementList validatorElementList, List errors) { 23 | } 24 | 25 | @Override 26 | public void onUncaughtException(Validator validator, Exception e, Object target) throws Exception { 27 | throw e; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/GenericResult.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 6 | 7 | /** 8 | * 错误结果模板抽象类 9 | *

10 | * 提供了一连串“惰性求值”计算后的“及时求值”收殓出口,泛型<T>代表结果类型 11 | * 12 | * @author zhangxu 13 | */ 14 | public abstract class GenericResult { 15 | 16 | /** 17 | * 是否验证成功,只要有一个失败就为false 18 | */ 19 | private boolean isSuccess; 20 | 21 | /** 22 | * 错误消息列表 23 | */ 24 | protected List errors; 25 | 26 | @Override 27 | public String toString() { 28 | return String.format("Result{isSuccess=%s, errors=%s}", isSuccess(), errors); 29 | } 30 | 31 | /** 32 | * 获取错误数量 33 | * 34 | * @return 错误数量 35 | */ 36 | public int getErrorNumber() { 37 | return CollectionUtil.isEmpty(errors) ? 0 : errors.size(); 38 | } 39 | 40 | public boolean isSuccess() { 41 | return isSuccess; 42 | } 43 | 44 | public void setIsSuccess(boolean isSuccess) { 45 | this.isSuccess = isSuccess; 46 | } 47 | 48 | public List getErrors() { 49 | return errors; 50 | } 51 | 52 | public void setErrors(List errors) { 53 | this.errors = errors; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/QuickValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.util.Decorator; 4 | 5 | 6 | /** 7 | * Quick validator for quickly executing template code like below: 8 | *

 9 |  * Result ret = FluentValidator.checkAll().configure(new SimpleRegistry())
10 |  *         .on(car)
11 |  *         .doValidate()
12 |  *         .result(toSimple());
13 |  * 
14 | * 15 | * @author zhangxu 16 | */ 17 | public class QuickValidator { 18 | 19 | /** 20 | * Execute validation by using a new FluentValidator instance with a shared context. 21 | * The result type is {@link ComplexResult} 22 | * 23 | * @param decorator Same as decorator design pattern, provided to add more functions to the fluentValidator 24 | * @param context Validation context which can be shared 25 | * @return ComplexResult 26 | */ 27 | public static ComplexResult doAndGetComplexResult(Decorator decorator, ValidatorContext context) { 28 | return validate(decorator, FluentValidator.checkAll(), context, ResultCollectors.toComplex()); 29 | } 30 | 31 | /** 32 | * Execute validation by using a new FluentValidator instance without a shared context. 33 | * The result type is {@link ComplexResult} 34 | * 35 | * @param decorator Same as decorator design pattern, provided to add more functions to the fluentValidator 36 | * @param context Validation context which can be shared 37 | * @return ComplexResult 38 | */ 39 | public static ComplexResult doAndGetComplexResult(Decorator decorator) { 40 | return validate(decorator, FluentValidator.checkAll(), null, ResultCollectors.toComplex()); 41 | } 42 | 43 | /** 44 | * Execute validation by using a new FluentValidator instance with a shared context. 45 | * The result type is {@link ComplexResult2} 46 | * 47 | * @param decorator Same as decorator design pattern, provided to add more functions to the fluentValidator 48 | * @param context Validation context which can be shared 49 | * @return ComplexResult2 50 | */ 51 | public static ComplexResult2 doAndGetComplexResult2(Decorator decorator, ValidatorContext context) { 52 | return validate(decorator, FluentValidator.checkAll(), context, ResultCollectors.toComplex2()); 53 | } 54 | 55 | /** 56 | * Execute validation by using a new FluentValidator instance and without a shared context. 57 | * The result type is {@link ComplexResult2} 58 | * 59 | * @param decorator Same as decorator design pattern, provided to add more functions to the fluentValidator 60 | * @return ComplexResult2 61 | */ 62 | public static ComplexResult2 doAndGetComplexResult2(Decorator decorator) { 63 | return validate(decorator, FluentValidator.checkAll(), null, ResultCollectors.toComplex2()); 64 | } 65 | 66 | /** 67 | * Use the decorator to add or attach more functions the given fluentValidator instance. 68 | *

69 | * The context can be shared and set up in the new FluentValidator instance. 70 | *

71 | * The motivation for this method is to provide a quick way to launch a validation task. By just passing 72 | * the validation logic which is wrapped inside the decorator, users can do validation in a ease way. 73 | *

74 | * Because Java7 lacks the ability to pass "action" to a method, so there is {@link Decorator} to help 75 | * to achieve a functional programming approach to get it done. In Java8, users can replace it with lambda. 76 | * 77 | * @param decorator Same as decorator design pattern, provided to add more functions to the fluentValidator 78 | * @param fluentValidator The base fluentValidator to be executed upon 79 | * @param context Validation context which can be shared 80 | * @param resultCollector Result collector 81 | * @return Result 82 | */ 83 | public static > T validate(Decorator decorator, FluentValidator fluentValidator, ValidatorContext context, ResultCollector resultCollector) { 84 | FluentValidator fv = decorator.decorate(fluentValidator); 85 | if (context != null) { 86 | fv.withContext(context); 87 | } 88 | 89 | T localResult = fv.failOver() 90 | .doValidate() 91 | .result(resultCollector); 92 | 93 | return localResult; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/Result.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 最简单的验证结果 5 | *

6 | * 作为{@link ResultCollectors#toSimple()}的结果泛型<T> 7 | * 8 | * @author zhangxu 9 | */ 10 | public class Result extends GenericResult { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ResultCollector.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 验证结果收集器 5 | *

6 | * 在FluentValidator.on(..).on(..).doValidate()这一连串“惰性求值”计算后的“及时求值”收殓出口, 8 | * 支持自定义的对外结果数据结构,泛型<T>代表结果类型 9 | *

10 | * 其思路类似于Java8中的java.util.stream.Collector,用于结合框架操作后的结果生成。 11 | *

12 |  *     List res = Stream.of("abc", "xyz", "hh").map(str -> str.toUpperCase()).collect(toList());
13 |  * 
14 | * 15 | * @author zhangxu 16 | */ 17 | public interface ResultCollector { 18 | 19 | /** 20 | * 转换为对外结果 21 | * 22 | * @param result 框架内部验证结果 23 | * 24 | * @return 对外验证结果对象 25 | */ 26 | T toResult(ValidationResult result); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ResultCollectors.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 4 | import com.baidu.unbiz.fluentvalidator.util.Function; 5 | import com.baidu.unbiz.fluentvalidator.util.Supplier; 6 | 7 | 8 | /** 9 | * 框架自身实现的一个简单的验证结果收集器 10 | * 11 | * @author zhangxu 12 | * @see ResultCollector 13 | * @see Result 14 | */ 15 | public class ResultCollectors { 16 | 17 | /** 18 | * 框架提供的一个简单结果收集器 19 | */ 20 | static class SimpleResultCollectorImpl implements ResultCollector { 21 | 22 | @Override 23 | public Result toResult(ValidationResult result) { 24 | Result ret = new Result(); 25 | if (result.isSuccess()) { 26 | ret.setIsSuccess(true); 27 | } else { 28 | ret.setIsSuccess(false); 29 | ret.setErrors(CollectionUtil.transform(result.getErrors(), new Function() { 30 | @Override 31 | public String apply(ValidationError input) { 32 | return input.getErrorMsg(); 33 | } 34 | })); 35 | } 36 | 37 | return ret; 38 | } 39 | } 40 | 41 | /** 42 | * 框架提供的一个复杂结果收集器 43 | */ 44 | static class ComplexResultCollectorImpl implements ResultCollector { 45 | 46 | @Override 47 | public ComplexResult toResult(ValidationResult result) { 48 | return newComplexResult(new Supplier() { 49 | @Override 50 | public ComplexResult get() { 51 | return new ComplexResult(); 52 | } 53 | }, result); 54 | } 55 | } 56 | 57 | /** 58 | * 框架提供的一个复杂结果收集器,结果对于NULL友好,即使没有任何错误{@link ComplexResult2#errors}也不会是NULL,而是一个empty list 59 | */ 60 | static class ComplexResult2CollectorImpl implements ResultCollector { 61 | 62 | @Override 63 | public ComplexResult2 toResult(ValidationResult result) { 64 | return newComplexResult(new Supplier() { 65 | @Override 66 | public ComplexResult2 get() { 67 | return new ComplexResult2(); 68 | } 69 | }, result); 70 | } 71 | } 72 | 73 | /** 74 | * {@link #toComplex()}和{@link #toComplex2()}复用的结果生成函数 75 | * 76 | * @param supplier 供给模板 77 | * @param result 内部用验证结果 78 | * @param 结果的泛型 79 | * @return 结果 80 | */ 81 | static T newComplexResult(Supplier supplier, ValidationResult result) { 82 | T ret = supplier.get(); 83 | if (result.isSuccess()) { 84 | ret.setIsSuccess(true); 85 | } else { 86 | ret.setIsSuccess(false); 87 | ret.setErrors(result.getErrors()); 88 | } 89 | 90 | ret.setTimeElapsed(result.getTimeElapsed()); 91 | return ret; 92 | } 93 | 94 | /** 95 | * 静态方法返回一个简单结果收集器 96 | * 97 | * @return 简单的结果收集器ResultCollectorImpl 98 | */ 99 | public static ResultCollector toSimple() { 100 | return new SimpleResultCollectorImpl(); 101 | } 102 | 103 | /** 104 | * 静态方法返回一个复杂结果收集器 105 | * 106 | * @return 简单的结果收集器ComplexResultCollectorImpl 107 | */ 108 | public static ResultCollector toComplex() { 109 | return new ComplexResultCollectorImpl(); 110 | } 111 | 112 | /** 113 | * 静态方法返回一个复杂结果收集器,结果对于NULL友好,即使没有任何错误{@link ComplexResult2#errors}也不会是NULL,而是一个empty list 114 | * 115 | * @return 简单的结果收集器ComplexResult2CollectorImpl 116 | */ 117 | public static ResultCollector toComplex2() { 118 | return new ComplexResult2CollectorImpl(); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidateCallback.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.validator.element.ValidatorElementList; 6 | 7 | /** 8 | * 验证回调接口 9 | *

10 | * 以参数形式参与{@link FluentValidator#doValidate(ValidateCallback)}来做验证过程中的回调操作。 11 | * 12 | * @author zhangxu 13 | */ 14 | public interface ValidateCallback { 15 | 16 | /** 17 | * 所有验证完成并且成功后 18 | * 19 | * @param validatorElementList 验证器list 20 | */ 21 | void onSuccess(ValidatorElementList validatorElementList); 22 | 23 | /** 24 | * 所有验证步骤结束,发现验证存在失败后 25 | * 26 | * @param validatorElementList 验证器list 27 | * @param errors 验证过程中发生的错误 28 | */ 29 | void onFail(ValidatorElementList validatorElementList, List errors); 30 | 31 | /** 32 | * 执行验证过程中发生了异常后 33 | * 34 | * @param validator 验证器 35 | * @param e 异常 36 | * @param target 正在验证的对象 37 | * 38 | * @throws Exception 39 | */ 40 | void onUncaughtException(Validator validator, Exception e, Object target) throws Exception; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidationError.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 内部使用的验证结果包含的错误 5 | * 6 | * @author zhangxu 7 | */ 8 | public class ValidationError { 9 | 10 | /** 11 | * 错误消息 12 | */ 13 | private String errorMsg; 14 | 15 | /** 16 | * 错误字段 17 | *

18 | * 举例来说,可以是普通的字段名也可以是一个OGNL表达式,例如: 19 | *

    20 | *
  • name
  • 21 | *
  • artist[0].gender
  • 22 | *
23 | */ 24 | private String field; 25 | 26 | /** 27 | * 错误码 28 | */ 29 | private int errorCode; 30 | 31 | /** 32 | * 错误值 33 | */ 34 | private Object invalidValue; 35 | 36 | @Override 37 | public String toString() { 38 | return "ValidationError{" + 39 | "errorCode=" + errorCode + 40 | ", errorMsg='" + errorMsg + '\'' + 41 | ", field='" + field + '\'' + 42 | ", invalidValue=" + invalidValue + 43 | '}'; 44 | } 45 | 46 | /** 47 | * 静态构造方法 48 | * 49 | * @param errorMsg 错误信息,其他信息可以省略,但是一个错误认为错误消息决不可少 50 | * 51 | * @return ValidationError 52 | */ 53 | public static ValidationError create(String errorMsg) { 54 | return new ValidationError().setErrorMsg(errorMsg); 55 | } 56 | 57 | public int getErrorCode() { 58 | return errorCode; 59 | } 60 | 61 | public ValidationError setErrorCode(int errorCode) { 62 | this.errorCode = errorCode; 63 | return this; 64 | } 65 | 66 | public String getErrorMsg() { 67 | return errorMsg; 68 | } 69 | 70 | public ValidationError setErrorMsg(String errorMsg) { 71 | this.errorMsg = errorMsg; 72 | return this; 73 | } 74 | 75 | public String getField() { 76 | return field; 77 | } 78 | 79 | public ValidationError setField(String field) { 80 | this.field = field; 81 | return this; 82 | } 83 | 84 | public Object getInvalidValue() { 85 | return invalidValue; 86 | } 87 | 88 | public ValidationError setInvalidValue(Object invalidValue) { 89 | this.invalidValue = invalidValue; 90 | return this; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidationResult.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.annotation.NotThreadSafe; 6 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 7 | 8 | /** 9 | * 内部用验证结果 10 | * 11 | * @author zhangxu 12 | * @see ValidationError 13 | */ 14 | @NotThreadSafe 15 | public class ValidationResult { 16 | 17 | /** 18 | * 是否成功,一旦发生错误,即置为false,默认为{@value} 19 | */ 20 | private boolean isSuccess = true; 21 | 22 | /** 23 | * 验证错误 24 | */ 25 | private List errors; 26 | 27 | /** 28 | * 验证总体耗时,指通过FluentValidator.doValidate(..)真正“及时求值”过程中的耗时 29 | */ 30 | private int timeElapsed; 31 | 32 | public boolean isSuccess() { 33 | return isSuccess; 34 | } 35 | 36 | public void setIsSuccess(boolean isSuccess) { 37 | this.isSuccess = isSuccess; 38 | } 39 | 40 | /** 41 | * 添加错误 42 | * 43 | * @param error 错误 44 | */ 45 | public void addError(ValidationError error) { 46 | if (CollectionUtil.isEmpty(errors)) { 47 | errors = CollectionUtil.createArrayList(Const.INITIAL_CAPACITY); 48 | } 49 | errors.add(error); 50 | } 51 | 52 | public List getErrors() { 53 | return errors; 54 | } 55 | 56 | public int getTimeElapsed() { 57 | return timeElapsed; 58 | } 59 | 60 | public void setTimeElapsed(int timeElapsed) { 61 | this.timeElapsed = timeElapsed; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/Validator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | /** 4 | * 验证器接口。 5 | *

6 | * 泛型T表示待验证对象的类型 7 | * 8 | * @author zhangxu 9 | */ 10 | public interface Validator { 11 | 12 | /** 13 | * 判断在该对象上是否接受或者需要验证 14 | *

15 | * 如果返回true,那么则调用{@link #validate(ValidatorContext, Object)},否则跳过该验证器 16 | * 17 | * @param context 验证上下文 18 | * @param t 待验证对象 19 | * 20 | * @return 是否接受验证 21 | */ 22 | boolean accept(ValidatorContext context, T t); 23 | 24 | /** 25 | * 执行验证 26 | *

27 | * 如果发生错误内部需要调用{@link ValidatorContext#addErrorMsg(String)}方法,也即context.addErrorMsg(String) 28 | * 来添加错误,该错误会被添加到结果存根{@link Result}的错误消息列表中。 29 | * 30 | * @param context 验证上下文 31 | * @param t 待验证对象 32 | * 33 | * @return 是否验证通过 34 | */ 35 | boolean validate(ValidatorContext context, T t); 36 | 37 | /** 38 | * 异常回调 39 | *

40 | * 当执行{@link #accept(ValidatorContext, Object)}或者{@link #validate(ValidatorContext, Object)}发生异常时的如何处理 41 | * 42 | * @param e 异常 43 | * @param context 验证上下文 44 | * @param t 待验证对象 45 | */ 46 | void onException(Exception e, ValidatorContext context, T t); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidatorChain.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 多个{@link Validator}组成的调用链 7 | * 8 | * @author zhangxu 9 | */ 10 | public class ValidatorChain { 11 | 12 | /** 13 | * 验证器list 14 | */ 15 | private List validators; 16 | 17 | /** 18 | * get validators 19 | * 20 | * @return validators 21 | */ 22 | public List getValidators() { 23 | return validators; 24 | } 25 | 26 | /** 27 | * set validators 28 | * 29 | * @param validators 30 | */ 31 | public void setValidators(List validators) { 32 | this.validators = validators; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "ValidatorChain{" + 38 | "validators=" + validators + 39 | '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidatorContext.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import java.util.Map; 4 | 5 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 6 | 7 | /** 8 | * 验证器执行调用中的上下文 9 | *

10 | * 在验证过程中{@link Validator#validate(ValidatorContext, Object)}以及{@link Validator#accept(ValidatorContext, 11 | * Object)}使用,主要用途在于: 12 | *

    13 | *
  • 1. 调用发起点可以放入一些变量或者对象,所有验证器均可以共享使用。
  • 14 | *
  • 2. 调用发起点可以做闭包,将一些验证过程中可以复用的结果对象缓存住(一般是比较耗时才可以获取到的),在发起点可以获取。
  • 15 | *
  • 3. 代理添加错误信息
  • 16 | *
17 | * 18 | * @author zhangxu 19 | * @see Closure 20 | * @see Result 21 | */ 22 | public class ValidatorContext { 23 | 24 | /** 25 | * 验证器均可以共享使用的属性键值对 26 | */ 27 | private Map attributes; 28 | 29 | /** 30 | * 调用发起点注入的闭包 31 | */ 32 | private Map closures; 33 | 34 | /** 35 | * 调用结果对象 36 | */ 37 | public ValidationResult result; 38 | 39 | /** 40 | * 添加错误信息 41 | * 42 | * @param msg 错误信息 43 | */ 44 | public void addErrorMsg(String msg) { 45 | result.addError(ValidationError.create(msg)); 46 | } 47 | 48 | /** 49 | * 添加错误信息 50 | * 51 | * @param validationError 验证错误 52 | */ 53 | public void addError(ValidationError validationError) { 54 | result.addError(validationError); 55 | } 56 | 57 | /** 58 | * 获取属性 59 | * 60 | * @param key 键 61 | * 62 | * @return 值 63 | */ 64 | public Object getAttribute(String key) { 65 | if (attributes != null && !attributes.isEmpty()) { 66 | return attributes.get(key); 67 | } 68 | return null; 69 | } 70 | 71 | /** 72 | * 根据类型T直接获取属性值 73 | * 74 | * @param key 键 75 | * @param clazz 值类型 76 | * 77 | * @return 值 78 | */ 79 | public T getAttribute(String key, Class clazz) { 80 | return (T) getAttribute(key); 81 | } 82 | 83 | public void setAttribute(String key, Object value) { 84 | if (attributes == null) { 85 | attributes = CollectionUtil.createHashMap(Const.INITIAL_CAPACITY); 86 | } 87 | attributes.put(key, value); 88 | } 89 | 90 | /** 91 | * 获取闭包 92 | * 93 | * @param key 闭包名称 94 | * 95 | * @return 闭包 96 | */ 97 | public Closure getClosure(String key) { 98 | if (closures != null && !closures.isEmpty()) { 99 | return closures.get(key); 100 | } 101 | return null; 102 | } 103 | 104 | /** 105 | * 注入闭包 106 | * 107 | * @param key 闭包名称 108 | * @param closure 闭包 109 | */ 110 | public void setClosure(String key, Closure closure) { 111 | if (closures == null) { 112 | closures = CollectionUtil.createHashMap(Const.INITIAL_CAPACITY); 113 | } 114 | closures.put(key, closure); 115 | } 116 | 117 | /** 118 | * 设置验证结果 119 | * 120 | * @param result 验证结果 121 | */ 122 | public void setResult(ValidationResult result) { 123 | this.result = result; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/ValidatorHandler.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.annotation.ThreadSafe; 4 | 5 | /** 6 | * 验证器默认实现 7 | *

8 | * 自定义的验证器如果不想实现{@link Validator}所有方法,可以使用这个默认实现,仅覆盖自己需要实现的方法 9 | * 10 | * @author zhangxu 11 | * @see Validator 12 | */ 13 | @ThreadSafe 14 | public class ValidatorHandler implements Validator, Composable { 15 | 16 | @Override 17 | public boolean accept(ValidatorContext context, T t) { 18 | return true; 19 | } 20 | 21 | @Override 22 | public boolean validate(ValidatorContext context, T t) { 23 | return true; 24 | } 25 | 26 | @Override 27 | public void onException(Exception e, ValidatorContext context, T t) { 28 | 29 | } 30 | 31 | @Override 32 | public void compose(FluentValidator current, ValidatorContext context, T t) { 33 | // extension point for clients to add more validators to the current fluent chain 34 | } 35 | 36 | /** 37 | * 验证器的名字,用简单类名称表示 38 | * 39 | * @return 名字 40 | */ 41 | @Override 42 | public String toString() { 43 | return this.getClass().getSimpleName(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/able/ListAble.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.able; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 可供转化为列表的接口 7 | * 8 | * @author zhangxu 9 | */ 10 | public interface ListAble { 11 | 12 | /** 13 | * 按照列表形态获取 14 | * 15 | * @return 列表 16 | */ 17 | List getAsList(); 18 | 19 | /** 20 | * 重写{@link #toString()}方法 21 | * 22 | * @return 字面输出含义 23 | */ 24 | String toString(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/able/ToStringable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.baidu.unbiz.fluentvalidator.able; 5 | 6 | /** 7 | * 重写 {@link #toString()}的接口 8 | * 9 | * @author zhangxu 10 | */ 11 | public interface ToStringable { 12 | 13 | /** 14 | * 字面输出含义 15 | * 16 | * @return 字面输出含义 17 | */ 18 | String toString(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/able/TransformTo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.baidu.unbiz.fluentvalidator.able; 5 | 6 | /** 7 | * 转换器 8 | * 9 | * @author zhangxu 10 | */ 11 | public interface TransformTo { 12 | 13 | /** 14 | * 将对象转换成TO类型 15 | * 16 | * @return 转换后的结果 17 | */ 18 | TO transform(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/able/Valuable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.baidu.unbiz.fluentvalidator.able; 5 | 6 | /** 7 | * 定义返回值接口,一般用于不能继承的对象,如枚举 8 | * 9 | * @author zhangxu 10 | */ 11 | public interface Valuable { 12 | 13 | /** 14 | * 取值 15 | * 16 | * @return the value 17 | */ 18 | T value(); 19 | } 20 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/annotation/FluentValid.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import com.baidu.unbiz.fluentvalidator.Validator; 10 | 11 | /** 12 | * 与Spring AOP配合,作用于参数用于表示验证。 13 | *

14 | * 作用于属性上,用于表示级联验证。 15 | * 16 | * @author zhangxu 17 | */ 18 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface FluentValid { 22 | 23 | /** 24 | * 验证器列表,接受{@link Validator}实现类的数组,除了级联外需要处理的额外验证 25 | */ 26 | Class[] value() default {}; 27 | 28 | /** 29 | * 作用于Spring AOP时候,用于标示分组验证,作于与属性时不起任何作用 30 | */ 31 | Class[] groups() default {}; 32 | 33 | /** 34 | * 作用于Spring AOP时候,用于标示分组验证,作于与属性时不起任何作用 35 | *

36 | * 和{@link #groups()}意义相反,设置了这个的就不会调用使用了{@link FluentValidate}注解的验证,对于hibernate无效 37 | */ 38 | Class[] excludeGroups() default {}; 39 | 40 | /** 41 | * 作用于Spring AOP时候,用于标示该参数验证是否启用failfast失败策略 42 | */ 43 | boolean isFailFast() default true; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/annotation/FluentValidate.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import com.baidu.unbiz.fluentvalidator.Validator; 10 | 11 | /** 12 | * 在类的属性级别加入此注解表示利用注解方式来进行验证 13 | *

14 | * 举例: 15 | *

16 |  * public class Car {
17 |  *
18 |  *     @FluentValidate({CarManufacturerValidator.class})
19 |  *     private String manufacturer;
20 |  *
21 |  *     @FluentValidate({CarLicensePlateValidator.class, CarLicensePlateValidator2.class})
22 |  *     private String licensePlate;
23 |  * }
24 |  * 
25 | * 26 | * @author zhangxu 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | @Documented 31 | public @interface FluentValidate { 32 | 33 | /** 34 | * 验证器列表,接受{@link Validator}实现类的数组 35 | */ 36 | Class[] value() default {}; 37 | 38 | /** 39 | * 分组验证,运行时只有在列表内的才验证 40 | * 41 | * @return 分组列表 42 | */ 43 | Class[] groups() default {}; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/annotation/NotThreadSafe.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 标记为非线程安全的注解,标示类或者方法不是必须线程安全实现的 11 | * 12 | * @author zhangxu 13 | */ 14 | @Target({ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface NotThreadSafe { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/annotation/Stateful.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 标记为有状态的,反义词为无状态的stateless 11 | * 12 | * @author zhangxu 13 | */ 14 | @Target({ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Stateful { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/annotation/ThreadSafe.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 标记为线程安全的注解,标示类或者方法必须是线程安全实现的 11 | * 12 | * @author zhangxu 13 | */ 14 | @Target({ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface ThreadSafe { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/exception/ClassInstantiationException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.exception; 2 | 3 | /** 4 | * 代表实例化类时失败的异常 5 | * 6 | * @author zhangxu 7 | */ 8 | public class ClassInstantiationException extends RuntimeException { 9 | 10 | public ClassInstantiationException() { 11 | } 12 | 13 | public ClassInstantiationException(String message) { 14 | super(message); 15 | } 16 | 17 | public ClassInstantiationException(String message, Throwable cause) { 18 | super(message, cause); 19 | } 20 | 21 | public ClassInstantiationException(Throwable cause) { 22 | super(cause); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/exception/RuntimeValidateException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.exception; 2 | 3 | /** 4 | * 验证器抛出运行时异常 5 | *

6 | * 所有验证过程中发生的异常会被这个运行时异常包装,验证调用点可以显示捕获,并且拿到内部的实际异常。一种典型的使用方法如下: 7 | *

 8 |  *     try {
 9 |  *         Result ret = FluentValidator.checkAll().failFast()
10 |  *             .on(car.getLicensePlate(), new CarLicensePlateValidator())
11 |  *             .doValidate().result(toSimple());
12 |  *     } catch (RuntimeValidateException e) {
13 |  *         assertThat(e.getCause().getMessage(), is("Call Rpc failed"));
14 |  *     }
15 |  * 
16 | * 17 | * @author zhangxu 18 | */ 19 | public class RuntimeValidateException extends RuntimeException { 20 | 21 | public RuntimeValidateException() { 22 | } 23 | 24 | public RuntimeValidateException(String message) { 25 | super(message); 26 | } 27 | 28 | public RuntimeValidateException(String message, Throwable cause) { 29 | super(message, cause); 30 | } 31 | 32 | public RuntimeValidateException(Throwable cause) { 33 | super(cause); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/registry/Registry.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.registry; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Bean注册查找器 7 | *

8 | * 框架内部的FluentValidator使用此接口来查找验证器Validator实例,可以看做通用的容器查找入口。 9 | * 简单的通过当前的ClassLoader通过反射初始化一个Validator实例,也可以选择使用Spring等IoC容器,使用ApplicationContext查找验证器Validator 11 | * 12 | * @author zhangxu 13 | */ 14 | public interface Registry { 15 | 16 | /** 17 | * 查找Bean 18 | * 19 | * @param type 类型 20 | * 21 | * @return 可找到的Bean的实例列表 22 | */ 23 | List findByType(Class type); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/registry/impl/SimpleRegistry.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.registry.impl; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.baidu.unbiz.fluentvalidator.exception.ClassInstantiationException; 9 | import com.baidu.unbiz.fluentvalidator.registry.Registry; 10 | import com.baidu.unbiz.fluentvalidator.util.ClassUtil; 11 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 12 | 13 | /** 14 | * {@link Registry}的一种简单实现,直接通过反射技术初始化一个Bean返回 15 | * 16 | * @author zhangxu 17 | */ 18 | public class SimpleRegistry implements Registry { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(SimpleRegistry.class); 21 | 22 | @Override 23 | public List findByType(Class type) { 24 | List ret = CollectionUtil.createArrayList(1); 25 | try { 26 | ret.add(ClassUtil.newInstance(type)); 27 | } catch (ClassInstantiationException e) { 28 | LOGGER.error("Failed to init " + type.getSimpleName()); 29 | } 30 | return ret; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/support/Computable.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | /** 6 | * 计算接口 7 | */ 8 | public interface Computable { 9 | 10 | /** 11 | * 通过关键字来计算 12 | * 13 | * @param key 查找关键字 14 | * @param callable # @see Callable 15 | * 16 | * @return 计算结果 17 | */ 18 | V get(K key, Callable callable); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/support/ConcurrentCache.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import java.util.concurrent.Callable; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.concurrent.ConcurrentMap; 6 | import java.util.concurrent.Future; 7 | import java.util.concurrent.FutureTask; 8 | 9 | /** 10 | * 此类不用额外使用自旋锁或者同步器,可保证并发时线程安全,在并发情况下具有高性能 11 | */ 12 | public class ConcurrentCache implements Computable { 13 | 14 | protected final ConcurrentMap> concurrentMap; 15 | 16 | public ConcurrentCache() { 17 | concurrentMap = new ConcurrentHashMap>(); 18 | } 19 | 20 | public static Computable createComputable() { 21 | return new ConcurrentCache(); 22 | } 23 | 24 | /** 25 | * 通过关键字获取数据,如果存在则直接返回,如果不存在,则通过计算callable来生成 26 | * 27 | * @param key 查找关键字 28 | * @param callable # @see Callable 29 | * 30 | * @return 计算结果 31 | */ 32 | public V get(K key, Callable callable) { 33 | Future future = concurrentMap.get(key); 34 | if (future == null) { 35 | FutureTask futureTask = new FutureTask(callable); 36 | future = concurrentMap.putIfAbsent(key, futureTask); 37 | if (future == null) { 38 | future = futureTask; 39 | futureTask.run(); 40 | } 41 | } 42 | try { 43 | // 此时阻塞 44 | return future.get(); 45 | } catch (Exception e) { 46 | concurrentMap.remove(key); 47 | return null; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/support/GroupingHolder.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | /** 4 | * 线程执行的上下文内容 5 | * 6 | * @author zhangxu 7 | */ 8 | public class GroupingHolder { 9 | 10 | /** 11 | * 线程上下文变量的持有者 12 | */ 13 | private static final ThreadLocal[]> CTX_HOLDER = new ThreadLocal[]>(); 14 | 15 | /** 16 | * 清空线程上下文 17 | */ 18 | public static final void clean() { 19 | CTX_HOLDER.set(null); 20 | } 21 | 22 | /** 23 | * 初始化线程上下文 24 | */ 25 | public static final void setGrouping(Class[] clazz) { 26 | CTX_HOLDER.set(clazz); 27 | } 28 | 29 | /** 30 | * 初始化线程上下文 31 | */ 32 | public static final Class[] getGrouping() { 33 | return CTX_HOLDER.get(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/ArrayUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | /** 6 | * 数组工具类 7 | * 8 | * @author zhangxu 9 | */ 10 | public class ArrayUtil { 11 | 12 | /** 13 | * 检查数组是否为null或空数组[]。 14 | *

15 | *

16 | *

 17 |      * ArrayUtil.isEmpty(null)              = true
 18 |      * ArrayUtil.isEmpty(new int[0])        = true
 19 |      * ArrayUtil.isEmpty(new int[10])       = false
 20 |      * 
21 | * 22 | * @param array 要检查的数组 23 | * 24 | * @return 如果不为空, 则返回true 25 | */ 26 | public static boolean isEmpty(T[] arrary) { 27 | return arrary == null || arrary.length == 0; 28 | } 29 | 30 | /** 31 | * 验证数组是否有交集 32 | *

33 | *

 34 |      * Class[] from = new Class[] {};
 35 |      * Class[] target = new Class[] {};
 36 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true));
 37 |      *
 38 |      * from = new Class[] {String.class};
 39 |      * target = new Class[] {};
 40 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true));
 41 |      *
 42 |      * from = new Class[] {};
 43 |      * target = new Class[] {String.class};
 44 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(false));
 45 |      *
 46 |      * from = new Class[] {String.class};
 47 |      * target = new Class[] {String.class};
 48 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true));
 49 |      *
 50 |      * from = new Class[] {String.class, Object.class};
 51 |      * target = new Class[] {String.class};
 52 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true));
 53 |      *
 54 |      * from = new Class[] {String.class};
 55 |      * target = new Class[] {String.class, Object.class};
 56 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true));
 57 |      *
 58 |      * from = new Class[] {Integer.class};
 59 |      * target = new Class[] {Object.class};
 60 |      * assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(false));
 61 |      *
 62 |      * 
63 | * 64 | * @param from 基础数组 65 | * @param target 目标数组,看是否存在于基础数组中 66 | * 67 | * @return 如果有交集, 则返回true 68 | */ 69 | public static boolean hasIntersection(T[] from, T[] target) { 70 | if (isEmpty(target)) { 71 | return true; 72 | } 73 | 74 | if (isEmpty(from)) { 75 | return false; 76 | } 77 | 78 | for (int i = 0; i < from.length; i++) { 79 | for (int j = 0; j < target.length; j++) { 80 | if (from[i] == target[j]) { 81 | return true; 82 | } 83 | } 84 | } 85 | return false; 86 | } 87 | 88 | /** 89 | * 将数组转变成数组,如果fromsnull,则返回null
90 | * 如果froms不为基本类型数组,则返回null 91 | * 92 | * @param froms 基本类型数组 93 | * 94 | * @return 包装类数组,如果fromsnull,则返回null
95 | * 如果froms不为基本类型数组,则返回null 96 | */ 97 | public static T[] toWrapperIfPrimitive(Object froms) { 98 | if (froms == null) { 99 | return null; 100 | } 101 | 102 | Class type = froms.getClass().getComponentType(); 103 | if (!type.isPrimitive()) { 104 | return (T[]) froms; 105 | } 106 | 107 | PrimitiveWrapperArray transformTo = PrimitiveWrapperArray.find(froms.getClass()); 108 | if (transformTo == null) { 109 | return null; 110 | } 111 | 112 | int size = Array.getLength(froms); 113 | T[] result = (T[]) Array.newInstance(ClassUtil.getWrapperTypeIfPrimitive(type), size); 114 | 115 | for (int i = 0; i < size; i++) { 116 | T value = (T) Array.get(froms, i); 117 | result[i] = value; 118 | } 119 | 120 | return result; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.baidu.unbiz.fluentvalidator.exception.ClassInstantiationException; 7 | 8 | /** 9 | * 类工具 10 | * 11 | * @author zhangxu 12 | */ 13 | public class ClassUtil { 14 | 15 | /** 16 | * 创建指定类的实例。 17 | * 18 | * @param clazz 要创建实例的类 19 | * 20 | * @return 指定类的实例 21 | * 22 | * @throws ClassInstantiationException 如果实例化失败 23 | */ 24 | public static T newInstance(Class clazz) throws ClassInstantiationException { 25 | if (clazz == null) { 26 | return null; 27 | } 28 | 29 | try { 30 | return clazz.newInstance(); 31 | } catch (Exception e) { 32 | throw new ClassInstantiationException("Failed to instantiate class: " + clazz.getName(), e); 33 | } 34 | } 35 | 36 | public static Class getWrapperTypeIfPrimitive(Class type) { 37 | if (type == null) { 38 | return null; 39 | } 40 | 41 | if (type.isPrimitive()) { 42 | return ((PrimitiveInfo) PRIMITIVES.get(type.getName())).wrapperType; 43 | } 44 | 45 | return type; 46 | } 47 | 48 | private static final Map> PRIMITIVES = new HashMap>(13); 49 | 50 | static { 51 | addPrimitive(boolean.class, "Z", Boolean.class, "booleanValue", false, Boolean.FALSE, Boolean.TRUE); 52 | addPrimitive(short.class, "S", Short.class, "shortValue", (short) 0, Short.MAX_VALUE, Short.MIN_VALUE); 53 | addPrimitive(int.class, "I", Integer.class, "intValue", 0, Integer.MAX_VALUE, Integer.MIN_VALUE); 54 | addPrimitive(long.class, "J", Long.class, "longValue", 0L, Long.MAX_VALUE, Long.MIN_VALUE); 55 | addPrimitive(float.class, "F", Float.class, "floatValue", 0F, Float.MAX_VALUE, Float.MIN_VALUE); 56 | addPrimitive(double.class, "D", Double.class, "doubleValue", 0D, Double.MAX_VALUE, Double.MIN_VALUE); 57 | addPrimitive(char.class, "C", Character.class, "charValue", '\0', Character.MAX_VALUE, Character.MIN_VALUE); 58 | addPrimitive(byte.class, "B", Byte.class, "byteValue", (byte) 0, Byte.MAX_VALUE, Byte.MIN_VALUE); 59 | addPrimitive(void.class, "V", Void.class, null, null, null, null); 60 | } 61 | 62 | private static void addPrimitive(Class type, String typeCode, Class wrapperType, String unwrapMethod, 63 | T defaultValue, T maxValue, T minValue) { 64 | PrimitiveInfo info = 65 | new PrimitiveInfo(type, typeCode, wrapperType, unwrapMethod, defaultValue, maxValue, minValue); 66 | 67 | PRIMITIVES.put(type.getName(), info); 68 | PRIMITIVES.put(wrapperType.getName(), info); 69 | } 70 | 71 | /** 72 | * 代表一个primitive类型的信息。 73 | */ 74 | private static class PrimitiveInfo { 75 | final Class type; 76 | @SuppressWarnings("unused") 77 | final String typeCode; 78 | final Class wrapperType; 79 | @SuppressWarnings("unused") 80 | final String unwrapMethod; 81 | final T defaultValue; 82 | final T maxValue; 83 | final T minValue; 84 | 85 | public PrimitiveInfo(Class type, String typeCode, Class wrapperType, String unwrapMethod, T defaultValue, 86 | T maxValue, T minValue) { 87 | this.type = type; 88 | this.typeCode = typeCode; 89 | this.wrapperType = wrapperType; 90 | this.unwrapMethod = unwrapMethod; 91 | this.defaultValue = defaultValue; 92 | this.maxValue = maxValue; 93 | this.minValue = minValue; 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/CollectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.Collections; 6 | import java.util.HashMap; 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | /** 11 | * 集合框架工具类 12 | * 13 | * @author zhangxu 14 | */ 15 | public class CollectionUtil { 16 | 17 | /** 18 | * 创建ArrayList实例 19 | * 20 | * @param 21 | * 22 | * @return ArrayList实例 23 | */ 24 | public static ArrayList createArrayList() { 25 | return new ArrayList(); 26 | } 27 | 28 | /** 29 | * 创建ArrayList实例 30 | * 31 | * @param 32 | * @param initialCapacity 初始化容量 33 | * 34 | * @return ArrayList实例 35 | */ 36 | public static ArrayList createArrayList(int initialCapacity) { 37 | return new ArrayList(initialCapacity); 38 | } 39 | 40 | /** 41 | * 创建LinkedList实例 42 | * 43 | * @param 44 | * 45 | * @return LinkedList实例 46 | */ 47 | public static LinkedList createLinkedList() { 48 | return new LinkedList(); 49 | } 50 | 51 | /** 52 | * 创建HashMap实例 53 | * 54 | * @param 55 | * @param 56 | * @param initialCapacity 初始化容量 57 | * 58 | * @return HashMap实例 59 | */ 60 | public static HashMap createHashMap(int initialCapacity) { 61 | return new HashMap(initialCapacity); 62 | } 63 | 64 | /** 65 | * 判断Collection是否为null或空数组[]。 66 | * 67 | * @param collection 68 | * 69 | * @return 如果为空, 则返回true 70 | * 71 | * @see Collection 72 | */ 73 | public static boolean isEmpty(Collection collection) { 74 | return (collection == null) || (collection.size() == 0); 75 | } 76 | 77 | /** 78 | * 列表转换 79 | * 80 | * @param fromList 源列表 81 | * @param function 转换函数 82 | * 83 | * @return 新列表 84 | * 85 | * @see Function 86 | */ 87 | public static List transform(Collection fromList, Function function) { 88 | if (CollectionUtil.isEmpty(fromList)) { 89 | return Collections.emptyList(); 90 | } 91 | 92 | List ret = new ArrayList(fromList.size()); 93 | for (F f : fromList) { 94 | T t = function.apply(f); 95 | if (t == null) { 96 | continue; 97 | } 98 | ret.add(t); 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/Decorator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 4 | 5 | /** 6 | * Fluent validator decorator, same as decorator design pattern 7 | * 8 | * @author zhangxu 9 | */ 10 | public interface Decorator { 11 | 12 | /** 13 | * Decorate one FluentValidator and return the new instance. 14 | * 15 | * @param fv FluentValidator 16 | * @return Decorated FluentValidator 17 | */ 18 | FluentValidator decorate(FluentValidator fv); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/Function.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | /** 4 | * Determines an output value based on an input value. 5 | * 6 | * @author zhangxu 7 | */ 8 | public interface Function { 9 | 10 | /** 11 | * Returns the result of applying this function to {@code input}. 12 | */ 13 | T apply(F input); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/PrimitiveWrapperArray.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.baidu.unbiz.fluentvalidator.util; 5 | 6 | import com.baidu.unbiz.fluentvalidator.able.TransformTo; 7 | import com.baidu.unbiz.fluentvalidator.able.Valuable; 8 | 9 | /** 10 | * @author xuc 11 | * @version create on 2014年9月22日 下午11:17:44 12 | */ 13 | public enum PrimitiveWrapperArray implements Valuable>, TransformTo> { 14 | 15 | PRIMITIVE_BOOLEAN { 16 | @Override 17 | public Class value() { 18 | return boolean[].class; 19 | } 20 | 21 | @Override 22 | public Class transform() { 23 | return Boolean[].class; 24 | } 25 | }, 26 | PRIMITIVE_BYTE { 27 | @Override 28 | public Class value() { 29 | return byte[].class; 30 | } 31 | 32 | @Override 33 | public Class transform() { 34 | return Byte[].class; 35 | } 36 | }, 37 | PRIMITIVE_CHAR { 38 | @Override 39 | public Class value() { 40 | return char[].class; 41 | } 42 | 43 | @Override 44 | public Class transform() { 45 | return Character[].class; 46 | } 47 | }, 48 | PRIMITIVE_SHORT { 49 | @Override 50 | public Class value() { 51 | return short[].class; 52 | } 53 | 54 | @Override 55 | public Class transform() { 56 | return Short[].class; 57 | } 58 | }, 59 | PRIMITIVE_INT { 60 | @Override 61 | public Class value() { 62 | return int[].class; 63 | } 64 | 65 | @Override 66 | public Class transform() { 67 | return Integer[].class; 68 | } 69 | }, 70 | PRIMITIVE_LONG { 71 | @Override 72 | public Class value() { 73 | return long[].class; 74 | } 75 | 76 | @Override 77 | public Class transform() { 78 | return Long[].class; 79 | } 80 | }, 81 | PRIMITIVE_FLOAT { 82 | @Override 83 | public Class value() { 84 | return float[].class; 85 | } 86 | 87 | @Override 88 | public Class transform() { 89 | return Float[].class; 90 | } 91 | }, 92 | PRIMITIVE_DOUBLE { 93 | @Override 94 | public Class value() { 95 | return double[].class; 96 | } 97 | 98 | @Override 99 | public Class transform() { 100 | return Double[].class; 101 | } 102 | }, 103 | 104 | WRAPPER_BOOLEAN { 105 | @Override 106 | public Class value() { 107 | return Boolean[].class; 108 | } 109 | 110 | @Override 111 | public Class transform() { 112 | return boolean[].class; 113 | } 114 | }, 115 | WRAPPER_BYTE { 116 | @Override 117 | public Class value() { 118 | return Byte[].class; 119 | } 120 | 121 | @Override 122 | public Class transform() { 123 | return byte[].class; 124 | } 125 | }, 126 | WRAPPER_CHAR { 127 | @Override 128 | public Class value() { 129 | return Character[].class; 130 | } 131 | 132 | @Override 133 | public Class transform() { 134 | return char[].class; 135 | } 136 | }, 137 | WRAPPER_SHORT { 138 | @Override 139 | public Class value() { 140 | return Short[].class; 141 | } 142 | 143 | @Override 144 | public Class transform() { 145 | return short[].class; 146 | } 147 | }, 148 | WRAPPER_INT { 149 | @Override 150 | public Class value() { 151 | return Integer[].class; 152 | } 153 | 154 | @Override 155 | public Class transform() { 156 | return int[].class; 157 | } 158 | }, 159 | WRAPPER_LONG { 160 | @Override 161 | public Class value() { 162 | return Long[].class; 163 | } 164 | 165 | @Override 166 | public Class transform() { 167 | return long[].class; 168 | } 169 | }, 170 | WRAPPER_FLOAT { 171 | @Override 172 | public Class value() { 173 | return Float[].class; 174 | } 175 | 176 | @Override 177 | public Class transform() { 178 | return float[].class; 179 | } 180 | }, 181 | WRAPPER_DOUBLE { 182 | @Override 183 | public Class value() { 184 | return Double[].class; 185 | } 186 | 187 | @Override 188 | public Class transform() { 189 | return double[].class; 190 | } 191 | }; 192 | 193 | public static PrimitiveWrapperArray find(Class clazz) { 194 | for (PrimitiveWrapperArray primitiveArray : PrimitiveWrapperArray.values()) { 195 | if (primitiveArray.value() == clazz) { 196 | return primitiveArray; 197 | } 198 | } 199 | 200 | return null; 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Method; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import com.baidu.unbiz.fluentvalidator.exception.RuntimeValidateException; 10 | 11 | /** 12 | * 反射工具类 13 | * 14 | * @author zhangxu 15 | */ 16 | public class ReflectionUtil { 17 | 18 | /** 19 | * 要求参数不为null 20 | *

21 | * 获取类及父类的所有Field,不包括ObjectField 22 | * 23 | * @param clazz 要获取的类 24 | * 25 | * @return Field列表 26 | */ 27 | static List getAllFieldsOfClass0(Class clazz) { 28 | List fields = CollectionUtil.createArrayList(); 29 | for (Class itr = clazz; hasSuperClass(itr); ) { 30 | fields.addAll(Arrays.asList(itr.getDeclaredFields())); 31 | itr = itr.getSuperclass(); 32 | } 33 | 34 | return fields; 35 | } 36 | 37 | /** 38 | * 获取所有包含指定AnnotationField数组 39 | * 40 | * @param clazz 查找类 41 | * @param annotationClass 注解类名 42 | * 43 | * @return Field数组 44 | */ 45 | public static Field[] getAnnotationFields(Class clazz, Class annotationClass) { 46 | if (clazz == null || annotationClass == null) { 47 | return null; 48 | } 49 | 50 | List fields = getAllFieldsOfClass0(clazz); 51 | if (CollectionUtil.isEmpty(fields)) { 52 | return null; 53 | } 54 | 55 | List list = CollectionUtil.createArrayList(); 56 | for (Field field : fields) { 57 | if (null != field.getAnnotation(annotationClass)) { 58 | list.add(field); 59 | field.setAccessible(true); 60 | } 61 | } 62 | 63 | return list.toArray(new Field[0]); 64 | } 65 | 66 | /** 67 | * 获取Field上的注解 68 | * 69 | * @param field 属性 70 | * @param annotationType 注解类型 71 | * 72 | * @return 注解对象 73 | */ 74 | public static A getAnnotation(Field field, Class annotationType) { 75 | if (field == null || annotationType == null) { 76 | return null; 77 | } 78 | 79 | return field.getAnnotation(annotationType); 80 | } 81 | 82 | /** 83 | * 判断是否有超类 84 | * 85 | * @param clazz 目标类 86 | * 87 | * @return 如果有返回true,否则返回false 88 | */ 89 | public static boolean hasSuperClass(Class clazz) { 90 | return (clazz != null) && !clazz.equals(Object.class); 91 | } 92 | 93 | /** 94 | * getter方法的前缀 95 | */ 96 | private static final String GETTER_METHOD_PREFIX = "get"; 97 | 98 | /** 99 | * boolean类型属性getter方法的前缀 100 | */ 101 | private static final String GETTER_METHOD_PREFIX_FOR_BOOLEAN = "is"; 102 | 103 | /** 104 | * 获取getter方法 105 | * 106 | * @param clazz 类 107 | * @param field 属性 108 | * 109 | * @return getter方法 110 | */ 111 | public static Method getGetterMethod(Class clazz, Field field) { 112 | return getMethod(clazz, getGetterMethodName(field)); 113 | } 114 | 115 | /** 116 | * 获取getter方法名 117 | * 118 | * @param field 属性 119 | * 120 | * @return getter方法名 121 | */ 122 | public static String getGetterMethodName(Field field) { 123 | String prefix; 124 | String fieldName = field.getName(); 125 | if (field.getType() != boolean.class || field.getType() != Boolean.class) { 126 | prefix = GETTER_METHOD_PREFIX; 127 | } else { 128 | prefix = GETTER_METHOD_PREFIX_FOR_BOOLEAN; 129 | } 130 | return prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 131 | } 132 | 133 | /** 134 | * 获取方法 135 | * 136 | * @param clazz 类 137 | * @param methodName 方法名 138 | * @param parameterTypes 方法参数 139 | * 140 | * @return 方法 141 | */ 142 | public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) { 143 | if (clazz == null || methodName == null || methodName.length() == 0) { 144 | return null; 145 | } 146 | 147 | for (Class itr = clazz; hasSuperClass(itr); ) { 148 | Method[] methods = itr.getDeclaredMethods(); 149 | 150 | for (Method method : methods) { 151 | if (method.getName().equals(methodName) && Arrays.equals(method.getParameterTypes(), parameterTypes)) { 152 | return method; 153 | } 154 | } 155 | 156 | itr = itr.getSuperclass(); 157 | } 158 | return null; 159 | } 160 | 161 | /** 162 | * 方法调用,如果clazznull,返回null; 163 | *

164 | * 如果methodnull,返回null 165 | *

166 | * 如果targetnull,则为静态方法 167 | * 168 | * @param method 调用的方法 169 | * @param target 目标对象 170 | * @param args 方法的参数值 171 | * 172 | * @return 调用结果 173 | */ 174 | public static T invokeMethod(Method method, Object target, Object... args) { 175 | if (method == null) { 176 | return null; 177 | } 178 | 179 | method.setAccessible(true); 180 | try { 181 | @SuppressWarnings("unchecked") 182 | T result = (T) method.invoke(target, args); 183 | return result; 184 | } catch (Exception e) { 185 | throw new RuntimeValidateException(e); 186 | } 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/util/Supplier.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | /** 4 | * Represents a supplier of results. 5 | * 6 | * @author zhangxu 7 | */ 8 | public interface Supplier { 9 | 10 | /** 11 | * Gets a result. 12 | */ 13 | T get(); 14 | } 15 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/validator/element/IterableValidatorElement.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator.element; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Const; 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.able.ListAble; 8 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 9 | 10 | /** 11 | * 集合或者列表、数组使用一个验证器验证时候的可遍历元素 12 | * 13 | * @author zhangxu 14 | * @see ValidatorElementComposite 15 | */ 16 | public class IterableValidatorElement extends ValidatorElementComposite implements ListAble { 17 | 18 | public IterableValidatorElement(List validatorElements) { 19 | super(validatorElements); 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | if (CollectionUtil.isEmpty(validatorElements)) { 25 | return "Empty iterable validator elements"; 26 | } 27 | return String.format("Total %d of %s", size(), validatorElements.get(0)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/validator/element/MultiValidatorElement.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator.element; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Const; 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.able.ListAble; 8 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 9 | 10 | /** 11 | * 一个对象上进行多个验证器验证的元素 12 | * 13 | * @author zhangxu 14 | * @see ValidatorElementComposite 15 | */ 16 | public class MultiValidatorElement extends ValidatorElementComposite implements ListAble { 17 | 18 | public MultiValidatorElement(List validatorElements) { 19 | super(validatorElements); 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | if (CollectionUtil.isEmpty(validatorElements)) { 25 | return "[]"; 26 | } 27 | return validatorElements.toString(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/validator/element/ValidatorElement.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator.element; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.Validator; 8 | import com.baidu.unbiz.fluentvalidator.able.ListAble; 9 | import com.baidu.unbiz.fluentvalidator.able.ToStringable; 10 | 11 | /** 12 | * 在{@link FluentValidator}内部调用使用的验证器链包装类 13 | * 14 | * @author zhangxu 15 | */ 16 | public class ValidatorElement implements ListAble { 17 | 18 | /** 19 | * 验证器 20 | */ 21 | private Validator validator; 22 | 23 | /** 24 | * 待验证对象 25 | */ 26 | private Object target; 27 | 28 | /** 29 | * 自定义的打印信息回调 30 | */ 31 | private ToStringable customizedToString; 32 | 33 | /** 34 | * create 35 | * 36 | * @param target 待验证对象 37 | * @param validator 验证器 38 | */ 39 | public ValidatorElement(Object target, Validator validator) { 40 | this.target = target; 41 | this.validator = validator; 42 | } 43 | 44 | /** 45 | * create 46 | * 47 | * @param target 待验证对象 48 | * @param validator 验证器 49 | * @param customizedToString 自定义的打印信息回调 50 | */ 51 | public ValidatorElement(Object target, Validator validator, 52 | ToStringable customizedToString) { 53 | this.target = target; 54 | this.validator = validator; 55 | this.customizedToString = customizedToString; 56 | } 57 | 58 | public Object getTarget() { 59 | return target; 60 | } 61 | 62 | public Validator getValidator() { 63 | return validator; 64 | } 65 | 66 | @Override 67 | public List getAsList() { 68 | return Arrays.asList(this); 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | if (customizedToString != null) { 74 | return customizedToString.toString(); 75 | } 76 | return String.format("%s@%s", target == null ? "null" : target.getClass().getSimpleName(), validator); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/validator/element/ValidatorElementComposite.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator.element; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Const; 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.able.ListAble; 8 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 9 | 10 | /** 11 | * 在{@link FluentValidator}内部调用使用的验证器链包装类,用于以下两种场景: 12 | *

16 | * 17 | * @author zhangxu 18 | */ 19 | public abstract class ValidatorElementComposite implements ListAble { 20 | 21 | /** 22 | * 待验证对象机器验证器列表 23 | */ 24 | protected List validatorElements; 25 | 26 | /** 27 | * Create 28 | * 29 | * @param validatorElements 待验证对象机器验证器列表 30 | */ 31 | public ValidatorElementComposite(List validatorElements) { 32 | this.validatorElements = validatorElements; 33 | } 34 | 35 | /** 36 | * 列表长度 37 | * 38 | * @return 长度 39 | */ 40 | public int size() { 41 | if (CollectionUtil.isEmpty(validatorElements)) { 42 | return 0; 43 | } 44 | return validatorElements.size(); 45 | } 46 | 47 | @Override 48 | public abstract String toString(); 49 | 50 | @Override 51 | public List getAsList() { 52 | return validatorElements; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /fluent-validator/src/main/java/com/baidu/unbiz/fluentvalidator/validator/element/ValidatorElementList.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator.element; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | import com.baidu.unbiz.fluentvalidator.FluentValidator; 7 | import com.baidu.unbiz.fluentvalidator.able.ListAble; 8 | import com.baidu.unbiz.fluentvalidator.util.CollectionUtil; 9 | 10 | /** 11 | * 在{@link FluentValidator}内部调用使用的验证器链 12 | * 13 | * @author zhangxu 14 | */ 15 | public class ValidatorElementList { 16 | 17 | /** 18 | * 待验证对象及其验证器链表 19 | */ 20 | private LinkedList> validatorElementLinkedList = CollectionUtil.createLinkedList(); 21 | 22 | /** 23 | * 加入待验证对象及其验证器 24 | * 25 | * @param listAble 待验证对象及其验证器封装类 26 | */ 27 | public void add(ListAble listAble) { 28 | this.validatorElementLinkedList.add(listAble); 29 | } 30 | 31 | /** 32 | * 获取待验证对象及其验证器链表长度 33 | * 34 | * @return 联调长度 35 | */ 36 | public int size() { 37 | return validatorElementLinkedList.size(); 38 | } 39 | 40 | /** 41 | * 获取验证器链 42 | * 43 | * @return 验证器链 44 | */ 45 | public LinkedList> getList() { 46 | return validatorElementLinkedList; 47 | } 48 | 49 | /** 50 | * 验证器链是否为空 51 | * 52 | * @return 是否为空 53 | */ 54 | public boolean isEmpty() { 55 | return validatorElementLinkedList.isEmpty(); 56 | } 57 | 58 | /** 59 | * 获取验证器链 60 | * 61 | * @return 验证器链 62 | */ 63 | public List getAllValidatorElements() { 64 | List ret = CollectionUtil.createArrayList(); 65 | for (ListAble e : validatorElementLinkedList) { 66 | ret.addAll(e.getAsList()); 67 | } 68 | return ret; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | int count = 0; 75 | for (ListAble e : validatorElementLinkedList) { 76 | if (count >= 20) { 77 | sb.append("["); 78 | sb.append(size() - count); 79 | sb.append("... more]->"); 80 | break; 81 | } 82 | sb.append("["); 83 | sb.append(e); 84 | sb.append("]->"); 85 | count++; 86 | } 87 | sb.append("NULL"); 88 | return sb.toString(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/FluentValidatorClassTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 4 | import static org.hamcrest.CoreMatchers.nullValue; 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import com.baidu.unbiz.fluentvalidator.dto.Garage; 12 | import com.google.common.collect.Lists; 13 | import org.junit.Test; 14 | 15 | import com.baidu.unbiz.fluentvalidator.dto.Car; 16 | import com.baidu.unbiz.fluentvalidator.rpc.ManufacturerService; 17 | import com.baidu.unbiz.fluentvalidator.rpc.impl.ManufacturerServiceImpl; 18 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator; 19 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator2; 20 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator3; 21 | 22 | /** 23 | * @author zhangxu 24 | */ 25 | public class FluentValidatorClassTest { 26 | 27 | private ManufacturerService manufacturerService = new ManufacturerServiceImpl(); 28 | 29 | /** 30 | * The following are tested: 31 | * 1) validator chain 32 | * 2) closure 33 | * 3) on wrapper class, not specific fields 34 | */ 35 | @Test 36 | public void testPutClosure2Context() { 37 | Car car = getValidCar(); 38 | 39 | Closure> closure = new ClosureHandler>() { 40 | 41 | private List allManufacturers; 42 | 43 | @Override 44 | public List getResult() { 45 | return allManufacturers; 46 | } 47 | 48 | @Override 49 | public void doExecute(Object... input) { 50 | allManufacturers = manufacturerService.getAllManufacturers(); 51 | } 52 | }; 53 | 54 | System.out.println(closure.getResult()); 55 | assertThat(closure.getResult(), nullValue()); 56 | 57 | ValidatorChain chain = new ValidatorChain(); 58 | List validators = new ArrayList(); 59 | validators.add(new CarValidator()); 60 | validators.add(new CarValidator2()); 61 | validators.add(new CarValidator3()); 62 | chain.setValidators(validators); 63 | 64 | Result ret = FluentValidator.checkAll() 65 | .putClosure2Context("manufacturerClosure", closure) 66 | .on(car, chain) 67 | .doValidate().result(toSimple()); 68 | System.out.println(ret); 69 | assertThat(ret.isSuccess(), is(true)); 70 | 71 | System.out.println(closure.getResult()); 72 | assertThat(closure.getResult().size(), is(3)); 73 | } 74 | 75 | @Test 76 | public void testCompose() { 77 | Garage garage = getGarage(); 78 | garage.setStr(""); 79 | garage.getCollectionCar().get(0).setLicensePlate("OUT_OF_NO_WHERE"); 80 | garage.getCollectionCar().get(2).setSeatCount(-1); 81 | 82 | Result ret = FluentValidator.checkAll() 83 | .on(garage, new GarageValidator()) 84 | .failOver() 85 | .doValidate() 86 | .result(toSimple()); 87 | System.out.println(ret); 88 | assertThat(ret.isSuccess(), is(false)); 89 | assertThat(ret.getErrorNumber(), is(3)); 90 | assertThat(ret.getErrors().get(0), is("License is not valid, invalid value=OUT_OF_NO_WHERE")); 91 | assertThat(ret.getErrors().get(1), is("Seat count is not valid, invalid value=-1")); 92 | assertThat(ret.getErrors().get(2), is("garage string can not be empty")); 93 | } 94 | 95 | class GarageValidator extends ValidatorHandler implements Validator { 96 | 97 | @Override 98 | public boolean validate(ValidatorContext context, Garage garage) { 99 | if ("".equals(garage.getStr())) { 100 | context.addErrorMsg("garage string can not be empty"); 101 | return false; 102 | } 103 | return true; 104 | } 105 | 106 | @Override 107 | public void compose(FluentValidator current, ValidatorContext context, Garage garage) { 108 | current.onEach(garage.getCollectionCar(), new CarValidator2()) 109 | .onEach(garage.getCollectionCar(), new CarValidator3()); 110 | } 111 | } 112 | 113 | private Garage getGarage() { 114 | Garage garage = new Garage(); 115 | garage.setCollectionCar(getValidCars()); 116 | garage.setArrayCar(getValidCars().toArray(new Car[]{})); 117 | garage.setSingleCar(getValidCar()); 118 | garage.setStr("abc"); 119 | return garage; 120 | } 121 | 122 | private List getValidCars() { 123 | return Lists.newArrayList(new Car("BMW", "LA1234", 5), 124 | new Car("Benz", "NYCuuu", 2), 125 | new Car("Chevrolet", "LA1234", 7)); 126 | } 127 | 128 | private Car getValidCar() { 129 | return new Car("BMW", "LA1234", 5); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/FluentValidatorOnEachTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator; 2 | 3 | import static com.baidu.unbiz.fluentvalidator.ResultCollectors.toSimple; 4 | import static org.hamcrest.core.Is.is; 5 | import static org.junit.Assert.assertThat; 6 | 7 | import java.util.List; 8 | 9 | import org.junit.Test; 10 | 11 | import com.baidu.unbiz.fluentvalidator.dto.Car; 12 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator; 13 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator2; 14 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator3; 15 | import com.google.common.collect.Lists; 16 | 17 | /** 18 | * @author zhangxu 19 | */ 20 | public class FluentValidatorOnEachTest { 21 | 22 | @Test 23 | public void testCarCollection() { 24 | List cars = getValidCars(); 25 | 26 | Result ret = FluentValidator.checkAll() 27 | .onEach(cars, new CarValidator()) 28 | .onEach(cars, new CarValidator2()) 29 | .onEach(cars, new CarValidator3()) 30 | .doValidate() 31 | .result(toSimple()); 32 | System.out.println(ret); 33 | assertThat(ret.isSuccess(), is(true)); 34 | } 35 | 36 | @Test 37 | public void testCarCollectionNegative() { 38 | List cars = getValidCars(); 39 | cars.get(0).setSeatCount(0); 40 | cars.get(1).setLicensePlate("hehe"); 41 | 42 | Result ret = FluentValidator.checkAll().failOver() 43 | .onEach(cars, new CarValidator()) 44 | .onEach(cars, new CarValidator2()) 45 | .onEach(cars, new CarValidator3()) 46 | .doValidate() 47 | .result(toSimple()); 48 | System.out.println(ret); 49 | assertThat(ret.isSuccess(), is(false)); 50 | assertThat(ret.getErrorNumber(), is(2)); 51 | } 52 | 53 | @Test 54 | public void testCarArray() { 55 | Car[] cars = getValidCars().toArray(new Car[] {}); 56 | 57 | Result ret = FluentValidator.checkAll() 58 | .onEach(cars, new CarValidator()) 59 | .onEach(cars, new CarValidator2()) 60 | .onEach(cars, new CarValidator3()) 61 | .doValidate() 62 | .result(toSimple()); 63 | System.out.println(ret); 64 | assertThat(ret.isSuccess(), is(true)); 65 | } 66 | 67 | @Test 68 | public void testCarArrayNegative() { 69 | Car[] cars = getValidCars().toArray(new Car[] {}); 70 | cars[0].setSeatCount(0); 71 | cars[1].setLicensePlate("hehe"); 72 | 73 | Result ret = FluentValidator.checkAll().failOver() 74 | .onEach(cars, new CarValidator()) 75 | .onEach(cars, new CarValidator2()) 76 | .onEach(cars, new CarValidator3()) 77 | .doValidate() 78 | .result(toSimple()); 79 | System.out.println(ret); 80 | assertThat(ret.isSuccess(), is(false)); 81 | assertThat(ret.getErrorNumber(), is(2)); 82 | } 83 | 84 | @Test 85 | public void testNull() { 86 | List cars = null; 87 | 88 | Result ret = FluentValidator.checkAll() 89 | .onEach(cars, new CarValidator()) 90 | .onEach(cars, new CarValidator2()) 91 | .onEach(cars, new CarValidator3()) 92 | .doValidate() 93 | .result(toSimple()); 94 | System.out.println(ret); 95 | assertThat(ret.isSuccess(), is(true)); 96 | } 97 | 98 | private List getValidCars() { 99 | return Lists.newArrayList(new Car("BMW", "LA1234", 5), 100 | new Car("Benz", "NYCuuu", 2), 101 | new Car("Chevrolet", "LA1234", 7)); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Car.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 4 | import com.baidu.unbiz.fluentvalidator.group.CheckManufacturer; 5 | import com.baidu.unbiz.fluentvalidator.validator.CarLicensePlateValidator; 6 | import com.baidu.unbiz.fluentvalidator.validator.CarManufacturerValidator; 7 | import com.baidu.unbiz.fluentvalidator.validator.CarSeatCountValidator; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class Car { 13 | 14 | @FluentValidate(value = {CarManufacturerValidator.class}, groups = {CheckManufacturer.class}) 15 | private String manufacturer; 16 | 17 | @FluentValidate({CarLicensePlateValidator.class}) 18 | private String licensePlate; 19 | 20 | @FluentValidate({CarSeatCountValidator.class}) 21 | private int seatCount; 22 | 23 | public Car(String manufacturer, String licencePlate, int seatCount) { 24 | this.manufacturer = manufacturer; 25 | this.licensePlate = licencePlate; 26 | this.seatCount = seatCount; 27 | } 28 | 29 | public int getSeatCount() { 30 | return seatCount; 31 | } 32 | 33 | public void setSeatCount(int seatCount) { 34 | this.seatCount = seatCount; 35 | } 36 | 37 | public String getManufacturer() { 38 | return manufacturer; 39 | } 40 | 41 | public void setManufacturer(String manufacturer) { 42 | this.manufacturer = manufacturer; 43 | } 44 | 45 | public String getLicensePlate() { 46 | return licensePlate; 47 | } 48 | 49 | public void setLicensePlate(String licensePlate) { 50 | this.licensePlate = licensePlate; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/dto/CollectionWrapper.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * 针对collection集合类的封装 7 | */ 8 | public class CollectionWrapper { 9 | 10 | private Map id2PersonMap; 11 | 12 | public Map getId2PersonMap() { 13 | return id2PersonMap; 14 | } 15 | 16 | public void setId2PersonMap(Map id2PersonMap) { 17 | this.id2PersonMap = id2PersonMap; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Garage.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValid; 6 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 7 | import com.baidu.unbiz.fluentvalidator.validator.StringValidator; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class Garage { 13 | 14 | @FluentValidate({StringValidator.class}) 15 | private String str; 16 | 17 | @FluentValid 18 | private Car singleCar; 19 | 20 | @FluentValid 21 | private List collectionCar; 22 | 23 | @FluentValid 24 | private Car[] arrayCar; 25 | 26 | public Car[] getArrayCar() { 27 | return arrayCar; 28 | } 29 | 30 | public void setArrayCar(Car[] arrayCar) { 31 | this.arrayCar = arrayCar; 32 | } 33 | 34 | public List getCollectionCar() { 35 | return collectionCar; 36 | } 37 | 38 | public void setCollectionCar(List collectionCar) { 39 | this.collectionCar = collectionCar; 40 | } 41 | 42 | public Car getSingleCar() { 43 | return singleCar; 44 | } 45 | 46 | public void setSingleCar(Car singleCar) { 47 | this.singleCar = singleCar; 48 | } 49 | 50 | public String getStr() { 51 | return str; 52 | } 53 | 54 | public void setStr(String str) { 55 | this.str = str; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Person.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 4 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator; 5 | 6 | /** 7 | * @author zhangxu 8 | */ 9 | public class Person { 10 | 11 | private String firstName; 12 | 13 | @FluentValidate 14 | private String lastName; 15 | 16 | private int age; 17 | 18 | public Person(String firstName, String lastName, int age) { 19 | this.firstName = firstName; 20 | this.lastName = lastName; 21 | this.age = age; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "Person{" + 27 | "age=" + age + 28 | ", firstName='" + firstName + '\'' + 29 | ", lastName='" + lastName + '\'' + 30 | '}'; 31 | } 32 | 33 | public int getAge() { 34 | return age; 35 | } 36 | 37 | public void setAge(int age) { 38 | this.age = age; 39 | } 40 | 41 | public String getFirstName() { 42 | return firstName; 43 | } 44 | 45 | public void setFirstName(String firstName) { 46 | this.firstName = firstName; 47 | } 48 | 49 | public String getLastName() { 50 | return lastName; 51 | } 52 | 53 | public void setLastName(String lastName) { 54 | this.lastName = lastName; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/dto/Person2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.dto; 2 | 3 | import com.baidu.unbiz.fluentvalidator.annotation.FluentValidate; 4 | import com.baidu.unbiz.fluentvalidator.validator.CarValidator; 5 | 6 | /** 7 | * @author zhangxu 8 | */ 9 | public class Person2 { 10 | 11 | @FluentValidate(value = {CarValidator.class}) 12 | private String firstName; 13 | 14 | @FluentValidate 15 | private String lastName; 16 | 17 | private int age; 18 | 19 | public Person2(String firstName, String lastName, int age) { 20 | this.firstName = firstName; 21 | this.lastName = lastName; 22 | this.age = age; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "Person{" + 28 | "age=" + age + 29 | ", firstName='" + firstName + '\'' + 30 | ", lastName='" + lastName + '\'' + 31 | '}'; 32 | } 33 | 34 | public int getAge() { 35 | return age; 36 | } 37 | 38 | public void setAge(int age) { 39 | this.age = age; 40 | } 41 | 42 | public String getFirstName() { 43 | return firstName; 44 | } 45 | 46 | public void setFirstName(String firstName) { 47 | this.firstName = firstName; 48 | } 49 | 50 | public String getLastName() { 51 | return lastName; 52 | } 53 | 54 | public void setLastName(String lastName) { 55 | this.lastName = lastName; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/error/CarError.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.error; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public enum CarError { 7 | MANUFACTURER_ERROR("Manufacturer is not valid, invalid value=%s"), 8 | LICENSEPLATE_ERROR("License is not valid, invalid value=%s"), 9 | SEATCOUNT_ERROR("Seat count is not valid, invalid value=%s"); 10 | 11 | CarError(String msg) { 12 | this.msg = msg; 13 | } 14 | 15 | private String msg; 16 | 17 | public String msg() { 18 | return msg; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/exception/CustomException.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.exception; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class CustomException extends RuntimeException { 7 | 8 | public CustomException() { 9 | } 10 | 11 | public CustomException(String message) { 12 | super(message); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/group/CheckManufacturer.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.group; 2 | 3 | /** 4 | * @author zhangxu 5 | */ 6 | public class CheckManufacturer { 7 | } 8 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/rpc/ManufacturerService.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.rpc; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhangxu 7 | */ 8 | public interface ManufacturerService { 9 | 10 | List getAllManufacturers(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/rpc/impl/ManufacturerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.rpc.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.baidu.unbiz.fluentvalidator.rpc.ManufacturerService; 10 | 11 | /** 12 | * @author zhangxu 13 | */ 14 | public class ManufacturerServiceImpl implements ManufacturerService { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(ManufacturerServiceImpl.class); 17 | 18 | @Override 19 | public List getAllManufacturers() { 20 | LOGGER.info("Get all manufacturers"); 21 | List ret = new ArrayList(); 22 | ret.add("BMW"); 23 | ret.add("Benz"); 24 | ret.add("Chevrolet"); 25 | return ret; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/sample/AnnotationClass.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.baidu.unbiz.fluentvalidator.sample; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.util.Date; 9 | 10 | public class AnnotationClass { 11 | 12 | private int x; 13 | @TestAnnotation(value = "y") 14 | private int y; 15 | 16 | private String z; 17 | @TestAnnotation(value = "d") 18 | private Date d; 19 | 20 | public int getX() { 21 | return x; 22 | } 23 | 24 | @TestAnnotation(value = "setX") 25 | public void setX(int x) { 26 | this.x = x; 27 | } 28 | 29 | @TestAnnotation(value = "getY") 30 | public int getY() { 31 | return y; 32 | } 33 | 34 | public void setY(int y) { 35 | this.y = y; 36 | } 37 | 38 | @TestAnnotation(value = "getZ") 39 | public String getZ() { 40 | return z; 41 | } 42 | 43 | @TestAnnotation(value = "setZ") 44 | public void setZ(String z) { 45 | this.z = z; 46 | } 47 | 48 | @TestAnnotation(value = "getD") 49 | public Date getD() { 50 | return d; 51 | } 52 | 53 | @TestAnnotation(value = "setD") 54 | public void setD(Date d) { 55 | this.d = d; 56 | } 57 | 58 | @TestAnnotation(value = "toString") 59 | public String toString() { 60 | return super.toString(); 61 | } 62 | 63 | @TestAnnotation(value = "clone") 64 | public Object clone() throws CloneNotSupportedException { 65 | return super.clone(); 66 | } 67 | 68 | @Retention(RetentionPolicy.RUNTIME) 69 | public @interface TestAnnotation { 70 | String value(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/support/ConcurrentCacheTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.support; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.concurrent.Callable; 6 | 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | /** 12 | * @author zhangxu 13 | */ 14 | public class ConcurrentCacheTest { 15 | 16 | private Computable cache; 17 | 18 | @Before 19 | public void setUp() throws Exception { 20 | cache = ConcurrentCache.createComputable(); 21 | } 22 | 23 | @After 24 | public void tearDown() throws Exception { 25 | cache = null; 26 | } 27 | 28 | @Test 29 | public void testGetObject() { 30 | final String key = "object"; 31 | 32 | Object result1 = cache.get(key, new Callable() { 33 | 34 | @Override 35 | public Object call() throws Exception { 36 | return new Object(); 37 | } 38 | }); 39 | 40 | Object result2 = cache.get(key, new Callable() { 41 | 42 | @Override 43 | public Object call() throws Exception { 44 | return new Object(); 45 | } 46 | }); 47 | 48 | assertEquals(result1, result2); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/util/ArrayUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertNull; 5 | import static org.junit.Assert.assertThat; 6 | 7 | import org.hamcrest.Matchers; 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author zhangxu 12 | */ 13 | public class ArrayUtilTest { 14 | 15 | @Test 16 | public void testIsEmpty() { 17 | assertThat(ArrayUtil.isEmpty(null), Matchers.is(true)); 18 | assertThat(ArrayUtil.isEmpty(new Integer[0]), Matchers.is(true)); 19 | assertThat(ArrayUtil.isEmpty(new Integer[10]), Matchers.is(false)); 20 | } 21 | 22 | @Test 23 | public void testHasIntersection() { 24 | Class[] from = new Class[] {}; 25 | Class[] target = new Class[] {}; 26 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true)); 27 | 28 | from = new Class[] {String.class}; 29 | target = new Class[] {}; 30 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true)); 31 | 32 | from = new Class[] {}; 33 | target = new Class[] {String.class}; 34 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(false)); 35 | 36 | from = new Class[] {String.class}; 37 | target = new Class[] {String.class}; 38 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true)); 39 | 40 | from = new Class[] {String.class, Object.class}; 41 | target = new Class[] {String.class}; 42 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true)); 43 | 44 | from = new Class[] {String.class}; 45 | target = new Class[] {String.class, Object.class}; 46 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(true)); 47 | 48 | from = new Class[] {Integer.class}; 49 | target = new Class[] {Object.class}; 50 | assertThat(ArrayUtil.hasIntersection(from, target), Matchers.is(false)); 51 | } 52 | 53 | @Test 54 | public void primitiveToWrapper() { 55 | assertNull(ArrayUtil.toWrapperIfPrimitive(null)); 56 | 57 | String[] strArray = ArrayUtil.toWrapperIfPrimitive(new String[0]); 58 | assertArrayEquals(new String[0], strArray); 59 | 60 | Boolean[] booleanArray = ArrayUtil.toWrapperIfPrimitive(new boolean[] {true, false, true}); 61 | assertArrayEquals(new Boolean[] {true, false, true}, booleanArray); 62 | 63 | Character[] charArray = ArrayUtil.toWrapperIfPrimitive(new char[] {'1', '2', '3'}); 64 | assertArrayEquals(new Character[] {'1', '2', '3'}, charArray); 65 | 66 | Byte[] byteArray = ArrayUtil.toWrapperIfPrimitive(new byte[] {1, 2, 3}); 67 | assertArrayEquals(new Byte[] {1, 2, 3}, byteArray); 68 | 69 | Short[] shortArray = ArrayUtil.toWrapperIfPrimitive(new short[] {1, 2, 3}); 70 | assertArrayEquals(new Short[] {1, 2, 3}, shortArray); 71 | 72 | Integer[] intArray = ArrayUtil.toWrapperIfPrimitive(new int[] {1, 2, 3}); 73 | assertArrayEquals(new Integer[] {1, 2, 3}, intArray); 74 | 75 | Long[] longArray = ArrayUtil.toWrapperIfPrimitive(new long[] {1L, 2L, 3L}); 76 | assertArrayEquals(new Long[] {1L, 2L, 3L}, longArray); 77 | 78 | Float[] floatArray = ArrayUtil.toWrapperIfPrimitive(new float[] {1f, 2f, 3f}); 79 | assertArrayEquals(new Float[] {1f, 2f, 3f}, floatArray); 80 | 81 | Double[] doubleArray = ArrayUtil.toWrapperIfPrimitive(new double[] {1d, 2d, 3d}); 82 | assertArrayEquals(new Double[] {1d, 2d, 3d}, doubleArray); 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/util/ClassUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author zhangxu 9 | */ 10 | public class ClassUtilTest { 11 | 12 | @Test 13 | public void getWrapperTypeIfPrimitiveInt() { 14 | assertEquals(Integer.class, ClassUtil.getWrapperTypeIfPrimitive(int.class)); 15 | } 16 | 17 | @Test 18 | public void getWrapperTypeIfPrimitiveLong() { 19 | assertEquals(Long.class, ClassUtil.getWrapperTypeIfPrimitive(long.class)); 20 | } 21 | 22 | @Test 23 | public void getWrapperTypeIfPrimitiveShort() { 24 | assertEquals(Short.class, ClassUtil.getWrapperTypeIfPrimitive(short.class)); 25 | } 26 | 27 | @Test 28 | public void getWrapperTypeIfPrimitiveDouble() { 29 | assertEquals(Double.class, ClassUtil.getWrapperTypeIfPrimitive(double.class)); 30 | } 31 | 32 | @Test 33 | public void getWrapperTypeIfPrimitiveFloat() { 34 | assertEquals(Float.class, ClassUtil.getWrapperTypeIfPrimitive(float.class)); 35 | } 36 | 37 | @Test 38 | public void getWrapperTypeIfPrimitiveChar() { 39 | assertEquals(Character.class, ClassUtil.getWrapperTypeIfPrimitive(char.class)); 40 | } 41 | 42 | @Test 43 | public void getWrapperTypeIfPrimitiveByte() { 44 | assertEquals(Byte.class, ClassUtil.getWrapperTypeIfPrimitive(byte.class)); 45 | } 46 | 47 | @Test 48 | public void getWrapperTypeIfPrimitiveBoolean() { 49 | assertEquals(Boolean.class, ClassUtil.getWrapperTypeIfPrimitive(boolean.class)); 50 | } 51 | 52 | @Test 53 | public void getWrapperTypeIfPrimitiveVoid() { 54 | assertEquals(Void.class, ClassUtil.getWrapperTypeIfPrimitive(void.class)); 55 | } 56 | 57 | @Test 58 | public void getWrapperTypeIfPrimitiveString() { 59 | assertEquals(String.class, ClassUtil.getWrapperTypeIfPrimitive(String.class)); 60 | } 61 | 62 | @Test 63 | public void getWrapperTypeIfPrimitiveInt2dArray() { 64 | assertEquals(int[][].class, ClassUtil.getWrapperTypeIfPrimitive(int[][].class)); 65 | } 66 | 67 | @Test 68 | public void getWrapperTypeIfPrimitiveLong2dArray() { 69 | assertEquals(long[][].class, ClassUtil.getWrapperTypeIfPrimitive(long[][].class)); 70 | } 71 | 72 | @Test 73 | public void getWrapperTypeIfPrimitiveShort2dArray() { 74 | assertEquals(short[][].class, ClassUtil.getWrapperTypeIfPrimitive(short[][].class)); 75 | } 76 | 77 | @Test 78 | public void getWrapperTypeIfPrimitiveDouble2dArray() { 79 | assertEquals(double[][].class, ClassUtil.getWrapperTypeIfPrimitive(double[][].class)); 80 | } 81 | 82 | @Test 83 | public void getWrapperTypeIfPrimitiveFloat2dArray() { 84 | assertEquals(float[][].class, ClassUtil.getWrapperTypeIfPrimitive(float[][].class)); 85 | } 86 | 87 | @Test 88 | public void getWrapperTypeIfPrimitiveChar2dArray() { 89 | assertEquals(char[][].class, ClassUtil.getWrapperTypeIfPrimitive(char[][].class)); 90 | } 91 | 92 | @Test 93 | public void getWrapperTypeIfPrimitiveByte2dArray() { 94 | assertEquals(byte[][].class, ClassUtil.getWrapperTypeIfPrimitive(byte[][].class)); 95 | } 96 | 97 | @Test 98 | public void getWrapperTypeIfPrimitiveBoolean2dArray() { 99 | assertEquals(boolean[][].class, ClassUtil.getWrapperTypeIfPrimitive(boolean[][].class)); 100 | } 101 | 102 | @Test 103 | public void getWrapperTypeIfPrimitiveString2dArray() { 104 | assertEquals(String[][].class, ClassUtil.getWrapperTypeIfPrimitive(String[][].class)); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/util/PreconditionsTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import org.junit.Test; 4 | 5 | public class PreconditionsTest { 6 | 7 | @Test 8 | public void testCheckArgument() { 9 | try { 10 | int i = -1; 11 | Preconditions.checkArgument(i >= 0, "Argument was %s but expected nonnegative", i); 12 | } catch (Exception e) { 13 | // TODO: handle exception 14 | } 15 | try { 16 | int i = -1; 17 | Preconditions.checkArgument(i >= 0); 18 | } catch (Exception e) { 19 | // TODO: handle exception 20 | } 21 | 22 | try { 23 | int i = -1; 24 | Preconditions.checkArgument(i >= 0, "Argument expected nonnegative"); 25 | } catch (Exception e) { 26 | // TODO: handle exception 27 | } 28 | } 29 | 30 | @Test 31 | public void testCheckNotNull() { 32 | try { 33 | Object obj = null; 34 | Preconditions.checkNotNull(obj, "Argument was %s but expected not null", obj); 35 | } catch (Exception e) { 36 | // TODO: handle exception 37 | } 38 | 39 | try { 40 | Object obj = null; 41 | Preconditions.checkNotNull(obj); 42 | } catch (Exception e) { 43 | // TODO: handle exception 44 | } 45 | 46 | try { 47 | Object obj = null; 48 | Preconditions.checkNotNull(obj, "Argument expected not null"); 49 | } catch (Exception e) { 50 | // TODO: handle exception 51 | } 52 | } 53 | 54 | @Test 55 | public void testCheckState() { 56 | try { 57 | int x = 1; 58 | Preconditions.checkState(x == 5, "Argument was %s but expected 5", x); 59 | } catch (Exception e) { 60 | // TODO: handle exception 61 | } 62 | 63 | try { 64 | int x = 1; 65 | Preconditions.checkState(x == 5); 66 | } catch (Exception e) { 67 | // TODO: handle exception 68 | } 69 | 70 | try { 71 | int x = 1; 72 | Preconditions.checkState(x == 5, "Argument expected 5"); 73 | } catch (Exception e) { 74 | // TODO: handle exception 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/util/ReflectionUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.util; 2 | 3 | import static org.hamcrest.core.Is.is; 4 | import static org.junit.Assert.assertNull; 5 | import static org.junit.Assert.assertThat; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | import java.lang.annotation.Annotation; 9 | import java.lang.reflect.Field; 10 | 11 | import org.junit.Test; 12 | 13 | import com.baidu.unbiz.fluentvalidator.sample.AnnotationClass; 14 | 15 | /** 16 | * @author zhangxu 17 | */ 18 | public class ReflectionUtilTest { 19 | 20 | @Test 21 | public void testGetAnnotationFields() { 22 | assertNull(ReflectionUtil.getAnnotationFields((Class) null, (Class) null)); 23 | 24 | assertNull(ReflectionUtil.getAnnotationFields((Class) null, AnnotationClass.TestAnnotation.class)); 25 | assertNull(ReflectionUtil.getAnnotationFields(AnnotationClass.class, (Class) null)); 26 | 27 | Field[] fields = 28 | ReflectionUtil.getAnnotationFields(AnnotationClass.class, AnnotationClass.TestAnnotation.class); 29 | assertThat(fields.length, is(2)); 30 | 31 | AnnotationClass.TestAnnotation anno = 32 | ReflectionUtil.getAnnotation(fields[0], AnnotationClass.TestAnnotation.class); 33 | assertThat(anno.value(), is("y")); 34 | 35 | fields = ReflectionUtil.getAnnotationFields(AnnotationClass.class, Test.class); 36 | assertThat(fields.length, is(0)); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarLicensePlateValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.error.CarError; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class CarLicensePlateValidator extends ValidatorHandler implements Validator { 12 | 13 | private MockRpcService normalMockRpcService = new NormalMockRpcService(); 14 | 15 | private MockRpcService abNormalMockRpcService = new AbnormalMockRpcService(); 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, String t) { 19 | if (t.startsWith("NYC") || t.startsWith("LA") || t.startsWith("BEIJING")) { 20 | if (!normalMockRpcService.isValid(t)) { 21 | context.addErrorMsg(String.format(CarError.LICENSEPLATE_ERROR.msg(), t)); 22 | return false; 23 | } 24 | } else { 25 | if (abNormalMockRpcService.isValid(t)) { 26 | context.addErrorMsg(String.format(CarError.LICENSEPLATE_ERROR.msg(), t)); 27 | return false; 28 | } 29 | } 30 | return true; 31 | } 32 | 33 | } 34 | 35 | interface MockRpcService { 36 | 37 | boolean isValid(String licensePlate); 38 | 39 | } 40 | 41 | class NormalMockRpcService implements MockRpcService { 42 | 43 | public boolean isValid(String licensePlate) { 44 | if (licensePlate.startsWith("BEIJING")) { 45 | return false; 46 | } 47 | return true; 48 | } 49 | 50 | } 51 | 52 | class AbnormalMockRpcService implements MockRpcService { 53 | 54 | public boolean isValid(String licensePlate) { 55 | throw new RuntimeException("Call Rpc failed"); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarManufacturerValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.error.CarError; 7 | import com.baidu.unbiz.fluentvalidator.rpc.ManufacturerService; 8 | import com.baidu.unbiz.fluentvalidator.rpc.impl.ManufacturerServiceImpl; 9 | 10 | /** 11 | * @author zhangxu 12 | */ 13 | public class CarManufacturerValidator extends ValidatorHandler implements Validator { 14 | 15 | private ManufacturerService manufacturerService = new ManufacturerServiceImpl(); 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, String t) { 19 | Boolean ignoreManufacturer = context.getAttribute("ignoreManufacturer", Boolean.class); 20 | if (ignoreManufacturer != null && ignoreManufacturer) { 21 | return true; 22 | } 23 | if (!manufacturerService.getAllManufacturers().contains(t)) { 24 | context.addErrorMsg(String.format(CarError.MANUFACTURER_ERROR.msg(), t)); 25 | return false; 26 | } 27 | return true; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarSeatCountValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.error.CarError; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class CarSeatCountValidator extends ValidatorHandler implements Validator { 12 | 13 | @Override 14 | public boolean validate(ValidatorContext context, Integer t) { 15 | if (t != 2 && t != 5 && t != 7) { 16 | context.addErrorMsg(String.format(CarError.SEATCOUNT_ERROR.msg(), t)); 17 | return false; 18 | } 19 | return true; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import java.util.List; 4 | 5 | import com.baidu.unbiz.fluentvalidator.Closure; 6 | import com.baidu.unbiz.fluentvalidator.Validator; 7 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 8 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 9 | import com.baidu.unbiz.fluentvalidator.dto.Car; 10 | import com.baidu.unbiz.fluentvalidator.error.CarError; 11 | 12 | /** 13 | * @author zhangxu 14 | */ 15 | public class CarValidator extends ValidatorHandler implements Validator { 16 | 17 | @Override 18 | public boolean validate(ValidatorContext context, Car car) { 19 | Closure> closure = context.getClosure("manufacturerClosure"); 20 | if (closure != null) { 21 | List manufacturers = closure.executeAndGetResult(); 22 | 23 | if (!manufacturers.contains(car.getManufacturer())) { 24 | context.addErrorMsg(String.format(CarError.MANUFACTURER_ERROR.msg(), car.getManufacturer())); 25 | return false; 26 | } 27 | } 28 | 29 | return true; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarValidator2.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.dto.Car; 7 | import com.baidu.unbiz.fluentvalidator.error.CarError; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class CarValidator2 extends ValidatorHandler implements Validator { 13 | 14 | @Override 15 | public boolean validate(ValidatorContext context, Car car) { 16 | if (!car.getLicensePlate().startsWith("NYC") 17 | && !car.getLicensePlate().startsWith("LA") 18 | && !car.getLicensePlate().startsWith("BEIJING")) { 19 | context.addErrorMsg(String.format(CarError.LICENSEPLATE_ERROR.msg(), car.getLicensePlate())); 20 | return false; 21 | } 22 | 23 | return true; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/CarValidator3.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | import com.baidu.unbiz.fluentvalidator.dto.Car; 7 | import com.baidu.unbiz.fluentvalidator.error.CarError; 8 | 9 | /** 10 | * @author zhangxu 11 | */ 12 | public class CarValidator3 extends ValidatorHandler implements Validator { 13 | 14 | @Override 15 | public boolean validate(ValidatorContext context, Car car) { 16 | if (car.getSeatCount() != 2 && car.getSeatCount() != 5 && car.getSeatCount() != 7) { 17 | context.addErrorMsg(String.format(CarError.SEATCOUNT_ERROR.msg(), car.getSeatCount())); 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/NotNullValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.Validator; 4 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 6 | 7 | /** 8 | * @author zhangxu 9 | */ 10 | public class NotNullValidator extends ValidatorHandler implements Validator { 11 | 12 | @Override 13 | public boolean validate(ValidatorContext context, Object t) { 14 | if (t == null) { 15 | context.addErrorMsg("Null is not expected!"); 16 | return false; 17 | } 18 | return true; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fluent-validator/src/test/java/com/baidu/unbiz/fluentvalidator/validator/StringValidator.java: -------------------------------------------------------------------------------- 1 | package com.baidu.unbiz.fluentvalidator.validator; 2 | 3 | import com.baidu.unbiz.fluentvalidator.ValidationError; 4 | import com.baidu.unbiz.fluentvalidator.Validator; 5 | import com.baidu.unbiz.fluentvalidator.ValidatorContext; 6 | import com.baidu.unbiz.fluentvalidator.ValidatorHandler; 7 | 8 | /** 9 | * @author zhangxu 10 | */ 11 | public class StringValidator extends ValidatorHandler implements Validator { 12 | 13 | @Override 14 | public boolean accept(ValidatorContext context, String s) { 15 | System.out.println("accept " + s); 16 | return true; 17 | } 18 | 19 | @Override 20 | public boolean validate(ValidatorContext context, String t) { 21 | String myname = context.getAttribute("myname", String.class); 22 | if (myname != null && myname.equals("pass")) { 23 | return true; 24 | } 25 | System.out.println("check " + t); 26 | if (!t.startsWith("abc")) { 27 | context.addError(ValidationError.create("string should be abc").setErrorCode(100).setField("str") 28 | .setInvalidValue(t)); 29 | return false; 30 | } 31 | return true; 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /fluent-validator/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | 3 | # navi log 4 | log4j.logger.com.baidu.unbiz=DEBUG 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.encoding=gbk 8 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.console.layout.ConversionPattern=[%p]\t%d\t[%t]\t%c{3}\t(%F:%L)\t-%m%n 10 | -------------------------------------------------------------------------------- /run_unittest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mvn clean package test --------------------------------------------------------------------------------