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