View Javadoc
1   package com.github.mygreen.supercsv.util;
2   
3   import java.lang.annotation.Annotation;
4   import java.lang.reflect.Method;
5   import java.util.Collection;
6   import java.util.Locale;
7   import java.util.Map;
8   import java.util.Objects;
9   import java.util.Optional;
10  
11  import com.github.mygreen.supercsv.annotation.PatternFlag;
12  import com.github.mygreen.supercsv.builder.BuildCase;
13  
14  
15  /**
16   * ユーティリティクラス。
17   * 
18   * @version 2.2
19   * @author T.TSUCHIE
20   *
21   */
22  public class Utils {
23      
24      /**
25       * <a href="http://www.joda.org/joda-time/" target="_blank">Joda-Time</a>のライブラリが利用可能かどうか。
26       */
27      public static final boolean ENABLED_LIB_JODA_TIME;
28      static {
29          boolean enabled;
30          try {
31              Class.forName("org.joda.time.LocalDateTime");
32              enabled = true;
33          } catch(ClassNotFoundException e) {
34              enabled = false;
35          }
36          ENABLED_LIB_JODA_TIME = enabled;
37      }
38      
39      /**
40       * 文字列が空文字か判定する。
41       * @param str
42       * @return
43       */
44      public static boolean isEmpty(final String str) {
45          if(str == null || str.isEmpty()) {
46              return true;
47          }
48          
49          if(str.length() == 1) {
50              return str.charAt(0) == '\u0000';
51          }
52          
53          return false;
54      }
55      
56      /**
57       * 文字列が空文字でないか判定する。
58       * @param str
59       * @return
60       */
61      public static boolean isNotEmpty(final String str) {
62          return !isEmpty(str);
63      }
64      
65      /**
66       * コレクションが空か判定する。
67       * @param collection
68       * @return nullまたはサイズが0のときにtrueを返す。
69       */
70      public static boolean isEmpty(final Collection<?> collection) {
71          if(collection == null || collection.isEmpty()) {
72              return true;
73          }
74          
75          return false;
76      }
77      
78      public static boolean isNotEmpty(final Collection<?> collection) {
79          return !isEmpty(collection);
80      }
81      
82      /**
83       * Mapが空か判定する。
84       * @param map
85       * @return nullまたはサイズが0のときにtrueを返す。
86       */
87      public static boolean isEmpty(final Map<?, ?> map) {
88          if(map == null || map.isEmpty()) {
89              return true;
90          }
91          
92          return false;
93      }
94      
95      public static boolean isNotEmpty(final Map<?, ?> map) {
96          return !isEmpty(map);
97      }
98      
99      /**
100      * 配列がが空か判定する。 
101      * @param arrays
102      * @return nullまたは、配列のサイズが0のときにtrueを返す。
103      */
104     public static boolean isEmpty(final Object[] arrays) {
105         if(arrays == null || arrays.length == 0) {
106             return true;
107         }
108         
109         return false;
110     }
111     
112     /**
113      * 配列が空でないか判定する
114      * @param arrays
115      * @return
116      */
117     public static boolean isNotEmpty(final Object[] arrays) {
118         return !isEmpty(arrays);
119     }
120     
121     /**
122      * 文字列形式のロケールをオブジェクトに変換する。
123      * <p>アンダーバーで区切った'ja_JP'を分解して、Localeに渡す。
124      * @since 1.2
125      * @param str
126      * @return 引数が空の時はデフォルトロケールを返す。
127      */
128     public static Locale getLocale(final String str) {
129         
130         if(isEmpty(str)) {
131             return Locale.getDefault();
132         }
133         
134         if(!str.contains("_")) {
135             return new Locale(str);
136         }
137         
138         final String[] split = str.split("_");
139         if(split.length == 2) {
140             return new Locale(split[0], split[1]);
141             
142         } else {
143             return new Locale(split[0], split[1], split[2]);
144         }
145         
146     }
147     
148     /**
149      * アノテーションの指定した属性値を取得する。
150      * <p>アノテーションの修飾子はpublicである必要があります。</p>
151      * @param anno アノテーションのインスタンス
152      * @param attrName 属性名
153      * @param attrType 属性のタイプ。
154      * @return 属性を持たない場合、空を返す。
155      */
156     @SuppressWarnings("unchecked")
157     public static <T> Optional<T> getAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
158         
159         try {
160             final Method method = anno.annotationType().getMethod(attrName);
161             method.setAccessible(true);
162             if(!attrType.equals(method.getReturnType())) {
163                 return Optional.empty();
164             }
165             
166             final Object value = method.invoke(anno);
167             return Optional.of((T)value);
168             
169         } catch (Exception e) {
170             return Optional.empty();
171         }
172         
173     }
174     
175     /**
176      * アノテーションの指定した属性値を持つかどうか判定する。
177      * <p>アノテーションの修飾子はpublicである必要があります。</p>
178      * @param anno アノテーションのインスタンス
179      * @param attrName 属性名
180      * @param attrType 属性のタイプ。
181      * @return 属性を持つ場合trueを返す。
182      */
183     public static <T>  boolean hasAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
184         
185         return getAnnotationAttribute(anno, attrName, attrType).isPresent();
186         
187     }
188     
189     /**
190      * アノテーションの属性「cases」を持つ場合、指定した種類を持つか判定する。
191      * <p>属性「buildCase」を持たない場合、または、空の配列の場合は、必ずtrueを返します。</p>
192      * 
193      * @param anno 判定対象のアノテーション。
194      * @param buildCase 組み立てる種類。
195      * @return trueの場合、指定した種類を含みます。
196      * @throws NullPointerException anno or buildCase is null.
197      */
198     public static boolean containsBuildCase(final Annotation anno, final BuildCase buildCase) {
199         
200         Objects.requireNonNull(anno);
201         Objects.requireNonNull(buildCase);
202         
203         final Optional<BuildCase[]> attrCases = getAnnotationAttribute(anno, "cases", BuildCase[].class);
204         if(attrCases.isPresent()) {
205             final BuildCase[] casesValue = attrCases.get();
206             if(casesValue.length == 0) {
207                 // 値が空の配列の場合
208                 return true;
209             }
210             
211             for(BuildCase value : casesValue) {
212                 if(value == buildCase) {
213                     return true;
214                 }
215             }
216             
217             return false;
218         }
219         
220         // 属性を持たない場合
221         return true;
222     }
223     
224     /**
225      * <a href="http://www.joda.org/joda-time/" target="_blank">Joda-Time</a>のライブラリが利用可能かどうか。
226      * @return {@literal true}利用可能。
227      */
228     public static boolean isEnabledJodaTime() {
229         return ENABLED_LIB_JODA_TIME;
230     }
231     
232     /**
233      * プリミティブ型の初期値を取得する。
234      * @param type プリミティブ型のクラス型。
235      * @return 非プリミティブ型や該当するクラスがない場合はnullを返す。
236      * @throws NullPointerException type is null.
237      */
238     public static Object getPrimitiveDefaultValue(final Class<?> type) {
239         
240         Objects.requireNonNull(type, "type should not be null.");
241         
242         if(!type.isPrimitive()) {
243             return null;
244             
245         } else if(boolean.class.isAssignableFrom(type)) {
246             return false;
247             
248         } else if(char.class.isAssignableFrom(type)) {
249             return '\u0000';
250             
251         } else if(byte.class.isAssignableFrom(type)) {
252             return (byte)0;
253             
254         } else if(short.class.isAssignableFrom(type)) {
255             return (short)0;
256             
257         } else if(int.class.isAssignableFrom(type)) {
258             return 0;
259             
260         } else if(long.class.isAssignableFrom(type)) {
261             return 0l;
262             
263         } else if(float.class.isAssignableFrom(type)) {
264             return 0.0f;
265             
266         } else if(double.class.isAssignableFrom(type)) {
267             return 0.0d;
268         }
269         
270         return null;
271         
272     }
273     
274     /**
275      * 文字列配列の結合
276      * @param array1
277      * @param array2
278      * @return 結合した配列。引数のどちらからnullの場合は、cloneした配列を返します。
279      */
280     public static String[] concat(final String[] array1, final String[] array2) {
281         
282         if(array1 == null || array1.length == 0) {
283             return clone(array2);
284             
285         } else if(array2 == null || array2.length == 0) {
286             return clone(array1);
287         }
288         
289         final String[] joinedArray = new String[array1.length + array2.length];
290         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
291         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
292         return joinedArray;
293         
294     }
295     
296     /**
297      * 文字列の配列をクローンします。
298      * @since 2.2
299      * @param array クローン対象の配列
300      * @return クローンした配列。引数がnullの場合は、nullを返します。
301      */
302     public static String[] clone(final String[] array) {
303         if (array == null) {
304             return null;
305         }
306         return array.clone();
307     }
308     
309     /**
310      * コレクションを配列に変換する。
311      * @param collection 変換対象のコレクション。
312      * @return 変換した配列。
313      * @throws NullPointerException collection is null.
314      */
315     public static int[] toArray(final Collection<Integer> collection) {
316         Objects.requireNonNull(collection);
317         
318         final int size = collection.size();
319         final int[] array = new int[size];
320         
321         int i=0;
322         for(Integer value : collection) {
323             array[i] = value;
324             i++;
325         }
326         
327         return array;
328     }
329     
330     /**
331      * 正規表現のフラグを組み立てる。
332      * @param flags 正規表現の列挙型のフラグ
333      * @return
334      */
335     public static int buildRegexFlags(final PatternFlag[] flags) {
336         
337         int intFlag = 0;
338         for(PatternFlag flag : flags) {
339             intFlag = intFlag | flag.getValue();
340         }
341         
342         return intFlag;
343         
344     }
345     
346     /**
347      * 先頭の文字を小文字にする。
348      * @param str
349      * @return 引数がnull、空文字の場合、そのまま返す。
350      */
351     public static String uncapitalize(final String str) {
352         final int strLen;
353         if(str == null || (strLen = str.length()) == 0) {
354             return str;
355         }
356         
357         return new StringBuilder(strLen)
358             .append(String.valueOf(str.charAt(0)).toLowerCase())
359             .append(str.substring(1))
360             .toString();
361     }
362     
363     /**
364      * 文字列をトリムする。
365      * @param value トリム対象の文字
366      * @param trimmed トリムするかどうか。
367      * @return トリミングした結果。
368      */
369     public static String trim(final String value, final boolean trimmed) {
370         if(!trimmed || value == null) {
371             return value;
372         }
373 
374         return value.trim();
375 
376     }
377     
378     /**
379      * 文字列をbooleanに変換します。
380      * 
381      * @param value 変換対象の値。
382      * @param defaultValue 変換対象がnull or 空文字の時のデフォルト値。
383      * @return 引数がnullのとき、falseを返します。
384      */
385     public static boolean toBoolean(final String value, final boolean defaultValue) {
386         String text = trim(value, true);
387         if(isEmpty(text)) {
388             return defaultValue;
389         }
390         
391         return Boolean.valueOf(text.toLowerCase());
392     }
393     
394 }