1 package org.supercsv.cellprocessor.time;
2
3 import java.time.format.DateTimeFormatter;
4 import java.time.format.DateTimeParseException;
5 import java.time.temporal.TemporalAccessor;
6 import java.util.Objects;
7
8 import org.supercsv.cellprocessor.CellProcessorAdaptor;
9 import org.supercsv.cellprocessor.ift.CellProcessor;
10 import org.supercsv.cellprocessor.ift.StringCellProcessor;
11 import org.supercsv.exception.SuperCsvCellProcessorException;
12 import org.supercsv.util.CsvContext;
13
14 /**
15 * Abstract base class for cell processors converting Strings to {@link TemporalAccessor} types.
16 *
17 * @param <T> the {@link TemporalAccessor} type that the processor returns
18 * @author James Bassett
19 * @since 2.4.0
20 */
21 public abstract class AbstractTemporalAccessorParsingProcessor<T extends TemporalAccessor> extends CellProcessorAdaptor
22 implements StringCellProcessor {
23
24 private final DateTimeFormatter formatter;
25
26 /**
27 * Constructs a new <tt>AbstractTemporalAccessorParsingProcessor</tt> processor, which
28 * parses a String as a {@link TemporalAccessor} type.
29 */
30 public AbstractTemporalAccessorParsingProcessor() {
31 this.formatter = null;
32 }
33
34 /**
35 * Constructs a new <tt>AbstractTemporalAccessorParsingProcessor</tt> processor, which
36 * parses a String as a {@link TemporalAccessor} type, then calls the next processor in the
37 * chain.
38 *
39 * @param next the next processor in the chain
40 * @throws NullPointerException if next is null
41 */
42 public AbstractTemporalAccessorParsingProcessor(final CellProcessor next) {
43 super(next);
44 this.formatter = null;
45 }
46
47 /**
48 * Constructs a new <tt>AbstractTemporalAccessorParsingProcessor</tt> processor, which
49 * parses a String as a {@link TemporalAccessor} type using the supplied formatter.
50 *
51 * @param formatter the formatter used for parsing
52 * @throws NullPointerException if formatter is null
53 */
54 public AbstractTemporalAccessorParsingProcessor(final DateTimeFormatter formatter) {
55 checkPreconditions(formatter);
56 this.formatter = formatter;
57 }
58
59 /**
60 * Constructs a new <tt>AbstractTemporalAccessorParsingProcessor</tt> processor, which
61 * parses a String as a {@link TemporalAccessor} type using the supplied formatter, then calls
62 * the next processor in the chain.
63 *
64 * @param formatter the formatter used for parsing
65 * @param next the next processor in the chain
66 * @throws NullPointerException if formatter or next is null
67 */
68 public AbstractTemporalAccessorParsingProcessor(final DateTimeFormatter formatter, final CellProcessor next) {
69 super(next);
70 checkPreconditions(formatter);
71 this.formatter = formatter;
72 }
73
74 /**
75 * Checks the preconditions for creating a new AbstractTemporalAccessorParsingProcessor
76 * processor.
77 *
78 * @param formatter the formatter
79 * @throws NullPointerException if formatter is null
80 */
81 private static void checkPreconditions(final DateTimeFormatter formatter) {
82 Objects.requireNonNull(formatter, "formatter should not be null");
83 }
84
85 /**
86 * {@inheritDoc}
87 *
88 * @throws SuperCsvCellProcessorException if value is null or is not a String
89 */
90 public Object execute(final Object value, final CsvContext context) {
91 validateInputNotNull(value, context);
92 if( !(value instanceof String) ) {
93 throw new SuperCsvCellProcessorException(String.class, value, context, this);
94 }
95
96 final String string = (String) value;
97 final T result;
98 try {
99 if( formatter != null ) {
100 result = parse(string, formatter);
101 } else {
102 result = parse(string);
103 }
104 }
105 catch(DateTimeParseException e) {
106 throw new SuperCsvCellProcessorException("Failed to parse value", context, this, e);
107 }
108
109 return next.execute(result, context);
110 }
111
112 /**
113 * Parses the String into the appropriate {@link TemporalAccessor} type.
114 *
115 * @param string the string to parse
116 * @return the {@link TemporalAccessor} type
117 * @throws IllegalArgumentException if the string can't be parsed
118 */
119 protected abstract T parse(final String string);
120
121 /**
122 * Parses the String into the appropriate {@link TemporalAccessor} type, using the supplied
123 * formatter.
124 *
125 * @param string the string to parse
126 * @param formatter the formatter to use
127 * @return the {@link TemporalAccessor} type
128 * @throws IllegalArgumentException if the string can't be parsed
129 */
130 protected abstract T parse(final String string, final DateTimeFormatter formatter);
131
132 }