Utils.java
package com.github.mygreen.supercsv.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import com.github.mygreen.supercsv.annotation.PatternFlag;
import com.github.mygreen.supercsv.builder.BuildCase;
/**
* ユーティリティクラス。
*
* @version 2.2
* @author T.TSUCHIE
*
*/
public class Utils {
/**
* <a href="http://www.joda.org/joda-time/" target="_blank">Joda-Time</a>のライブラリが利用可能かどうか。
*/
public static final boolean ENABLED_LIB_JODA_TIME;
static {
boolean enabled;
try {
Class.forName("org.joda.time.LocalDateTime");
enabled = true;
} catch(ClassNotFoundException e) {
enabled = false;
}
ENABLED_LIB_JODA_TIME = enabled;
}
/**
* 文字列が空文字か判定する。
* @param str
* @return
*/
public static boolean isEmpty(final String str) {
if(str == null || str.isEmpty()) {
return true;
}
if(str.length() == 1) {
return str.charAt(0) == '\u0000';
}
return false;
}
/**
* 文字列が空文字でないか判定する。
* @param str
* @return
*/
public static boolean isNotEmpty(final String str) {
return !isEmpty(str);
}
/**
* コレクションが空か判定する。
* @param collection
* @return nullまたはサイズが0のときにtrueを返す。
*/
public static boolean isEmpty(final Collection<?> collection) {
if(collection == null || collection.isEmpty()) {
return true;
}
return false;
}
public static boolean isNotEmpty(final Collection<?> collection) {
return !isEmpty(collection);
}
/**
* 配列がが空か判定する。
* @param arrays
* @return nullまたは、配列のサイズが0のときにtrueを返す。
*/
public static boolean isEmpty(final Object[] arrays) {
if(arrays == null || arrays.length == 0) {
return true;
}
return false;
}
/**
* 配列が空でないか判定する
* @param arrays
* @return
*/
public static boolean isNotEmpty(final Object[] arrays) {
return !isEmpty(arrays);
}
/**
* 文字列形式のロケールをオブジェクトに変換する。
* <p>アンダーバーで区切った'ja_JP'を分解して、Localeに渡す。
* @since 1.2
* @param str
* @return 引数が空の時はデフォルトロケールを返す。
*/
public static Locale getLocale(final String str) {
if(isEmpty(str)) {
return Locale.getDefault();
}
if(!str.contains("_")) {
return new Locale(str);
}
final String[] split = str.split("_");
if(split.length == 2) {
return new Locale(split[0], split[1]);
} else {
return new Locale(split[0], split[1], split[2]);
}
}
/**
* アノテーションの指定した属性値を取得する。
* <p>アノテーションの修飾子はpublicである必要があります。</p>
* @param anno アノテーションのインスタンス
* @param attrName 属性名
* @param attrType 属性のタイプ。
* @return 属性を持たない場合、空を返す。
*/
@SuppressWarnings("unchecked")
public static <T> Optional<T> getAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
try {
final Method method = anno.annotationType().getMethod(attrName);
method.setAccessible(true);
if(!attrType.equals(method.getReturnType())) {
return Optional.empty();
}
final Object value = method.invoke(anno);
return Optional.of((T)value);
} catch (Exception e) {
return Optional.empty();
}
}
/**
* アノテーションの指定した属性値を持つかどうか判定する。
* <p>アノテーションの修飾子はpublicである必要があります。</p>
* @param anno アノテーションのインスタンス
* @param attrName 属性名
* @param attrType 属性のタイプ。
* @return 属性を持つ場合trueを返す。
*/
public static <T> boolean hasAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
return getAnnotationAttribute(anno, attrName, attrType).isPresent();
}
/**
* アノテーションの属性「cases」を持つ場合、指定した種類を持つか判定する。
* <p>属性「buildCase」を持たない場合、または、空の配列の場合は、必ずtrueを返します。</p>
*
* @param anno 判定対象のアノテーション。
* @param buildCase 組み立てる種類。
* @return trueの場合、指定した種類を含みます。
* @throws NullPointerException anno or buildCase is null.
*/
public static boolean containsBuildCase(final Annotation anno, final BuildCase buildCase) {
Objects.requireNonNull(anno);
Objects.requireNonNull(buildCase);
final Optional<BuildCase[]> attrCases = getAnnotationAttribute(anno, "cases", BuildCase[].class);
if(attrCases.isPresent()) {
final BuildCase[] casesValue = attrCases.get();
if(casesValue.length == 0) {
// 値が空の配列の場合
return true;
}
for(BuildCase value : casesValue) {
if(value == buildCase) {
return true;
}
}
return false;
}
// 属性を持たない場合
return true;
}
/**
* <a href="http://www.joda.org/joda-time/" target="_blank">Joda-Time</a>のライブラリが利用可能かどうか。
* @return {@literal true}利用可能。
*/
public static boolean isEnabledJodaTime() {
return ENABLED_LIB_JODA_TIME;
}
/**
* プリミティブ型の初期値を取得する。
* @param type プリミティブ型のクラス型。
* @return 非プリミティブ型や該当するクラスがない場合はnullを返す。
* @throws NullPointerException type is null.
*/
public static Object getPrimitiveDefaultValue(final Class<?> type) {
Objects.requireNonNull(type, "type should not be null.");
if(!type.isPrimitive()) {
return null;
} else if(boolean.class.isAssignableFrom(type)) {
return false;
} else if(char.class.isAssignableFrom(type)) {
return '\u0000';
} else if(byte.class.isAssignableFrom(type)) {
return (byte)0;
} else if(short.class.isAssignableFrom(type)) {
return (short)0;
} else if(int.class.isAssignableFrom(type)) {
return 0;
} else if(long.class.isAssignableFrom(type)) {
return 0l;
} else if(float.class.isAssignableFrom(type)) {
return 0.0f;
} else if(double.class.isAssignableFrom(type)) {
return 0.0d;
}
return null;
}
/**
* 文字列配列の結合
* @param array1
* @param array2
* @return 結合した配列。引数のどちらからnullの場合は、cloneした配列を返します。
*/
public static String[] concat(final String[] array1, final String[] array2) {
if(array1 == null || array1.length == 0) {
return clone(array2);
} else if(array2 == null || array2.length == 0) {
return clone(array1);
}
final String[] joinedArray = new String[array1.length + array2.length];
System.arraycopy(array1, 0, joinedArray, 0, array1.length);
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
return joinedArray;
}
/**
* 文字列の配列をクローンします。
* @since 2.2
* @param array クローン対象の配列
* @return クローンした配列。引数がnullの場合は、nullを返します。
*/
public static String[] clone(final String[] array) {
if (array == null) {
return null;
}
return array.clone();
}
/**
* コレクションを配列に変換する。
* @param collection 変換対象のコレクション。
* @return 変換した配列。
* @throws NullPointerException collection is null.
*/
public static int[] toArray(final Collection<Integer> collection) {
Objects.requireNonNull(collection);
final int size = collection.size();
final int[] array = new int[size];
int i=0;
for(Integer value : collection) {
array[i] = value;
i++;
}
return array;
}
/**
* 正規表現のフラグを組み立てる。
* @param flags 正規表現の列挙型のフラグ
* @return
*/
public static int buildRegexFlags(final PatternFlag[] flags) {
int intFlag = 0;
for(PatternFlag flag : flags) {
intFlag = intFlag | flag.getValue();
}
return intFlag;
}
/**
* 先頭の文字を小文字にする。
* @param str
* @return 引数がnull、空文字の場合、そのまま返す。
*/
public static String uncapitalize(final String str) {
final int strLen;
if(str == null || (strLen = str.length()) == 0) {
return str;
}
return new StringBuilder(strLen)
.append(String.valueOf(str.charAt(0)).toLowerCase())
.append(str.substring(1))
.toString();
}
}