package com.github.mygreen.supercsv.builder; import static org.junit.Assert.*; import static org.assertj.core.api.Assertions.*; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.time.LocalDate; import java.util.Comparator; import java.util.List; import java.util.Optional; import org.junit.Before; import org.junit.Test; import com.github.mygreen.supercsv.annotation.CsvBean; import com.github.mygreen.supercsv.annotation.CsvColumn; import com.github.mygreen.supercsv.annotation.CsvComposition; import com.github.mygreen.supercsv.annotation.CsvOverridesAttribute; import com.github.mygreen.supercsv.annotation.DefaultGroup; import com.github.mygreen.supercsv.annotation.constraint.CsvLengthMax; import com.github.mygreen.supercsv.annotation.constraint.CsvNumberRange; import com.github.mygreen.supercsv.annotation.constraint.CsvRequire; import com.github.mygreen.supercsv.builder.FieldAccessor; import com.github.mygreen.supercsv.io.SampleNormalBean; /** * {@link FieldAccessor}のテスタ * * @since 2.0 * @author T.TSUCHIE * */ public class FieldAccessorTest { private Comparator<Annotation> comparator; @Before public void setUp() throws Exception { this.comparator = new AnnotationComparator(); } @Test public void testConstructor_normal() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.getName()).isEqualTo("col1"); assertThat(property.getType()).isEqualTo(String.class); assertThat(property.getDeclaredClass()).isEqualTo(SampleBean.class); } @Test(expected=NullPointerException.class) public void testConstructor_arg_null() { new FieldAccessor(null, comparator); } /** * {@link FieldAccessor#getName()} */ @Test public void testGetName() throws Exception{ Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.getName()).isEqualTo("col1"); } /** * {@link FieldAccessor#getNameWithClass()} */ @Test public void testGetNameWithClass() throws Exception{ Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.getNameWithClass()).isEqualTo(SampleBean.class.getName() + "#col1"); } /** * {@link FieldAccessor#getTypeName()} */ @Test public void testGetTypeName() throws Exception{ Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.getTypeName()).isEqualTo("java.lang.String"); } /** * {@link FieldAccessor#isTypeOf(Class)} */ @Test public void testIsTypeOf() throws Exception{ Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.isTypeOf(String.class)).isTrue(); assertThat(property.isTypeOf(int.class)).isFalse(); } /** * {@link FieldAccessor#getValue(Object)} */ @Test public void testGetValue() throws Exception{ Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); SampleBean targetObj = new SampleBean(); assertThat(property.getValue(targetObj)).isNull(); targetObj.col1 = "test"; assertThat(property.getValue(targetObj)).isEqualTo("test"); } /** * {@link FieldAccessor#getValue(Object)} * <p>Beanのタイプが不一致</p> */ @Test(expected=IllegalArgumentException.class) public void testGetValue_wrongType() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); property.getValue(new SampleNormalBean()); fail(); } /** * アノテーションの取得 - 1件取得 */ @Test public void testGetAnnotation() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); { // 存在するアノテーション Optional<CsvColumn> anno = property.getAnnotation(CsvColumn.class); assertThat(anno.isPresent()).isTrue(); assertThat(anno.get().number()).isEqualTo(1); } { // 存在しないアノテーション Optional<CsvRequire> anno = property.getAnnotation(CsvRequire.class); assertThat(anno.isPresent()).isFalse(); } } /** * アノテーションの取得 - 複数件の取得 */ @Test public void testGetAnnotations() throws Exception { Field field = SampleBean.class.getDeclaredField("col4"); FieldAccessor property = new FieldAccessor(field, comparator); { List<CsvColumn> annos = property.getAnnotations(CsvColumn.class); assertThat(annos).hasSize(1); } { // 繰り返しのアノテーション List<CsvNumberRange> annos = property.getAnnotations(CsvNumberRange.class); assertThat(annos).hasSize(2); } } /** * アノテーションの取得 - 合成のアノテーション */ @Test public void testGetAnnotations_composition() throws Exception { Field field = SampleBean.class.getDeclaredField("col5"); FieldAccessor property = new FieldAccessor(field, comparator); { List<CsvColumn> annos = property.getAnnotations(CsvColumn.class); assertThat(annos).hasSize(1); } { // 合成のアノテーション自身 List<CsvUsername> annos = property.getAnnotations(CsvUsername.class); assertThat(annos).hasSize(1); } { // 合成のアノテーションの中のアノテーション List<CsvLengthMax> annos = property.getAnnotations(CsvLengthMax.class); assertThat(annos).hasSize(2); } } /** * アノテーションの取得 - グループ属性なしの場合 */ @Test public void testGetAnnotationsByGroup_noGroup() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); { // 存在するアノテーション - groups属性を持たない List<CsvColumn> annos = property.getAnnotationsByGroup(CsvColumn.class); assertThat(annos).hasSize(0); } { // 存在しないアノテーション - groups属性を持つ List<CsvRequire> annos = property.getAnnotationsByGroup(CsvRequire.class); assertThat(annos).hasSize(0); } { // 存在するアノテーション(デフォルトグループ) - groups属性を持たない List<CsvColumn> annos = property.getAnnotationsByGroup(CsvColumn.class, DefaultGroup.class); assertThat(annos).hasSize(0); } { // 存在しないアノテーション(デフォルトグループ) - groups属性を持つ List<CsvRequire> annos = property.getAnnotationsByGroup(CsvRequire.class, DefaultGroup.class); assertThat(annos).hasSize(0); } } /** * アノテーションの取得 - グループ属性ありの場合 */ @Test public void testGetAnnotationsByGroup_group() throws Exception { Field field = SampleBean.class.getDeclaredField("col2"); FieldAccessor property = new FieldAccessor(field, comparator); { // グループ属性が定義されていないアノテーション List<CsvColumn> annos = property.getAnnotationsByGroup(CsvColumn.class, Group1.class); assertThat(annos).hasSize(0); } { // 存在するアノテーション List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, Group1.class); assertThat(annos).hasSize(1); assertThat(annos.get(0).min()).isEqualTo("50"); } { // 存在しないアノテーション List<CsvRequire> annos = property.getAnnotationsByGroup(CsvRequire.class, Group1.class); assertThat(annos).hasSize(0); } { // 存在しないグループ List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, Group2.class); assertThat(annos).hasSize(0); } } /** * アノテーションの取得 - グループの指定あり(デフォルトグループ) */ @Test public void testGetAnnotationsByGroup_defaultGroup() throws Exception { Field field = SampleBean.class.getDeclaredField("col3"); FieldAccessor property = new FieldAccessor(field, comparator); { // グループの指定なし(定義側もグループの指定なし) List<CsvColumn> annos = property.getAnnotationsByGroup(CsvColumn.class); assertThat(annos).hasSize(0); } { // グループの指定なし(定義側がデフォルトグループ) List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class); assertThat(annos).hasSize(1); assertThat(annos.get(0).min()).isEqualTo("50"); } { // 存在するアノテーション(定義側がデフォルトグループ) List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, DefaultGroup.class); assertThat(annos).hasSize(1); assertThat(annos.get(0).min()).isEqualTo("50"); } } /** * アノテーションの取得 - 複数の同じアノテーション */ @Test public void testGetAnnotationsByGroup_repeatGroup() throws Exception { Field field = SampleBean.class.getDeclaredField("col4"); FieldAccessor property = new FieldAccessor(field, comparator); { // デフォルトのグループ List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, DefaultGroup.class); assertThat(annos).hasSize(1); { CsvNumberRange anno = annos.get(0); assertThat(anno.min()).isEqualTo("1"); } } { // グループの指定 List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, Group1.class); assertThat(annos).hasSize(1); { CsvNumberRange anno = annos.get(0); assertThat(anno.min()).isEqualTo("50"); } } { // 複数のグループの指定 List<CsvNumberRange> annos = property.getAnnotationsByGroup(CsvNumberRange.class, DefaultGroup.class, Group1.class); assertThat(annos).hasSize(2); { CsvNumberRange anno = annos.get(0); assertThat(anno.min()).isEqualTo("1"); } { CsvNumberRange anno = annos.get(1); assertThat(anno.min()).isEqualTo("50"); } } } /** * アノテーションの一覧の取得。 * <p>繰り返しのアノテーションの場合</p> */ @Test public void testGetAnnoationsByGroup_repetable() throws Exception { Field field = SampleBean.class.getDeclaredField("col4"); FieldAccessor property = new FieldAccessor(field, comparator); { // デフォルトのグループ List<Annotation> annos = property.getAnnotationsByGroup(); assertThat(annos).hasSize(1); { assertThat(annos.get(0)).isInstanceOf(CsvNumberRange.class); CsvNumberRange anno = (CsvNumberRange) annos.get(0); assertThat(anno.min()).isEqualTo("1"); assertThat(anno.max()).isEqualTo("100"); } } { // 複数のグループの指定 List<Annotation> annos = property.getAnnotationsByGroup(DefaultGroup.class, Group1.class); assertThat(annos).hasSize(2); { assertThat(annos.get(0)).isInstanceOf(CsvNumberRange.class); CsvNumberRange anno = (CsvNumberRange) annos.get(0); assertThat(anno.min()).isEqualTo("1"); assertThat(anno.max()).isEqualTo("100"); } { assertThat(annos.get(1)).isInstanceOf(CsvNumberRange.class); CsvNumberRange anno = (CsvNumberRange) annos.get(1); assertThat(anno.min()).isEqualTo("50"); assertThat(anno.max()).isEqualTo("200"); } } } /** * アノテーションの一覧の取得。 * <p>合成したアノテーションの場合</p> */ @Test public void tesGetAnnotationsByGroup_composition() throws Exception { Field field = SampleBean.class.getDeclaredField("col5"); FieldAccessor property = new FieldAccessor(field, comparator); { // デフォルトのグループ List<Annotation> annos = property.getAnnotationsByGroup(); assertThat(annos).hasSize(2); { assertThat(annos.get(0)).isInstanceOf(CsvRequire.class); CsvRequire anno = (CsvRequire) annos.get(0); assertThat(anno.message()).isEqualTo("ユーザ名は不正です。"); } { assertThat(annos.get(1)).isInstanceOf(CsvLengthMax.class); CsvLengthMax anno = (CsvLengthMax) annos.get(1); assertThat(anno.message()).isEqualTo("ユーザ名は不正です。"); assertThat(anno.value()).isEqualTo(64); } } { // 複数のグループの指定 List<Annotation> annos = property.getAnnotationsByGroup(DefaultGroup.class, Group1.class); assertThat(annos).hasSize(3); { assertThat(annos.get(0)).isInstanceOf(CsvRequire.class); CsvRequire anno = (CsvRequire) annos.get(0); assertThat(anno.message()).isEqualTo("ユーザ名は不正です。"); } { assertThat(annos.get(1)).isInstanceOf(CsvLengthMax.class); CsvLengthMax anno = (CsvLengthMax) annos.get(1); assertThat(anno.message()).isEqualTo("ユーザ名は不正です。"); assertThat(anno.order()).isEqualTo(1); assertThat(anno.value()).isEqualTo(20); } { assertThat(annos.get(2)).isInstanceOf(CsvLengthMax.class); CsvLengthMax anno = (CsvLengthMax) annos.get(2); assertThat(anno.message()).isEqualTo("ユーザ名は不正です。"); assertThat(anno.order()).isEqualTo(2); assertThat(anno.value()).isEqualTo(64); } } } @Test public void testHasAnnotation() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); assertThat(property.hasAnnotation(CsvColumn.class)).isTrue(); assertThat(property.hasAnnotation(CsvRequire.class)).isFalse(); } /** * アノテーションの判定 - グループ属性なしの場合 */ @Test public void testHasAnnotationByGroup_noGroup() throws Exception { Field field = SampleBean.class.getDeclaredField("col1"); FieldAccessor property = new FieldAccessor(field, comparator); { // 存在するアノテーション - groups属性を持たない assertThat(property.hasAnnotationByGroup(CsvColumn.class)).isFalse(); } { // 存在しないアノテーション - groups属性を持つ assertThat(property.hasAnnotationByGroup(CsvRequire.class)).isFalse(); } { // 存在するアノテーション(デフォルトグループ) - groups属性を持たない assertThat(property.hasAnnotationByGroup(CsvColumn.class, DefaultGroup.class)).isFalse(); } { // 存在しないアノテーション(デフォルトグループ) - groups属性を持つ assertThat(property.hasAnnotationByGroup(CsvRequire.class, DefaultGroup.class)).isFalse(); } } /** * アノテーションの判定 - グループ属性を持つ場合 */ @Test public void testHasAnnotationByGroup_group() throws Exception { Field field = SampleBean.class.getDeclaredField("col2"); FieldAccessor property = new FieldAccessor(field, comparator); { // グループ属性が定義されていないアノテーション assertThat(property.hasAnnotationByGroup(CsvColumn.class, Group1.class)).isFalse(); } { // 存在するアノテーション assertThat(property.hasAnnotationByGroup(CsvNumberRange.class, Group1.class)).isTrue(); } { // 存在しないアノテーション assertThat(property.hasAnnotationByGroup(CsvRequire.class, Group1.class)).isFalse(); } { // 存在しないグループ assertThat(property.hasAnnotationByGroup(CsvNumberRange.class, Group2.class)).isFalse(); } } @CsvBean private static class SampleBean { /** * グループ指定なし */ @CsvColumn(number=1, label="列1") @CsvLengthMax(value=100) private String col1; /** * グループ指定あり */ @CsvColumn(number=2) @CsvNumberRange(min="50", max="200", groups={Group1.class}) private int col2; /** * グループ指定あり - デフォルトグループ */ @CsvColumn(number=3) @CsvNumberRange(min="50", max="200", groups={DefaultGroup.class}) private int col3; /** * 同じアノテーションがある */ @CsvColumn(number=4) @CsvNumberRange(min="1", max="100") @CsvNumberRange(min="50", max="200", groups={Group1.class}) private LocalDate col4; /** * 合成したアノテーション */ @CsvColumn(number=5) @CsvUsername(message="ユーザ名は不正です。", maxLength=20) private String col5; } // テスト用のグループ private interface Group1 { } private interface Group2 { } // 合成したアノテーション @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @CsvComposition @CsvRequire @CsvLengthMax(value=64, order=2, groups={DefaultGroup.class}) @CsvLengthMax(value=10, order=1, groups={Group1.class}) public @interface CsvUsername { String message() default ""; @CsvOverridesAttribute(annotation=CsvLengthMax.class, name="value", index=1) int maxLength() default 0; } }