View Javadoc
1   /*
2    * Copyright 2013 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.annotations.processor;
15  
16  import java.lang.reflect.Field;
17  import java.lang.reflect.InvocationTargetException;
18  import java.lang.reflect.Method;
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Map.Entry;
24  
25  import olg.csv.base.csv.CSVSettings;
26  import olg.csv.base.ods.ODSSettings;
27  import olg.csv.bean.IBeanProcessor;
28  import olg.csv.bean.IPropertyProcessor;
29  import olg.csv.bean.IRowProcessor;
30  import olg.csv.bean.annotations.CSVProperty;
31  import olg.csv.bean.annotations.Column;
32  import olg.csv.bean.annotations.Embedded;
33  import olg.csv.bean.annotations.ODSProperty;
34  import olg.csv.bean.annotations.Param;
35  import olg.csv.bean.annotations.RowBean;
36  import olg.csv.bean.impl.BeanProcessor;
37  import olg.csv.bean.impl.CellProcessor;
38  import olg.csv.bean.impl.RowProcessor;
39  import olg.csv.bean.parser.AbstractParser;
40  import olg.csv.bean.parser.ParseException;
41  
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  /**
45   * This class is responsible for processing the @RowBean annotation.
46   * 
47   * @author Olivier Godineau
48   * 
49   * @param <T>
50   *            the type this processor deals with
51   */
52  public final class RowBeanProcessor<T> {
53  	/**
54  	 * Class logger.
55  	 */
56  	private static final Logger LOGGER = LoggerFactory.getLogger(RowBeanProcessor.class);
57  
58  	/**
59  	 * ODSProperties allowed on Reading process.
60  	 */
61  	private ODSPropertyType[] ODSReadingProperties = ODSPropertyType.values();
62  	/**
63  	 * ODS Properties allowed on Writing process.
64  	 */
65  	private ODSPropertyType[] ODSWritingProperties = { ODSPropertyType.SHEETNAME, ODSPropertyType.BEGIN_AT_ROW,
66  			ODSPropertyType.BEGIN_AT_COLUMN, ODSPropertyType.HEADERS};
67  	/**
68  	 * CSV Properties allowed on Reading.
69  	 */
70  	private CSVPropertyType[] CSVReadingProperties = { CSVPropertyType.DELIMITER, CSVPropertyType.SEPARATOR,
71  			CSVPropertyType.CHARSETNAME, CSVPropertyType.HEADERS};
72  	/**
73  	 * CSV Properties allowed on Writing.
74  	 */
75  	private CSVPropertyType[] CSVWritingProperties = { CSVPropertyType.DELIMITER, CSVPropertyType.SEPARATOR,
76  			CSVPropertyType.CHARSETNAME, CSVPropertyType.LINE_SEPARATOR, CSVPropertyType.HEADERS};
77  
78  	/**
79  	 * 
80  	 * ODS Property list.
81  	 * 
82  	 */
83  	private enum ODSPropertyType {
84  		/**
85  		 * 
86  		 */
87  		HEADERS(ODSProperty.HEADERS, "withHeaders", new AbstractParser<Boolean>() {
88  
89  			@Override
90  			public Boolean parse(String str) {
91  				if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false")) {
92  					return Boolean.valueOf(str);
93  				} else {
94  					LOGGER.error("{} ODS Property only supports \"true\" or \"false\" value", ODSProperty.HEADERS);
95  					throw new ParseException();
96  				}
97  			}
98  		}),
99  		/**
100 		 * 
101 		 */
102 		SHEETNUM(ODSProperty.SHEETNUM, "sheetNum", new AbstractParser<Integer>() {
103 
104 			@Override
105 			public Integer parse(String str) {
106 				try {
107 					return Integer.valueOf(str);
108 				} catch (NumberFormatException ex) {
109 					LOGGER.error("{} ODS Property only supports integer value", ODSProperty.SHEETNUM);
110 					throw new ParseException();
111 				}
112 			}
113 
114 		}),
115 		/**
116 		 * 
117 		 */
118 		SHEETNAME(ODSProperty.SHEETNAME, "sheetName", null),
119 		/**
120 		 * 
121 		 */
122 		BEGIN_AT_ROW(ODSProperty.BEGIN_AT_ROW, "beginAtRow", new AbstractParser<Integer>() {
123 			@Override
124 			public Integer parse(String str) {
125 				try {
126 					return Integer.valueOf(str);
127 				} catch (NumberFormatException ex) {
128 					LOGGER.error("{} ODS Property only supports integer value", ODSProperty.BEGIN_AT_ROW);
129 					throw new ParseException();
130 				}
131 			}
132 		}),
133 
134 		/**
135 		 * 
136 		 */
137 		END_AT_ROW(ODSProperty.END_AT_ROW, "endAtRow", new AbstractParser<Integer>() {
138 			@Override
139 			public Integer parse(String str) {
140 				try {
141 					return Integer.valueOf(str);
142 				} catch (NumberFormatException ex) {
143 					LOGGER.error("{} ODS Property only supports integer value", ODSProperty.END_AT_ROW);
144 					throw new ParseException();
145 				}
146 			}
147 		}),
148 
149 		/**
150 		 * 
151 		 */
152 		BEGIN_AT_COLUMN(ODSProperty.BEGIN_AT_COLUMN, "beginAtColumn", null),
153 		/**
154 		 * 
155 		 */
156 
157 		END_AT_COLUMN(ODSProperty.END_AT_COLUMN, "endAtColumn", null);
158 
159 		/**
160 		 * param name.
161 		 */
162 		private String code;
163 		/**
164 		 * param value parser.
165 		 */
166 		private AbstractParser<?> parser;
167 		/**
168 		 * Method to set the property.
169 		 */
170 		private Method setter;
171 
172 		/**
173 		 * the property this option sets.
174 		 */
175 		private String property;
176 
177 		/**
178 		 * 
179 		 * @param code
180 		 *            param name.
181 		 * @param property
182 		 *            ODSSettings property to set.
183 		 * @param parser
184 		 *            parser to convert string to ODSSettings property type.
185 		 */
186 		private ODSPropertyType(String code, String property, AbstractParser<?> parser) {
187 			this.code = code;
188 			this.parser = parser;
189 			this.property = property;
190 			Method[] methods = ODSSettings.class.getMethods();
191 
192 			String setterName = "set" + property.substring(0, 1).toUpperCase() + (property.substring(1));
193 
194 			for (Method methode : methods) {
195 				if (methode.getName().equals(setterName) && methode.getParameterTypes().length == 1) {
196 					this.setter = methode;
197 					break;
198 				}
199 			}
200 
201 		}
202 		/**
203 		 * Identify the Property by its code.
204 		 * 
205 		 * @param code
206 		 *            the code
207 		 * @return the property
208 		 */
209 		static ODSPropertyType getByCode(String code) {
210 			ODSPropertyType retour = null;
211 			for (ODSPropertyType type : ODSPropertyType.values()) {
212 				if (type.code.equals(code)) {
213 					retour = type;
214 					break;
215 				}
216 			}
217 			return retour;
218 		}
219 
220 		/**
221 		 * Set the ODSSettings.
222 		 * 
223 		 * @param settings
224 		 *            the settings to set.
225 		 * @param value
226 		 *            the value.
227 		 * @return the ODSSettings setted.
228 		 * @throws AnnotationProcessorException
229 		 *             if an error occurs during parsing the value.
230 		 */
231 		ODSSettings setParam(ODSSettings settings, String value) throws AnnotationProcessorException {
232 
233 			try {
234 				setter.invoke(settings, (parser != null ? parser.parse(value) : value));
235 			} catch (IllegalAccessException e) {
236 				LOGGER.error("Hmm, I thought it couldn't happen", e);
237 			} catch (IllegalArgumentException e) {
238 				LOGGER.error("Hmm, I thought it couldn't happen", e);
239 			} catch (InvocationTargetException e) {
240 				LOGGER.error("ODSSettings error on {} setting ", property, e.getTargetException());
241 				throw new AnnotationProcessorException();
242 			} catch (ParseException e) {
243 				throw new AnnotationProcessorException();
244 			}
245 			return settings;
246 		}
247 	};
248 
249 	/**
250 	 * 
251 	 * CSV Property list.
252 	 * 
253 	 */
254 	private enum CSVPropertyType {
255 		/**
256 		 * 
257 		 */
258 		HEADERS(CSVProperty.HEADERS, "withHeaders", new AbstractParser<Boolean>() {
259 
260 			@Override
261 			public Boolean parse(String str) {
262 				if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false")) {
263 					return Boolean.valueOf(str);
264 				} else {
265 					LOGGER.error("{} CSV Property only supports \"true\" or \"false\" value, not [{}]",
266 							CSVProperty.HEADERS, str);
267 					throw new ParseException();
268 				}
269 			}
270 		}
271 
272 		),
273 		/**
274 		 * 
275 		 */
276 		SEPARATOR(CSVProperty.SEPARATOR, "separator", new AbstractParser<Character>() {
277 			@Override
278 			public Character parse(String str) {
279 				Character retour = null;
280 
281 				if (str.trim().length() != 1) {
282 					LOGGER.error("{} CSVProperty only supports String as char, not [{}]", CSVProperty.SEPARATOR, str);
283 					throw new ParseException();
284 				}
285 				retour = str.trim().charAt(0);
286 
287 				return retour;
288 			}
289 		}),
290 
291 		/**
292 		 * 
293 		 */
294 		DELIMITER(CSVProperty.DELIMITER, "delimiter", new AbstractParser<Character>() {
295 			@Override
296 			public Character parse(String str) {
297 				Character retour = null;
298 
299 				if (str.trim().length() != 1) {
300 					LOGGER.error("{} CSVProperty only supports String as char, not [{}]", CSVProperty.SEPARATOR, str);
301 					throw new ParseException();
302 				}
303 				retour = str.trim().charAt(0);
304 
305 				return retour;
306 
307 			}
308 		}),
309 		/**
310 		 * 
311 		 */
312 		CHARSETNAME(CSVProperty.CHARSETNAME, "charsetName", null),
313 		/**
314 				 * 
315 				 */
316 		LINE_SEPARATOR(CSVProperty.LINE_SEPARATOR, "lineSeparator", null);
317 
318 		/**
319 		 * param name.
320 		 */
321 		private String code;
322 
323 		/**
324 		 * param value parser.
325 		 */
326 		private AbstractParser<?> parser;
327 		/**
328 		 * Method to set property.
329 		 */
330 		private Method setter;
331 		/**
332 		 * Property this option sets.
333 		 */
334 		private String property;
335 
336 		/**
337 		 * 
338 		 * @param code
339 		 *            param name.
340 		 * @param property
341 		 *            ODSSettings property to set.
342 		 * @param parser
343 		 *            parser to convert string to ODSSettings property type.
344 		 */
345 		private CSVPropertyType(String code, String property, AbstractParser<?> parser) {
346 			this.code = code;
347 			this.parser = parser;
348 			this.property = property;
349 
350 			Method[] methods = CSVSettings.class.getMethods();
351 
352 			String setterName = "set" + property.substring(0, 1).toUpperCase() + (property.substring(1));
353 
354 			for (Method methode : methods) {
355 				if (methode.getName().equals(setterName) && methode.getParameterTypes().length == 1) {
356 					this.setter = methode;
357 					break;
358 				}
359 			}
360 		}
361 		/**
362 		 * Identify a property by its code.
363 		 * 
364 		 * @param code
365 		 *            the code
366 		 * @return the property
367 		 */
368 		public static CSVPropertyType getByCode(String code) {
369 			CSVPropertyType retour = null;
370 			for (CSVPropertyType type : CSVPropertyType.values()) {
371 				if (type.code.equals(code)) {
372 					retour = type;
373 					break;
374 				}
375 			}
376 			return retour;
377 		}
378 
379 		/**
380 		 * Set the CVSSettings.
381 		 * 
382 		 * @param settings
383 		 *            the settings to set.
384 		 * @param value
385 		 *            the value.
386 		 * @return the CSVSettings setted.
387 		 * @throws AnnotationProcessorException
388 		 *             on setting the value to the property
389 		 */
390 		public CSVSettings setParam(CSVSettings settings, String value) throws AnnotationProcessorException {
391 
392 			try {
393 				setter.invoke(settings, (parser != null ? parser.parse(value) : value));
394 			} catch (IllegalAccessException e) {
395 				LOGGER.error("Hmm, I thought it couldn't happen", e);
396 			} catch (IllegalArgumentException e) {
397 				LOGGER.error("Hmm, I thought it couldn't happen", e);
398 			} catch (InvocationTargetException e) {
399 				LOGGER.error("CSVSettings error on {} setting ", property, e.getTargetException());
400 				throw new AnnotationProcessorException();
401 			} catch (ParseException e) {
402 				throw new AnnotationProcessorException();
403 			}
404 			return settings;
405 		}
406 	};
407 
408 	/**
409 	 * The class of the type.
410 	 */
411 	private Class<T> clazz;
412 
413 	/**
414 	 * Processor responsible for processing @Column annotations placed on the fields of the class.
415 	 */
416 	private ColumnProcessor<T> columnProcessor;
417 
418 	/**
419 	 * Processor responsible for processing @Embedded annotations placed on the fields of the class.
420 	 */
421 	private EmbeddedProcessor<T> embeddedProcessor;
422 
423 	/**
424 	 * Constructor.
425 	 * 
426 	 * @param clazz
427 	 *            the T class.
428 	 */
429 	public RowBeanProcessor(Class<T> clazz) {
430 		super();
431 		this.clazz = clazz;
432 		this.columnProcessor = new ColumnProcessor<T>(clazz);
433 		this.embeddedProcessor = new EmbeddedProcessor<T>(clazz);
434 	}
435 
436 	/**
437 	 * Returns if T has RowBean annotation.
438 	 * 
439 	 * @return true if the T class has RowBean annotation.
440 	 */
441 	public boolean hasRowBeanAnnotation() {
442 		return clazz.getAnnotation(RowBean.class) != null;
443 	}
444 	/**
445 	 * Returns ODSSettings for reading identified from the RowBean annotation of the class otherwise default Reading ODS
446 	 * settings.
447 	 * 
448 	 * @return the ODSSettings
449 	 * @throws AnnotationProcessorException
450 	 *             if error occurs during annotation processing.
451 	 */
452 	public ODSSettings getReadingODSSettings() throws AnnotationProcessorException {
453 		RowBean rowBean = clazz.getAnnotation(RowBean.class);
454 		Param[] odsReadingParams = rowBean.ODSReadingParams();
455 		return getODSSettings(odsReadingParams, ODSReadingProperties, "ODSReadingParam");
456 
457 	}
458 
459 	/**
460 	 * Returns ODSSettings for writing identified from the RowBean annotation of the class otherwise default writing ODS
461 	 * settings.
462 	 * 
463 	 * @return the ODSSettings
464 	 * @throws AnnotationProcessorException
465 	 *             if an error occurs during settings identification.
466 	 */
467 	public ODSSettings getWritingODSSettings() throws AnnotationProcessorException {
468 		RowBean rowBean = clazz.getAnnotation(RowBean.class);
469 		Param[] odsWritingParams = rowBean.ODSWritingParams();
470 		return getODSSettings(odsWritingParams, ODSWritingProperties, "ODSWritingParam");
471 
472 	}
473 
474 	/**
475 	 * Returns CSVSettings for reading identified from the RowBean annotation of the class otherwise default Reading CSV
476 	 * settings.
477 	 * 
478 	 * @return the CSVSettings
479 	 * @throws AnnotationProcessorException
480 	 *             if an error occurs during settings identification.
481 	 */
482 	public CSVSettings getReadingCSVSettings() throws AnnotationProcessorException {
483 		RowBean rowBean = clazz.getAnnotation(RowBean.class);
484 		Param[] csvReadinggParams = rowBean.CSVReadingParams();
485 		return getCSVSettings(csvReadinggParams, CSVReadingProperties, "CSVReadingParam");
486 
487 	}
488 	/**
489 	 * Returns CSVSettings for writing identified from the RowBean annotation of the class otherwise default writing CSV
490 	 * settings.
491 	 * 
492 	 * @return the CSVSettings
493 	 * @throws AnnotationProcessorException
494 	 *             if an error occurs during settings identification.
495 	 */
496 	public CSVSettings getWritingCSVSettings() throws AnnotationProcessorException {
497 		RowBean rowBean = clazz.getAnnotation(RowBean.class);
498 		Param[] csvWritingParams = rowBean.CSVWritingParams();
499 		return getCSVSettings(csvWritingParams, CSVWritingProperties, "CSVWritingParam");
500 	}
501 
502 	/**
503 	 * Build a BeanProcessor from annotations setted on the class this processor deals with.
504 	 * 
505 	 * @return the beanProcessor
506 	 * @throws AnnotationProcessorException
507 	 *             if error occurs during annotation processing.
508 	 */
509 	public IBeanProcessor<T> getBeanProcessor() throws AnnotationProcessorException {
510 
511 		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
512 		List<IPropertyProcessor<T>> propertyProcessors = new ArrayList<IPropertyProcessor<T>>();
513 		boolean noError = getReadingProcessor(0, propertyProcessors, map);
514 		BeanProcessor<T> beanProcessor = new BeanProcessor<T>(this.clazz);
515 
516 		for (Entry<Integer, Integer> entry : map.entrySet()) {
517 			if (entry.getValue() > 1) {
518 				LOGGER.error("For column {}, {} fields match. Only one is supported", entry.getKey(), entry.getValue());
519 				noError = false;
520 			}
521 		}
522 
523 		if (noError) {
524 			beanProcessor.addAll(propertyProcessors);
525 			return beanProcessor;
526 		} else {
527 			throw new AnnotationProcessorException(
528 					"Some error occured on BeanProcessor loading. See logs for more details");
529 		}
530 
531 	}
532 	/**
533 	 * Build a RowProcessor from annotations setted on the class this processor deals with.
534 	 * 
535 	 * @return the RowProcessor
536 	 * @throws AnnotationProcessorException
537 	 *             if error occurs during annotation processing.
538 	 */
539 	public IRowProcessor<T> getRowProcessor() throws AnnotationProcessorException {
540 		Map<Integer, List<CellProcessor<T>>> map = new HashMap<Integer, List<CellProcessor<T>>>();
541 		boolean noError = getWritingProcessor(map);
542 		List<CellProcessor<T>> cellProcessors = new ArrayList<CellProcessor<T>>();
543 
544 		if (noError) {
545 
546 			for (Entry<Integer, List<CellProcessor<T>>> entry : map.entrySet()) {
547 				// COntrole un processor par num de colonne.
548 				if (entry.getValue().size() > 1) {
549 					LOGGER.error("For column {}, {} fields match. Only one is supported", entry.getKey(), entry
550 							.getValue().size());
551 					noError = false;
552 				} else {
553 					cellProcessors.add(entry.getValue().iterator().next());
554 				}
555 			}
556 		}
557 		if (noError) {
558 			return new RowProcessor<T>(cellProcessors);
559 		} else {
560 			throw new AnnotationProcessorException(
561 					"Some error occured on RowProcessor loading. See logs for more details");
562 		}
563 	}
564 
565 	/**
566 	 * Complete a map with the cell Processors identified on the annotated fields of the class (and superclass).
567 	 * 
568 	 * @param map
569 	 *            the map to complete with the CellProcessor built from column annotation setted on the class fields.
570 	 *            the keys are the cell num target of the cellProcessor.
571 	 * @return true if no error occurs.
572 	 */
573 	protected boolean getWritingProcessor(Map<Integer, List<CellProcessor<T>>> map) {
574 		if (hasRowBeanAnnotation()) {
575 			return getWritingProcessor(this.clazz, map);
576 		} else {
577 			LOGGER.error("@RowBean Annotation not found on {} class", this.clazz.getSimpleName());
578 			return false;
579 		}
580 	}
581 
582 	/**
583 	 * Collect the property processors identified by annotation setted on the fields (@Column and @Embedded) of the
584 	 * class and its super class (if annoted with @RowBean).
585 	 * 
586 	 * @param translate
587 	 *            index from which begin the column numerotation
588 	 * @param processors
589 	 *            the processor list to complete
590 	 * @param map
591 	 *            the map to complete. this map shows for each cell num the count of the property processors setted on.
592 	 * @return true if no error occurs.
593 	 */
594 	protected boolean getReadingProcessor(int translate, List<IPropertyProcessor<T>> processors,
595 			Map<Integer, Integer> map) {
596 		if (hasRowBeanAnnotation()) {
597 			return getReadingProcessor(this.clazz, translate, processors, map);
598 		} else {
599 			LOGGER.error("@RowBean Annotation not found on {} class", this.clazz.getSimpleName());
600 			return false;
601 		}
602 	}
603 
604 	/**
605 	 * Collects cell processors from column and embedded annotation setted on a class if annoted with RowBean
606 	 * annotation. Collects cell processors from super class if annoted with RowBean annotation.
607 	 * 
608 	 * @param beanClass
609 	 *            the bean class.
610 	 * @param map
611 	 *            the map to complete with the CellProcessor built from column annotation setted on the field. the keys
612 	 *            are the cell num target of the cellProcessor.
613 	 * @return true if no error occurs.
614 	 */
615 	private boolean getWritingProcessor(Class<? super T> beanClass, Map<Integer, List<CellProcessor<T>>> map) {
616 		boolean noError = true;
617 
618 		if (beanClass.getAnnotation(RowBean.class) != null) {
619 
620 			if (beanClass.getSuperclass() != null) {
621 				noError &= getWritingProcessor(beanClass.getSuperclass(), map);
622 			}
623 
624 			Field[] fields = beanClass.getDeclaredFields();
625 
626 			for (Field field : fields) {
627 				if (!checkField(field, beanClass)) {
628 					noError = false;
629 					continue;
630 				}
631 
632 				noError &= this.columnProcessor.getWritingProcessor(field, map);
633 
634 				noError &= this.embeddedProcessor.getWritingProcessor(field, map);
635 
636 			}
637 		}
638 
639 		return noError;
640 
641 	}
642 
643 	/**
644 	 * Find the property processors identified on a class if annoted with @RowBean and from its super class if annoted
645 	 * with @RowBean. The processor are read from the @Column and @Embedded annotation setted on its fields.
646 	 * 
647 	 * @param beanClass
648 	 *            the bean class.
649 	 * @param translate
650 	 *            index from which begin the column numerotation
651 	 * @param processors
652 	 *            the list to complete
653 	 * @param map
654 	 *            the map to complete. this map shows for each cell num the count of the property processors setted on.
655 	 * @return true if no error occurs.
656 	 */
657 	private boolean getReadingProcessor(Class<? super T> beanClass, int translate,
658 			List<IPropertyProcessor<T>> processors, Map<Integer, Integer> map) {
659 		boolean noError = true;
660 
661 		if (beanClass.getAnnotation(RowBean.class) != null) {
662 			if (beanClass.getSuperclass() != null) {
663 
664 				noError &= getReadingProcessor(beanClass.getSuperclass(), translate, processors, map);
665 			}
666 		}
667 
668 		Field[] fields = beanClass.getDeclaredFields();
669 
670 		for (Field field : fields) {
671 			if (!checkField(field, beanClass)) {
672 				noError = false;
673 				continue;
674 			}
675 
676 			noError &= this.columnProcessor.getReadingProcessor(translate, field, processors, map);
677 			noError &= this.embeddedProcessor.getReadingProcessor(translate, field, processors, map);
678 
679 		}
680 		return noError;
681 	}
682 
683 	/**
684 	 * Check if a field hasn't both column annotation and Embedded annotation.
685 	 * 
686 	 * @param field
687 	 *            the field
688 	 * @param beanClass
689 	 *            the class declaring the field.
690 	 * @return true if the field hasn't both column annotation and Embedded annotation.
691 	 */
692 	private boolean checkField(Field field, Class<? super T> beanClass) {
693 		if (field.getAnnotation(Column.class) != null && field.getAnnotation(Embedded.class) != null) {
694 			LOGGER.error("{}.{} : A field must not have both the column annotation and the embedded annotation",
695 					beanClass.getSimpleName(), field.getName());
696 			return false;
697 		}
698 
699 		return true;
700 	}
701 
702 	/**
703 	 * Identifies a param as an allowed ODSPropertyType.
704 	 * 
705 	 * @param param
706 	 *            the param.
707 	 * @param permittedProperties
708 	 *            allowed ODSPropertyTypes.
709 	 * @return the ODSPropertyType or null if the param is not identify as a permitted properties.
710 	 */
711 	private ODSPropertyType identifyPermittedProperty(Param param, ODSPropertyType[] permittedProperties) {
712 		ODSPropertyType propertyType = ODSPropertyType.getByCode(param.name());
713 		if (propertyType != null) {
714 			boolean find = false;
715 			for (ODSPropertyType permittedProperty : permittedProperties) {
716 				if (propertyType == permittedProperty) {
717 					find = true;
718 					break;
719 				}
720 			}
721 			propertyType = (find ? propertyType : null);
722 		}
723 		return propertyType;
724 	}
725 
726 	/**
727 	 * Returns ODSSettings corresponding to ODS params of a process.
728 	 * 
729 	 * @param odsParams
730 	 *            the ODS Params
731 	 * @param properties
732 	 *            the ODS Properties which are allowed for the process
733 	 * @param type
734 	 *            String identifying the process
735 	 * @return the corresonding settings.
736 	 * @throws AnnotationProcessorException
737 	 *             if errors occur
738 	 */
739 	private ODSSettings getODSSettings(Param[] odsParams, ODSPropertyType[] properties, String type)
740 			throws AnnotationProcessorException {
741 
742 		ODSSettings settings = new ODSSettings();
743 		boolean exceptionOnProcess = false;
744 
745 		if (odsParams != null && odsParams.length > 0) {
746 			for (Param param : odsParams) {
747 				ODSPropertyType propertyType = identifyPermittedProperty(param, properties);
748 
749 				if (propertyType != null) {
750 					if ("".equals(param.value())) {
751 						LOGGER.warn("{}@RowBean : empty string  is not a legal value for {} {}", new Object[] {
752 								this.clazz.getSimpleName(), param.name(), type});
753 					} else {
754 						try {
755 							propertyType.setParam(settings, param.value());
756 						} catch (AnnotationProcessorException ex) {
757 							exceptionOnProcess = true;
758 						}
759 					}
760 				} else {
761 					LOGGER.warn("{}@RowBean : {} is not a legal {}, it will be ignored",
762 							new Object[] { this.clazz.getSimpleName(), param.name(), type});
763 				}
764 			}
765 		}
766 		if (exceptionOnProcess) {
767 			throw new AnnotationProcessorException("See logs for more details");
768 		}
769 		return settings;
770 	}
771 
772 	/**
773 	 * Identifies a param as an allowed CSVPropertyType.
774 	 * 
775 	 * @param param
776 	 *            the param.
777 	 * @param permittedProperties
778 	 *            allowed CSVPropertyTypes.
779 	 * @return the CSVPropertyType or null if the param is not identify as a permitted properties.
780 	 */
781 	private CSVPropertyType identifyPermittedProperty(final Param param, CSVPropertyType[] permittedProperties) {
782 		CSVPropertyType propertyType = CSVPropertyType.getByCode(param.name());
783 		if (propertyType != null) {
784 			boolean find = false;
785 			for (CSVPropertyType permittedProperty : permittedProperties) {
786 				if (propertyType == permittedProperty) {
787 					find = true;
788 					break;
789 				}
790 			}
791 			propertyType = (find ? propertyType : null);
792 		}
793 		return propertyType;
794 	}
795 
796 	/**
797 	 * Products the CSVSettings corresponding to params of a process.
798 	 * 
799 	 * @param csvParams
800 	 *            the params to translate as CSVSettings
801 	 * @param properties
802 	 *            the CSVProperties which are allowed for the specifig process
803 	 * @param type
804 	 *            String identifying the process
805 	 * @return the CSVSettings corresponding to the param of the process
806 	 * @throws AnnotationProcessorException
807 	 *             if errors occur.
808 	 */
809 	private CSVSettings getCSVSettings(final Param[] csvParams, CSVPropertyType[] properties, String type)
810 			throws AnnotationProcessorException {
811 
812 		CSVSettings settings = new CSVSettings();
813 		boolean exceptionOnProcess = false;
814 
815 		if (csvParams != null && csvParams.length > 0) {
816 			for (Param param : csvParams) {
817 				CSVPropertyType propertyType = identifyPermittedProperty(param, properties);
818 
819 				if (propertyType != null) {
820 					if ("".equals(param.value())) {
821 						LOGGER.warn("{}@RowBean : empty string  is not a legal value for {} {}", new Object[] {
822 								this.clazz.getSimpleName(), param.name(), type});
823 					} else {
824 						try {
825 							propertyType.setParam(settings, param.value());
826 						} catch (AnnotationProcessorException ex) {
827 							exceptionOnProcess = true;
828 						}
829 					}
830 				} else {
831 					LOGGER.warn("{}@RowBean : {} is not a legal {}, it will be ignored",
832 							new Object[] { this.clazz.getSimpleName(), param.name(), type});
833 				}
834 			}
835 		}
836 		if (exceptionOnProcess) {
837 			throw new AnnotationProcessorException("See logs for more details");
838 		}
839 		return settings;
840 	}
841 
842 }