View Javadoc
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 }