1 package org.supercsv.cellprocessor.joda;
2
3 import java.util.Locale;
4
5 import org.joda.time.format.DateTimeFormatter;
6 import org.supercsv.cellprocessor.CellProcessorAdaptor;
7 import org.supercsv.cellprocessor.ift.CellProcessor;
8 import org.supercsv.exception.SuperCsvCellProcessorException;
9 import org.supercsv.util.CsvContext;
10
11 /**
12 * Abstract base class for cell processors converting Joda types to Strings.
13 *
14 * @since 2.3.0
15 * @author James Bassett
16 * @param <T>
17 * the Joda type that the processor formats
18 */
19 public abstract class AbstractJodaFormattingProcessor<T> extends
20 CellProcessorAdaptor {
21
22 private final Class<T> jodaClass;
23
24 private final DateTimeFormatter formatter;
25
26 private final String pattern;
27
28 private final Locale locale;
29
30 /**
31 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
32 * which formats the Joda type as a String.
33 *
34 * @param jodaClass
35 * the Joda class that the processor formats
36 * @throws NullPointerException
37 * if jodaClass is null
38 */
39 public AbstractJodaFormattingProcessor(final Class<T> jodaClass) {
40 checkPreconditions(jodaClass);
41 this.jodaClass = jodaClass;
42 this.formatter = null;
43 this.pattern = null;
44 this.locale = null;
45
46 }
47
48 /**
49 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
50 * which formats the Joda type as a String, then calls the next processor in
51 * the chain.
52 *
53 * @param jodaClass
54 * the Joda class that the processor formats
55 * @param next
56 * next processor in the chain
57 * @throws NullPointerException
58 * if jodaClass or next is null
59 */
60 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
61 final CellProcessor next) {
62 super(next);
63 checkPreconditions(jodaClass);
64 this.jodaClass = jodaClass;
65 this.formatter = null;
66 this.pattern = null;
67 this.locale = null;
68
69 }
70
71 /**
72 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
73 * which formats the Joda type as a String using the supplied formatter.
74 *
75 * @param jodaClass
76 * the Joda class that the processor formats
77 * @param formatter
78 * the formatter to use
79 * @throws NullPointerException
80 * if jodaClass or formatter is null
81 */
82 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
83 final DateTimeFormatter formatter) {
84 checkPreconditions(jodaClass, formatter);
85 this.jodaClass = jodaClass;
86 this.formatter = formatter;
87 this.pattern = null;
88 this.locale = null;
89 }
90
91 /**
92 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
93 * which formats the Joda type as a String using the supplied formatter,
94 * then calls the next processor in the chain.
95 *
96 * @param jodaClass
97 * the Joda class that the processor formats
98 * @param formatter
99 * the formatter to use
100 * @param next
101 * the next processor in the chain
102 * @throws NullPointerException
103 * if jodaClass, formatter or next is null
104 */
105 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
106 final DateTimeFormatter formatter, final CellProcessor next) {
107 super(next);
108 checkPreconditions(jodaClass, formatter);
109 this.jodaClass = jodaClass;
110 this.formatter = formatter;
111 this.pattern = null;
112 this.locale = null;
113 }
114
115 /**
116 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
117 * which formats the Joda type as a String using the supplied pattern and
118 * the default locale.
119 *
120 * @param jodaClass
121 * the Joda class that the processor formats
122 * @param pattern
123 * the pattern to use
124 * @throws NullPointerException
125 * if jodaClass or pattern is null
126 */
127 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
128 final String pattern) {
129 this(jodaClass, pattern, (Locale) null);
130 }
131
132 /**
133 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
134 * which formats the Joda type as a String using the supplied pattern and
135 * the default locale, then calls the next processor in the chain.
136 *
137 * @param jodaClass
138 * the Joda class that the processor formats
139 * @param pattern
140 * the pattern to use
141 * @param next
142 * the next processor in the chain
143 * @throws NullPointerException
144 * if jodaClass, pattern or next is null
145 */
146 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
147 final String pattern, final CellProcessor next) {
148 this(jodaClass, pattern, (Locale) null, next);
149 }
150
151 /**
152 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
153 * which formats the Joda type as a String using the supplied pattern and
154 * the locale.
155 *
156 * @param jodaClass
157 * the Joda class that the processor formats
158 * @param pattern
159 * the pattern to use
160 * @param locale
161 * the locale to use (default used if <tt>null</tt>)
162 * @throws NullPointerException
163 * if jodaClass or pattern is null
164 */
165 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
166 final String pattern, final Locale locale) {
167 checkPreconditions(jodaClass, pattern);
168 this.jodaClass = jodaClass;
169 this.pattern = pattern;
170 this.locale = locale;
171 this.formatter = null;
172 }
173
174 /**
175 * Constructs a new <tt>AbstractJodaFormattingProcessor</tt> processor,
176 * which formats the Joda type as a String using the supplied pattern and
177 * the locale, then calls the next processor in the chain.
178 *
179 * @param jodaClass
180 * the Joda class that the processor formats
181 * @param pattern
182 * the pattern to use
183 * @param locale
184 * the locale to use (default used if <tt>null</tt>)
185 * @param next
186 * the next processor in the chain
187 * @throws NullPointerException
188 * if jodaClass, pattern or next is null
189 */
190 public AbstractJodaFormattingProcessor(final Class<T> jodaClass,
191 final String pattern, final Locale locale, final CellProcessor next) {
192 super(next);
193 checkPreconditions(jodaClass, pattern);
194 this.jodaClass = jodaClass;
195 this.pattern = pattern;
196 this.locale = locale;
197 this.formatter = null;
198 }
199
200 /**
201 * Checks the preconditions for creating a new
202 * AbstractJodaFormattingProcessor processor.
203 *
204 * @param jodaClass
205 * the Joda class
206 * @throws NullPointerException
207 * if jodaClass is null
208 */
209 private static void checkPreconditions(final Class<?> jodaClass) {
210 if (jodaClass == null) {
211 throw new NullPointerException("jodaClass should not be null");
212 }
213 }
214
215 /**
216 * Checks the preconditions for creating a new
217 * AbstractJodaFormattingProcessor processor.
218 *
219 * @param jodaClass
220 * the Joda class
221 * @param formatter
222 * the formatter
223 * @throws NullPointerException
224 * if jodaClass or formatter is null
225 */
226 private static void checkPreconditions(final Class<?> jodaClass,
227 final DateTimeFormatter formatter) {
228 if (jodaClass == null) {
229 throw new NullPointerException("jodaClass should not be null");
230 } else if (formatter == null) {
231 throw new NullPointerException("formatter should not be null");
232 }
233 }
234
235 /**
236 * Checks the preconditions for creating a new
237 * AbstractJodaFormattingProcessor processor.
238 *
239 * @param jodaClass
240 * the Joda class
241 * @param pattern
242 * the pattern
243 * @throws NullPointerException
244 * if jodaClass or pattern is null
245 */
246 private static void checkPreconditions(final Class<?> jodaClass,
247 final String pattern) {
248 if (jodaClass == null) {
249 throw new NullPointerException("jodaClass should not be null");
250 } else if (pattern == null) {
251 throw new NullPointerException("pattern should not be null");
252 }
253 }
254
255 /**
256 * {@inheritDoc}
257 *
258 * @throws SuperCsvCellProcessorException
259 * if value is null, not the correct type, or can't be formatted
260 */
261 public Object execute(final Object value, final CsvContext context) {
262 validateInputNotNull(value, context);
263 if (!(value.getClass().equals(jodaClass))) {
264 throw new SuperCsvCellProcessorException(jodaClass, value, context,
265 this);
266 }
267 final T jodaType = jodaClass.cast(value);
268 try {
269 if (formatter != null) {
270 return format(jodaType, formatter);
271 } else if (pattern != null) {
272 return format(jodaType, pattern, locale);
273 } else {
274 return format(jodaType);
275 }
276 } catch (IllegalArgumentException e) {
277 throw new SuperCsvCellProcessorException(
278 String.format("Failed to format value as a %s",
279 jodaClass.getSimpleName()), context, this, e);
280 }
281 }
282
283 /**
284 * Formats the Joda type as a String using a DateTimeFormatter.
285 *
286 * @param jodaType
287 * the Joda type to format
288 * @param formatter
289 * the formatter to use
290 * @return the formatted String
291 * @throws IllegalArgumentException
292 * if the Joda type couldn't be formatted
293 */
294 protected abstract String format(final T jodaType,
295 final DateTimeFormatter formatter);
296
297 /**
298 * Formats the Joda type as a String using the supplied pattern and
299 * (optional) locale.
300 *
301 * @param jodaType
302 * the Joda type to format
303 * @param pattern
304 * the pattern to use
305 * @param locale
306 * the (optional) locale
307 * @return the formatted String
308 * @throws IllegalArgumentException
309 * if the Joda type couldn't be formatted
310 */
311 protected abstract String format(final T jodaType, final String pattern,
312 final Locale locale);
313
314 /**
315 * Formats the Joda type as a String using the default pattern and locale.
316 *
317 * @param jodaType
318 * the Joda type to format
319 * @return the formatted String
320 * @throws IllegalArgumentException
321 * if the Joda type couldn't be formatted
322 */
323 protected abstract String format(final T jodaType);
324
325 }