1 package com.github.mygreen.supercsv.builder.time;
2
3 import java.time.ZoneId;
4 import java.time.format.DateTimeFormatter;
5 import java.time.format.ResolverStyle;
6 import java.time.temporal.TemporalAccessor;
7 import java.util.Locale;
8 import java.util.Optional;
9 import java.util.TimeZone;
10
11 import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeRange;
12 import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeMin;
13 import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeMax;
14 import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat;
15 import com.github.mygreen.supercsv.builder.AbstractProcessorBuilder;
16 import com.github.mygreen.supercsv.builder.Configuration;
17 import com.github.mygreen.supercsv.builder.FieldAccessor;
18 import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeRangeFactory;
19 import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeMinFactory;
20 import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeMaxFactory;
21 import com.github.mygreen.supercsv.cellprocessor.format.TemporalFormatWrapper;
22 import com.github.mygreen.supercsv.cellprocessor.format.TextFormatter;
23 import com.github.mygreen.supercsv.util.Utils;
24
25
26
27
28
29
30
31
32
33
34
35 public abstract class AbstractTemporalProcessorBuilder<T extends TemporalAccessor & Comparable<? super T>>
36 extends AbstractProcessorBuilder<T> {
37
38 public AbstractTemporalProcessorBuilder() {
39 super();
40 }
41
42 @Override
43 protected void init() {
44 super.init();
45
46
47 registerForConstraint(CsvDateTimeRange.class, new DateTimeRangeFactory<>());
48 registerForConstraint(CsvDateTimeMin.class, new DateTimeMinFactory<>());
49 registerForConstraint(CsvDateTimeMax.class, new DateTimeMaxFactory<>());
50
51 }
52
53
54
55
56
57
58
59
60 protected DateTimeFormatter createFormatter(final FieldAccessor field, final Configuration config) {
61
62 final Optional<CsvDateTimeFormat> formatAnno = field.getAnnotation(CsvDateTimeFormat.class);
63 if(!formatAnno.isPresent()) {
64 return DateTimeFormatter.ofPattern(getDefaultPattern());
65 }
66
67 String pattern = formatAnno.get().pattern();
68 if(pattern.isEmpty()) {
69 pattern = getDefaultPattern();
70 }
71
72 final ResolverStyle style = formatAnno.get().lenient() ? ResolverStyle.LENIENT : ResolverStyle.STRICT;
73 final Locale locale = Utils.getLocale(formatAnno.get().locale());
74 final ZoneId zone = formatAnno.get().timezone().isEmpty() ? ZoneId.systemDefault()
75 : TimeZone.getTimeZone(formatAnno.get().timezone()).toZoneId();
76
77 return DateTimeFormatter.ofPattern(pattern, locale)
78 .withResolverStyle(style)
79 .withZone(zone);
80
81 }
82
83 @SuppressWarnings("unchecked")
84 @Override
85 protected TextFormatter<T> getDefaultFormatter(final FieldAccessor field, final Configuration config) {
86
87 final Optional<CsvDateTimeFormat> formatAnno = field.getAnnotation(CsvDateTimeFormat.class);
88 final String pattern = getPattern(field);
89 final DateTimeFormatter formatter = createFormatter(field, config);
90
91 final TemporalFormatWrapper<T> wrapper = new TemporalFormatWrapper<>(formatter, (Class<T>)field.getType());
92 wrapper.setPattern(pattern);
93 formatAnno.ifPresent(a -> wrapper.setValidationMessage(a.message()));
94 return wrapper;
95
96 }
97
98
99
100
101
102
103
104
105
106 protected String getPattern(final FieldAccessor field) {
107 return field.getAnnotation(CsvDateTimeFormat.class)
108 .map(a -> a.pattern())
109 .filter(p -> !p.isEmpty())
110 .orElse(getDefaultPattern());
111 }
112
113
114
115
116
117
118 protected abstract String getDefaultPattern();
119
120 }