View Javadoc
1   /*
2    * Copyright 2012 Olivier Godineau
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at http://www.apache.org/licenses/LICENSE-2.0
7    * 
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11   * License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  package olg.csv.bean.parser.impl;
15  
16  import java.lang.reflect.Constructor;
17  import java.lang.reflect.InvocationTargetException;
18  import java.text.DateFormat;
19  import java.text.SimpleDateFormat;
20  import java.util.Date;
21  import java.util.Locale;
22  
23  import olg.csv.base.UsageInvalideException;
24  import olg.csv.bean.Util;
25  import olg.csv.bean.parser.AbstractParser;
26  import olg.csv.bean.parser.ParseException;
27  
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  /**
32   * Parser dedicated in parsing String into date.
33   * 
34   */
35  public final class DateParser extends AbstractParser<Date> {
36  	/**
37  	 * the class Logger.
38  	 */
39  	private static final Logger LOGGER = LoggerFactory.getLogger(DateParser.class);
40  
41  	/**
42  	 * the date format to use to parse string as date.
43  	 */
44  	private final DateFormat dateFormat;
45  
46  	/**
47  	 * The concrete class the parser must return.
48  	 */
49  	private Class<? extends Date> concreteClass = null;
50  
51  	/**
52  	 * the date constructor to invoke on parsing.
53  	 */
54  	private Constructor<? extends Date> constructor = null;
55  
56  	@Override
57  	public Date parse(String str) {
58  		String errorMessage = "Error on parsing ";
59  		Date date = null;
60  		try {
61  			date = dateFormat.parse(str);
62  		} catch (java.text.ParseException e) {
63  			throw new ParseException(errorMessage + str, e);
64  		}
65  		if (concreteClass != null) {
66  			if (constructor == null) {
67  				try {
68  					Date date2 = ((Date) concreteClass.newInstance());
69  					date2.setTime(date.getTime());
70  					date = date2;
71  				} catch (InstantiationException e) {
72  					// Ne devrait pas arriver
73  					LOGGER.error(errorMessage, e);
74  					throw new ParseException(errorMessage + str, e);
75  				} catch (IllegalAccessException e) {
76  					// Ne devrait pas arriver
77  					LOGGER.error(errorMessage, e);
78  					throw new ParseException(errorMessage + str, e);
79  				}
80  
81  			} else {
82  				try {
83  					date = (Date) constructor.newInstance(date.getTime());
84  				} catch (IllegalArgumentException e) {
85  					// Ne devrait pas arriver
86  					LOGGER.error(errorMessage, e);
87  					throw new ParseException(errorMessage + str, e);
88  				} catch (InstantiationException e) {
89  					// Ne devrait pas arriver
90  					LOGGER.error(errorMessage, e);
91  					throw new ParseException(errorMessage + str, e);
92  				} catch (IllegalAccessException e) {
93  					// Ne devrait pas arriver
94  					LOGGER.error(errorMessage, e);
95  				} catch (InvocationTargetException e) {
96  					// Ne devrait pas arriver
97  					LOGGER.error(errorMessage, e);
98  					throw new ParseException(errorMessage + str, e);
99  				}
100 			}
101 		}
102 		return date;
103 
104 	}
105 
106 	/**
107 	 * Constructs a date parser.
108 	 * 
109 	 * @param format
110 	 *            the date format.
111 	 * @param concreteClass
112 	 *            Si <code>null</code>, la classe retournée lors du parsing sera
113 	 *            {@link java.util.Date}
114 	 * @param locale
115 	 *            the locale to apply to this DateParser. May be
116 	 *            <code>null</code>
117 	 */
118 	public DateParser(String format, Class<? extends Date> concreteClass, Locale locale) {
119 		super();
120 		if (format == null || "".equals(format.trim())) {
121 			throw new UsageInvalideException(
122 					"DateParser format argument must be conformed to SimpleDateFormat specifications");
123 		}
124 		try {
125 
126 			if (locale == null) {
127 				this.dateFormat = new SimpleDateFormat(format); // NOPMD by
128 																// olivier on
129 																// 07/02/12
130 																// 01:27
131 			} else {
132 				this.dateFormat = new SimpleDateFormat(format, locale);
133 			}
134 
135 		} catch (IllegalArgumentException ex) {
136 			throw new UsageInvalideException("DateParser argument " + format
137 					+ "must be conformed to SimpleDateFormat specifications", ex);
138 		}
139 		if (concreteClass != null) {
140 			if (checkconcreteClass(concreteClass)) {
141 				this.concreteClass = concreteClass;
142 				try {
143 					// Le constructeur prenant un temps en milliseconde en
144 					// paramètre
145 					constructor = concreteClass.getConstructor(new Class[]{long.class});
146 
147 				} catch (NoSuchMethodException e) {
148 					try {
149 						// On vérifie que le constructeur par défaut existe
150 						concreteClass.getConstructor(new Class[]{});
151 
152 					} catch (NoSuchMethodException e1) {
153 						throw new UsageInvalideException(
154 						// NOPMD by olivier on 28/01/12 15:21
155 								"DateParser argument [" + concreteClass + "] must have a constructor with no argument "
156 										+ "or a constructor with long parameter", e1);
157 					}
158 				}
159 
160 			} else {
161 				throw new UsageInvalideException(
162 						"DateParser constructor : concreteClass argument must extend java.util.Date"); // should
163 																										// not
164 																										// happen
165 			}
166 		}
167 
168 	}
169 
170 	/**
171 	 * Check if a class is a concrete Date class.
172 	 * 
173 	 * @param concreteClass
174 	 *            the class to check.
175 	 * @return true if the class is concrete and is a {@link Date} class or has
176 	 *         Date class as a super class.
177 	 */
178 	public boolean checkconcreteClass(Class<?> concreteClass) {
179 		boolean retour = false;
180 		if (concreteClass != null && Util.isConcrete(concreteClass) && !concreteClass.isArray()) {
181 			if (concreteClass.equals(Date.class)) {
182 				retour = true;
183 			} else {
184 				retour = checkconcreteClass(concreteClass.getSuperclass());
185 			}
186 
187 		}
188 		return retour;
189 
190 	}
191 
192 }