nablarch.test.NablarchTestUtils Maven / Gradle / Ivy
The newest version!
package nablarch.test;
import nablarch.core.util.Builder;
import nablarch.core.util.StringUtil;
import nablarch.core.util.annotation.Published;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static nablarch.core.util.Builder.*;
/**
* ユーティリティクラス。
*
* @author Tsuyoshi Kawasaki
*/
@Published(tag = "architect")
public final class NablarchTestUtils {
/** カンマを示す正規表現 */
private static final Pattern COMMA = Pattern.compile(",");
/**
* 指定された文字列をカンマ(,)で分割し、配列を生成する。
* 指定された文字列が、nullまたは空文字列の場合には、サイズ0の配列を返却する。
*
* @param str 文字列
* @return 変換した配列
*/
public static String[] makeArray(String str) {
return (StringUtil.isNullOrEmpty(str))
? new String[0]
: COMMA.split(str);
}
/**
* LRUアルゴリズムのMap実装を生成する。
*
* @param maxSize Mapの最大サイズ
* @param キーの型
* @param 値の型
* @return LRUアルゴリズムのMap実装
*/
public static Map createLRUMap(final int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException(Builder.concat(
"argument maxSize must not be less than zero. but was [", maxSize, "]"));
}
return new LinkedHashMap(maxSize, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > maxSize;
}
};
}
/**
* プライベートコンストラクタを起動
*
* @param target テスト対象クラス
* @param テスト対象クラスの型
*/
public static void invokePrivateDefaultConstructor(Class target) {
if (target == null) {
throw new IllegalArgumentException("argument must not be null.");
}
// プライベートデフォルトコンストラクタを取得
Constructor constructor = getPrivateDefaultConstructor(target);
// コンストラクタ起動
invoke(constructor);
}
/**
* プライベートデフォルトコンストラクタを取得する
*
* @param target 取得対象クラス
* @param 取得対象クラスの型
* @return コンストラクタ
*/
private static Constructor getPrivateDefaultConstructor(Class target) {
Constructor constructor = getDefaultConstructor(target);
if (!Modifier.isPrivate(constructor.getModifiers())) {
throw new IllegalArgumentException(
"constructor is NOT private scope. class=[" + target.getName() + "]");
}
return constructor;
}
/**
* デフォルトコンストラクタを取得する
*
* @param target 取得対象クラス
* @param 取得対象クラスの型
* @return コンストラクタ
*/
private static Constructor getDefaultConstructor(Class target) {
try {
return target.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
"can't find default constructor. class=[" + target.getName() + "]", e);
}
}
/**
* コンストラクタを起動する。
*
* @param constructor 起動対象コンストラクタ
*/
private static void invoke(Constructor> constructor) {
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (Exception e) {
throw new IllegalStateException("invoking constructor failed.", e);
}
}
/**
* リストの各要素を大文字に変換する。
*
* @param original 元のリスト
* @return 変換後のリスト
*/
public static List toUpperCase(List original) {
if (original == null || original.isEmpty()) {
return original;
}
List uppers = new ArrayList(original.size());
for (String e : original) {
uppers.add(e.toUpperCase());
}
return uppers;
}
/**
* 拡張子を除いたファイル名を取得する。
*
* @param fileName 元のファイル名
* @return 拡張子を除いたファイル名
*/
public static String getFileNameWithoutSuffix(String fileName) {
// null、空文字の場合そのまま返却
if (StringUtil.isNullOrEmpty(fileName)) {
return fileName;
}
int indexOfSuffix = fileName.indexOf(".");
return (indexOfSuffix == -1)
? fileName
: fileName.substring(0, indexOfSuffix);
}
/**
* 配列をSetに変換する。
*
* @param array 変換対象の配列
* @param 配列の型
* @return 変換後のSet
*/
public static Set asSet(T... array) {
return (array == null)
? null
: new HashSet(Arrays.asList(array));
}
/**
* コレクションがnullまたは空であるか判定する。
*
* @param collection 判定対象
* @return nullまたは空の場合、真
*/
public static boolean isNullOrEmpty(Collection> collection) {
return collection == null || collection.isEmpty();
}
/**
* 正規化されたパスへ変換する。
*
* @param path 変換対象
* @return 正規化されたパス
*/
public static String toCanonicalPath(String path) {
return toCanonical(new File(path)).getPath();
}
/**
* 正規化されたファイルへ変換する。
*
* @param file 変換対象
* @return 正規化されたファイル
*/
public static File toCanonical(File file) {
if (file == null) {
throw new IllegalArgumentException("file must not be null.");
}
try {
return file.getCanonicalFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* ファイルを削除する。
* ディレクトリが指定された場合、そのディレクトリとその配下全てを削除する。
* 指定されたファイルが存在しない場合は何もしない。
*
* @param target 削除対象ファイル
*/
public static void deleteFile(File target) {
if (target == null || !target.exists()) {
return;
}
if (target.isDirectory()) {
for (File child : target.listFiles()) {
deleteFile(child);
}
}
boolean success = target.delete();
if (!success) {
throw new IllegalStateException(
"can't delete " + target.getAbsolutePath());
}
}
/**
* リスト末尾の空要素(nullまたは空文字)を取り除く。(破壊的メソッド)
*
* @param list リスト
* @return 引数のリスト自身
*/
public static List trimTail(List list) {
if (list == null) {
return null;
}
// 末尾からループ
for (int i = list.size() - 1; i >= 0; i--) {
if (StringUtil.hasValue(list.get(i))) {
break; // 空でない要素があれば終了
}
list.remove(i); // 空要素を削除
}
return list;
}
/**
* リスト末尾の空要素(nullまたは空文字)を取り除く。(非破壊的メソッド)
*
* @param orig 元となるリスト
* @return 末尾の空要素が取り除かれた新しいリスト
*/
public static List trimTailCopy(List orig) {
if (orig == null) {
return null;
}
List copied = new ArrayList(orig);
return trimTail(copied);
}
/**
* 文字列の長さを閾値まで制限する。
* 文字列長が閾値を超えていた場合、先頭から閾値までの文字列を返却する。
* そうでない場合は、元の文字列をそのまま返却する。
*
* @param string 対象文字列
* @param threshold 閾値(0以上)
* @return 短縮された文字列
*/
public static String limit(String string, int threshold) {
if (string == null) {
throw new IllegalArgumentException("string must not be null.");
}
if (threshold < 0) {
throw new IllegalArgumentException("threshold must not be negative. but was [" + threshold + "]");
}
// 閾値を超えていれば短縮する。
return string.length() > threshold
? string.substring(0, threshold)
: string;
}
/** 円マークのパターン */
private static final Pattern YEN_PATTERN = Pattern.compile(Pattern.quote("\\"));
/** エスケープ後の円マークのパターン */
private static final Pattern ESCAPED_YEN_PATTERN = Pattern.compile(Pattern.quote("\\\\"));
/** エスケープ後の円マーク */
private static final String ESCAPED_YEN = Matcher.quoteReplacement("\\\\");
/** エスケープ解除後の円マーク */
private static final String UNESCAPED_YEN = Matcher.quoteReplacement("\\");
/**
* 文字列をエスケープする。
*
* @param orig エスケープ対象文字列
* @return エスケープ後の文字列
*/
public static String escape(String orig) {
return YEN_PATTERN.matcher(orig).replaceAll(ESCAPED_YEN); // \ -> \\
}
/**
* 文字列のエスケープを解除する。
*
* @param escaped エスケープされた文字列
* @return エスケープ解除された文字列
*/
public static String unescapeYen(String escaped) {
return ESCAPED_YEN_PATTERN.matcher(escaped).replaceAll(UNESCAPED_YEN);
}
/** プライベートコンストラクタ */
private NablarchTestUtils() {
}
/**
* リフレクションAPIを使用する際の簡易的なテンプレートクラス。
* 例外が発生した場合の典型的な対処を提供する。
*
* @author T.Kawasaki
*/
public abstract static class ReflectionOperation {
/** 実行する。 */
public final void execute() {
try {
operate();
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new RuntimeException(cause);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* サブクラス、無名クラスでリフレクション操作を行う。
*
* @throws Exception 例外
*/
protected abstract void operate() throws Exception;
}
/**
* ファイルを出力ストリームとしてオープンする。
*
* @param outFilePath 出力先ファイルパス
* @return 出力ストリーム
*/
public static BufferedOutputStream openAsOutputStream(String outFilePath) {
return openAsOutputStream(outFilePath, false);
}
/**
* ファイルを出力ストリームとしてオープンする。
*
* @param outFilePath 出力先ファイルパス
* @param deleteOnExit プログラム終了後にファイルを削除するか
* @return 出力ストリーム
*/
public static BufferedOutputStream openAsOutputStream(String outFilePath, boolean deleteOnExit) {
File outFile = new File(outFilePath);
touch(outFile);
if (deleteOnExit) {
outFile.deleteOnExit();
}
return openAsOutputStream(outFile);
}
/**
* ファイルを出力ストリームとしてオープンする。
*
* @param outFile 出力先ファイル
* @return 出力ストリーム
*/
public static BufferedOutputStream openAsOutputStream(File outFile) {
try {
return new BufferedOutputStream(new FileOutputStream(outFile));
} catch (IOException e) {
throw new RuntimeException("can't open file. [" + outFile.getAbsolutePath() + "]", e);
}
}
/**
* ファイルを作成する。
*
* @param file 作成対象ファイル
*/
public static void touch(File file) {
if (file.exists()) {
return;
}
try {
boolean success = file.createNewFile();
if (!success) {
throw new RuntimeException("can't create file. [" + file + "]");
}
} catch (IOException e) {
throw new RuntimeException("can't create file. [" + file + "]");
}
}
/**
* Mapに必須のキーが含まれていることを表明する。
*
* @param msgOnFail 表明失敗時のメッセージ
* @param target 調査対象となるのMap
* @param requiredKeys 必須のキー
* @param キーの型
*/
public static void assertContainsRequiredKeys(String msgOnFail, Map target, Set requiredKeys) {
Set required = new HashSet(requiredKeys);
Set actual = target.keySet();
required.removeAll(actual);
if (required.isEmpty()) {
return; // 必須カラムが全て存在する。
}
throw new IllegalArgumentException(concat(
msgOnFail,
" ;required column(s) not found ", required));
}
/**
* Throwableサブクラスのメッセージを取得する。
* ネストされた例外がある場合はそのメッセージも取得する。
*
* @param target メッセージ取得対象の{@link Throwable}
* @return メッセージ
*/
public static String getMessages(Throwable target) {
if (target == null) {
throw new IllegalArgumentException("argument must not be null.");
}
return getThrowableMessage(target, new ArrayList());
}
/**
* @param target メッセージ取得対象の{@link Throwable}
* @param accumulator 蓄積されたメッセージ
* @return メッセージ
* @see #getMessages(Throwable)
*/
private static String getThrowableMessage(Throwable target, List accumulator) {
accumulator.add(target.getMessage());
Throwable cause = target.getCause();
boolean hasMoreCause = (cause != null && cause != target);
return hasMoreCause
? getThrowableMessage(cause, accumulator) // recursive call.
: Builder.join(accumulator, " ; ");
}
/**
* 文字列を整数値に変換する。
*
* @param intExpression 数字
* @return 変換後の整数値
* @throws IllegalArgumentException 文字列が整数値として解釈できない場合
*/
public static int parseInt(String intExpression) throws IllegalArgumentException {
try {
return Integer.parseInt(intExpression);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(Builder.concat(
"argument must be numeric.",
" but was [", intExpression, "] "), e);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy