View Javadoc
1   /*
2    * Copyright 2013 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.orangesignal.csv.bean;
18  
19  import java.lang.reflect.InvocationTargetException;
20  import java.math.BigDecimal;
21  import java.math.BigInteger;
22  import java.text.DateFormat;
23  import java.util.Collections;
24  import java.util.Date;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  /**
29   * {@link CsvValueConverter} を実装したデフォルトのシンプルな実装クラスを提供します。
30   *
31   * @author Koji Sugisawa
32   */
33  public class SimpleCsvValueConverter implements CsvValueConverter {
34  
35  	/**
36  	 * プリミティブ型とプリミティブ型デフォルト値のマップです。
37  	 */
38  	private static final Map<Class<?>, Object> PRIMITIVE_DEFAULTS;
39  
40  	private static final Map<String, Boolean> BOOLEAN_DEFAULTS;
41  
42  	static {
43  		final Map<Class<?>, Object> primitiveMap = new HashMap<Class<?>, Object>();
44  		primitiveMap.put(Boolean.TYPE, Boolean.FALSE);
45  		primitiveMap.put(Byte.TYPE, Byte.valueOf((byte) 0));
46  		primitiveMap.put(Character.TYPE, Character.valueOf('\u0000'));
47  		primitiveMap.put(Short.TYPE, Short.valueOf((short) 0));
48  		primitiveMap.put(Integer.TYPE, Integer.valueOf(0));
49  		primitiveMap.put(Long.TYPE, Long.valueOf(0L));
50  		primitiveMap.put(Float.TYPE, Float.valueOf(0F));
51  		primitiveMap.put(Double.TYPE, Double.valueOf(0D));
52  		PRIMITIVE_DEFAULTS = Collections.unmodifiableMap(primitiveMap);
53  
54  		final Map<String, Boolean> booleanMap = new HashMap<String, Boolean>();
55  		putBooleanMap(booleanMap, "0", "1");
56  		putBooleanMap(booleanMap, "false", "true");
57  		putBooleanMap(booleanMap, "f", "t");
58  		putBooleanMap(booleanMap, "no", "yes");
59  		putBooleanMap(booleanMap, "n", "y");
60  		putBooleanMap(booleanMap, "off", "on");
61  		putBooleanMap(booleanMap, "x", "o");
62  		BOOLEAN_DEFAULTS = Collections.unmodifiableMap(booleanMap);
63  	}
64  
65  	private static void putBooleanMap(final Map<String, Boolean> map, final String falseValue, final String trueValue) {
66  		map.put(falseValue, Boolean.FALSE);
67  		map.put(trueValue, Boolean.TRUE);
68  	}
69  
70  	/**
71  	 * 日時書式を保持します。
72  	 */
73  	private DateFormat dateFormat;
74  
75  	/**
76  	 * デフォルトコンストラクタです。
77  	 */
78  	public SimpleCsvValueConverter() {
79  	}
80  
81  	/**
82  	 * 日時書式を返します。
83  	 * 
84  	 * @return 日時書式
85  	 */
86  	public DateFormat getDateFormat() { return dateFormat; }
87  
88  	/**
89  	 * 日時書式を設定します。
90  	 * 
91  	 * @param dateFormat 日時書式
92  	 */
93  	public void setDateFormat(final DateFormat dateFormat) { this.dateFormat = dateFormat; }
94  
95  	@Override
96  	public Object convert(final String str, final Class<?> type) {
97  		// 入力パラメータを検証します。
98  		if (type == null) {
99  			throw new IllegalArgumentException("Class must not be null");
100 		}
101 
102 		if (str == null) {
103 			if (type.isPrimitive()) {
104 				return PRIMITIVE_DEFAULTS.get(type);
105 			}
106 			return null;
107 		}
108 		if (type.equals(String.class)) {
109 			return str;
110 		}
111 
112 		if (type.equals(Boolean.TYPE) || type.equals(Boolean.class)) {
113 			for (final Map.Entry<String, Boolean> entry : BOOLEAN_DEFAULTS.entrySet()) {
114 				if (entry.getKey().equalsIgnoreCase(str)) {
115 					return entry.getValue();
116 				}
117 			}
118 		} else if (type.equals(Byte.TYPE) || type.equals(Byte.class)) {
119 			return Byte.valueOf(str);
120 //		} else if (type.equals(Character.TYPE) || type.equals(Character.class)) {
121 //			return Character.valueOf(str);
122 		} else if (type.equals(Short.TYPE) || type.equals(Short.class)) {
123 			return Short.valueOf(str);
124 		} else if (type.equals(Integer.TYPE) || type.equals(Integer.class)) {
125 			return Integer.valueOf(str);
126 		} else if (type.equals(Long.TYPE) || type.equals(Long.class)) {
127 			return Long.valueOf(str);
128 		} else if (type.equals(Float.TYPE) || type.equals(Float.class)) {
129 			return Float.valueOf(str);
130 		} else if (type.equals(Double.TYPE) || type.equals(Double.class)) {
131 			return Double.valueOf(str);
132 		} else if (type.equals(BigInteger.class)) {
133 			return new BigInteger(str);
134 		} else if (type.equals(Number.class) || type.equals(BigDecimal.class)) {
135 			return new BigDecimal(str);
136 		} else if (dateFormat != null && Date.class.isAssignableFrom(type)) {
137 			try {
138 				return type.getConstructor(Long.TYPE).newInstance(dateFormat.parse(str).getTime());
139 			} catch (Exception e) {
140 				throw new IllegalArgumentException(e.getMessage(), e);
141 			}
142 		} else if (Enum.class.isAssignableFrom(type)) {
143 			try {
144 				return type.getMethod("valueOf", String.class).invoke(null, str);
145 			} catch (final NoSuchMethodException e) {
146 				throw new IllegalArgumentException(String.format("Unknown convert type %s", type.getName()), e);
147 			} catch (final IllegalAccessException e) {
148 				throw new IllegalArgumentException(String.format("Unknown convert type %s", type.getName()), e);
149 			} catch (final InvocationTargetException e) {
150 				throw new IllegalArgumentException(String.format("Unknown convert type %s", type.getName()), e);
151 			}
152 		}
153 
154 		throw new IllegalArgumentException(String.format("Unknown convert type %s", type.getName()));
155 	}
156 
157 	@Override
158 	public String convert(final Object value) {
159 		if (value == null) {
160 			return null;
161 		}
162 		if (value instanceof Date && dateFormat != null) {
163 			return dateFormat.format(value);
164 		}
165 		return value.toString();
166 	}
167 
168 }