package com.gh.mygreen.xlsmapper.validation.beanvalidation;
import static com.gh.mygreen.xlsmapper.TestUtils.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.awt.Point;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.junit.Before;
import org.junit.Test;
import com.gh.mygreen.xlsmapper.IsEmptyBuilder;
import com.gh.mygreen.xlsmapper.XlsMapper;
import com.gh.mygreen.xlsmapper.annotation.LabelledCellType;
import com.gh.mygreen.xlsmapper.annotation.RecordTerminal;
import com.gh.mygreen.xlsmapper.annotation.XlsColumn;
import com.gh.mygreen.xlsmapper.annotation.XlsDateConverter;
import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecords;
import com.gh.mygreen.xlsmapper.annotation.XlsIsEmpty;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCell;
import com.gh.mygreen.xlsmapper.annotation.XlsSheet;
import com.gh.mygreen.xlsmapper.expression.ExpressionLanguageELImpl;
import com.gh.mygreen.xlsmapper.validation.CellFieldError;
import com.gh.mygreen.xlsmapper.validation.MessageInterpolator;
import com.gh.mygreen.xlsmapper.validation.ObjectError;
import com.gh.mygreen.xlsmapper.validation.ResourceBundleMessageResolver;
import com.gh.mygreen.xlsmapper.validation.SheetBindingErrors;
import com.gh.mygreen.xlsmapper.validation.SheetMessageConverter;
/**
* {@link SheetBeanValidator}のテスタ
*
* @since 0.5
* @author T.TSUCHIE
*
*/
public class SheetBeanValidatorTest {
private SheetMessageConverter messageConverter;
@Before
public void setUp() throws Exception {
this.messageConverter = new SheetMessageConverter();
}
private Validator getBeanValidator() {
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.usingContext()
.messageInterpolator(new MessageResolverInterpolator(new ResourceBundleMessageResolver()))
.getValidator();
return validator;
}
/**
* 単純なBeanのテスト - エラーなし
*/
@Test
public void test_simple_success() throws Exception {
XlsMapper mapper = new XlsMapper();
mapper.getConig().setContinueTypeBindFailure(true);
// シートの読み込み
SheetBindingErrors errors;
SimpleBeanSheet sheet;
try(InputStream in = new FileInputStream("src/test/data/validator_bean.xlsx")) {
errors = new SheetBindingErrors(SimpleBeanSheet.class);
sheet = mapper.load(in, SimpleBeanSheet.class, errors);
}
// 入力値検証
SheetBeanValidator sheetValidator = new SheetBeanValidator(getBeanValidator());
sheetValidator.validate(sheet, errors);
assertThat(errors.getAllErrors(), hasSize(0));
}
/**
* 単純なBeanのテスト - エラーあり
*/
@Test
public void test_simple_error() throws Exception {
XlsMapper mapper = new XlsMapper();
mapper.getConig().setContinueTypeBindFailure(true);
// シートの読み込み
SheetBindingErrors errors = new SheetBindingErrors(SimpleBeanSheet.class);;
SimpleBeanSheet sheet;
try(InputStream in = new FileInputStream("src/test/data/validator_bean.xlsx")) {
sheet = mapper.load(in, SimpleBeanSheet.class, errors);
}
// データの書き換え
sheet.description = "あいうえおかきくけこさ";
sheet.age = -1;
sheet.email = "test";
// 入力値検証
SheetBeanValidator sheetValidator = new SheetBeanValidator(getBeanValidator());
sheetValidator.validate(sheet, errors);
// printErrors(errors);
{
String fieldName = "description";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Length"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.description));
assertThat(fieldError.getVars(), hasEntry("min", (Object)0));
assertThat(fieldError.getVars(), hasEntry("max", (Object)10));
}
{
String fieldName = "age";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Range"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.age));
assertThat(fieldError.getVars(), hasEntry("min", (Object)0L));
assertThat(fieldError.getVars(), hasEntry("max", (Object)100L));
}
{
String fieldName = "email";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Email"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.email));
}
}
/**
* リストなBeanのテスト - エラーなし
*/
@Test
public void test_list_success() throws Exception {
XlsMapper mapper = new XlsMapper();
mapper.getConig().setContinueTypeBindFailure(true);
// シートの読み込み
SheetBindingErrors errors = new SheetBindingErrors(ListBeanSheet.class);
ListBeanSheet sheet;
try(InputStream in = new FileInputStream("src/test/data/validator_bean.xlsx")) {
sheet = mapper.load(in, ListBeanSheet.class, errors);
}
// 入力値検証
SheetBeanValidator sheetValidator = new SheetBeanValidator(getBeanValidator());
sheetValidator.validate(sheet, errors);
printErrors(errors);
assertThat(errors.getAllErrors(), hasSize(0));
}
/**
* リストなBeanのテスト - エラーあり
*/
@Test
public void test_list_error() throws Exception {
XlsMapper mapper = new XlsMapper();
mapper.getConig().setContinueTypeBindFailure(true);
// シートの読み込み
SheetBindingErrors errors = new SheetBindingErrors(ListBeanSheet.class);
ListBeanSheet sheet;
try(InputStream in = new FileInputStream("src/test/data/validator_bean.xlsx")) {
sheet = mapper.load(in, ListBeanSheet.class, errors);
}
// データの書き換え
sheet.className = null;
sheet.list.get(1).email = "test";
sheet.list.get(2).birthday = getDateByDay(new Date(), 1);
// 入力値検証
SheetBeanValidator sheetValidator = new SheetBeanValidator(getBeanValidator());
sheetValidator.validate(sheet, errors);
// printErrors(errors);
{
String fieldName = "className";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("NotBlank"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.className));
}
try {
errors.pushNestedPath("list", 1);
PersonRecord record = sheet.list.get(1);
String fieldName = "email";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(record.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(record.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Email"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)record.email));
} finally {
errors.popNestedPath();
}
try {
errors.pushNestedPath("list", 2);
PersonRecord record = sheet.list.get(2);
String fieldName = "birthday";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(record.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(record.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Past"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)record.birthday));
} finally {
errors.popNestedPath();
}
}
/**
* メッセージ処理系を独自のものにする。
* ・式言語処理を独自のものにする。
*/
@Test
public void test_interpolator_el() throws Exception {
XlsMapper mapper = new XlsMapper();
mapper.getConig().setContinueTypeBindFailure(true);
// シートの読み込み
SheetBindingErrors errors = new SheetBindingErrors(SimpleBeanSheet.class);;
SimpleBeanSheet sheet;
try(InputStream in = new FileInputStream("src/test/data/validator_bean.xlsx")) {
sheet = mapper.load(in, SimpleBeanSheet.class, errors);
}
// データの書き換え
sheet.updateTime = getDateByDay(new Date(), 1);
sheet.description = "あいうえおかきくけこさ";
sheet.age = -1;
sheet.email = "test";
// BeanValidatorの式言語の実装を独自のものにする。
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator beanValidator = validatorFactory.usingContext()
.messageInterpolator(new MessageInterpolatorAdapter(
new ResourceBundleMessageResolver(ResourceBundle.getBundle("com.gh.mygreen.xlsmapper.validation.beanvalidation.OtherElMessages")),
new MessageInterpolator(new ExpressionLanguageELImpl())))
.getValidator();
// 入力値検証
SheetBeanValidator sheetValidator = new SheetBeanValidator(beanValidator);
sheetValidator.validate(sheet, errors);
printErrors(errors);
{
String fieldName = "updateTime";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Past"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.updateTime));
}
{
String fieldName = "description";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Length"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.description));
assertThat(fieldError.getVars(), hasEntry("min", (Object)0));
assertThat(fieldError.getVars(), hasEntry("max", (Object)10));
}
{
String fieldName = "age";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Range"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.age));
assertThat(fieldError.getVars(), hasEntry("min", (Object)0L));
assertThat(fieldError.getVars(), hasEntry("max", (Object)100L));
}
{
String fieldName = "email";
CellFieldError fieldError = errors.getFirstCellFieldError(fieldName);
assertThat(fieldError.getCellAddress(), is(sheet.positions.get(fieldName)));
assertThat(fieldError.getLabel(), is(sheet.labels.get(fieldName)));
assertThat(fieldError.getCodes(), hasItemInArray("Email"));
assertThat(fieldError.getVars(), hasEntry("validatedValue", (Object)sheet.email));
}
}
private void printErrors(SheetBindingErrors errors) {
for(ObjectError error : errors.getAllErrors()) {
String message = messageConverter.convertMessage(error);
System.out.println(message);
}
}
@XlsSheet(name="単純なBean")
private static class SimpleBeanSheet {
private Map<String, Point> positions;
private Map<String, String> labels;
@Length(max=10)
@XlsLabelledCell(label="説明", type=LabelledCellType.Bottom)
private String description;
@Range(min=0, max=100)
@XlsLabelledCell(label="年齢", type=LabelledCellType.Right)
private Integer age;
@NotBlank
@Email
@XlsLabelledCell(label="e-mail(必須)", type=LabelledCellType.Right)
private String email;
@DecimalMin(value="0.0", inclusive=true)
@XlsLabelledCell(label="得点(平均)", type=LabelledCellType.Right)
private Double average;
@NotNull
@Past
@XlsDateConverter(lenient=true, javaPattern="yyyy年M月d日")
@XlsLabelledCell(label="更新日時", type=LabelledCellType.Right)
private Date updateTime;
}
@XlsSheet(name="リストのBean")
private static class ListBeanSheet {
private Map<String, Point> positions;
private Map<String, String> labels;
@NotBlank
@XlsLabelledCell(label="クラス名", type=LabelledCellType.Right)
private String className;
@Valid
@XlsHorizontalRecords(tableLabel="名簿一覧", terminal=RecordTerminal.Border, ignoreEmptyRecord=true)
private List<PersonRecord> list;
}
private static class PersonRecord {
private Map<String, Point> positions;
private Map<String, String> labels;
@XlsColumn(columnName="No.")
private int no;
@Length(max=10)
@XlsColumn(columnName="氏名")
private String name;
@NotBlank
@Email
@XlsColumn(columnName="メールアドレス")
private String email;
@NotNull
@Past
@XlsDateConverter(lenient=true, javaPattern="yyyy年M月d日")
@XlsColumn(columnName="生年月日")
private Date birthday;
@XlsIsEmpty
public boolean isEmpty() {
return IsEmptyBuilder.reflectionIsEmpty(this, "positions", "labels", "no");
}
}
}