/*
* Aipo is a groupware program developed by TOWN, Inc.
* Copyright (C) 2004-2015 TOWN, Inc.
* http://www.aipo.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aimluck.commons.field;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.aimluck.commons.utils.ALStringUtil;
import com.aimluck.eip.util.ALLocalizationUtils;
/**
* 入力フィールドを表すクラス(文字列用)です。 <br />
*
*/
public class ALStringField extends ALAbstractField {
/**
*
*/
private static final long serialVersionUID = -5978839673623376818L;
/** 文字の種類(全て) */
public static final int TYPE_ALL = 0;
/** 文字の種類(半角英字) */
public static final int TYPE_ALPHABET = 1;
/** 文字の種類(半角数字) */
public static final int TYPE_NUMBER = 2;
/** 文字の種類(半角英数字) */
public static final int TYPE_ALPHABET_NUMBER = TYPE_ALPHABET | TYPE_NUMBER;
/** 文字の種類(半角カナ文字) */
public static final int TYPE_HANKAKUKANA = 4;
/** 文字の種類(半角英数字カナ文字) */
public static final int TYPE_ALPHABET_NUMBER_HANKAKUKANA =
TYPE_ALPHABET_NUMBER | TYPE_HANKAKUKANA;
/** 文字の種類(全角文字) */
public static final int TYPE_MULTIBYTE = 8;
/** 文字の種類(半角記号) */
public static final int TYPE_SYMBOL = 16;
/** 文字の種類(半角英数字記号) */
public static final int TYPE_ASCII = TYPE_ALPHABET_NUMBER | TYPE_SYMBOL;
public static final Pattern PATTERN = Pattern.compile("[\\u0000-\\uFFFF]*");
/** 文字の種類 */
protected int characterType = TYPE_ALL;
/** 文字列の長さ制限フラグ */
protected boolean limitLength = false;
/** 文字列の長さ(最小値) */
protected int minLength = 0;
/** 文字列の長さ(最大値) */
protected int maxLength = Integer.MAX_VALUE;
/** 入力フィールド値(文字列) */
protected String value = null;
/** 入力フィールド値の左右の空白を削除するかのフラグ */
protected boolean isTrimValue = true;
/**
* コンストラクタ
*
*/
public ALStringField() {
this(null);
}
/**
* コンストラクタ
*
* @param str
*/
public ALStringField(String str) {
setValue(str);
}
/**
* 文字列の種類を取得します。
*
* @return
*/
public int getCharacterType() {
return characterType;
}
/**
* 文字列の長さ(最小値)を取得します。
*
* @return
*/
public int getMinLength() {
return minLength;
}
/**
* 文字列の長さ(最大値)を取得します。
*
* @return
*/
public int getMaxLength() {
return maxLength;
}
/**
* 入力フィールド値を取得します。
*
* @return
*/
public String getValue() {
return value;
}
public String getURLEncodedValue() {
if (value == null) {
return "";
} else {
try {
return URLEncoder.encode(value, "utf-8");
} catch (UnsupportedEncodingException e) {
return "file";
}
}
}
/**
* 文字の種類を設定します。
*
* @param i
*/
public void setCharacterType(int i) {
characterType = i;
}
/**
* 文字列の長さ制限の有無を判定します。
*
* @return
*/
public boolean isLimitLength() {
return limitLength;
}
/**
* 入力フィールド値を設定します。
*
* @param str
*/
@Override
public void setValue(String str) {
if (str != null && isTrimValue) {
value = removeSpace(str);
} else {
value = str;
}
}
/**
* 文字列の長さ制限(最小値と最大値)を設定します。
*
* @param min
* @param max
*/
public void limitLength(int min, int max) {
if (max < min) {
throw new IllegalArgumentException();
}
minLength = min;
maxLength = max;
limitLength = true;
}
/**
* 文字列の長さ制限(最小値)を設定します。
*
* @param min
*/
public void limitMinLength(int min) {
if (maxLength < min) {
throw new IllegalArgumentException();
}
minLength = min;
limitLength = true;
}
/**
* 文字列の長さ制限(最大値)を設定します。
*
* @param max
*/
public void limitMaxLength(int max) {
if (max < minLength) {
throw new IllegalArgumentException();
}
maxLength = max;
limitLength = true;
}
/**
* 入力フィールド値の左右の空白を取り除くかのフラグを設定します。
*
* @param bool
*/
public void setTrim(boolean bool) {
isTrimValue = bool;
}
/**
* 入力フィールド値の左右の空白を取り除くかどうかを判定します。
*
* @return
*/
public boolean isTrim() {
return isTrimValue;
}
/**
* 入力フィールド値を検証します。
*
* @param msgList
* @return
*/
public boolean validate(List<String> msgList) {
if (msgList == null) {
msgList = new ArrayList<String>();
}
if (!isNotNullValue()) {
if (isNotNull()) {
// 必須入力属性で値が設定されていない場合
msgList.add(ALLocalizationUtils.getl10nFormat(
"COMMONS_FIELD_INPUT_NAME_SPAN",
fieldName));
return false;
}
} else {
if (!isValidCharacterType()) {
// 設定されている文字セット以外の文字を含む場合
msgList.add(ALLocalizationUtils.getl10nFormat(
"COMMONS_FIELD_INPUT_CHAR_TYPE_BY_NAME_SPAN",
fieldName,
getCharTypeByName()));
return false;
} else {
if (isLimitLength()) {
// 文字列長制限がある場合
int len = value.length();
if (len < getMinLength()) {
// 文字列長が最小値を下回る場合
msgList.add(ALLocalizationUtils.getl10nFormat(
"COMMONS_FIELD_INPUT_LENGTH_CAUTION_LESS_SPAN",
fieldName,
getMinLength()));
return false;
}
if (len > getMaxLength()) {
// 文字列長が最大値を上回る場合
msgList.add(ALLocalizationUtils.getl10nFormat(
"COMMONS_FIELD_INPUT_LENGTH_CAUTION_OVER_SPAN",
fieldName,
getMaxLength()));
return false;
}
}
if (!isUTF8()) {
// utf-8を超える範囲の文字が含まれている場合
msgList.add(ALLocalizationUtils.getl10nFormat(
"COMMONS_FIELD_INPUT_NOT_UTF_EIGHT",
fieldName));
return false;
}
}
}
return true;
}
/**
* 文字の種類が正しいかを判定します。
*
* @return
*/
protected boolean isValidCharacterType() {
if (getCharacterType() == TYPE_ALL) {
return true;
}
if (!isNotNullValue()) {
return true;
}
int length = value.length();
for (int i1 = 0; i1 < length; i1++) {
if ((getType(value.charAt(i1)) & getCharacterType()) == 0) {
// 指定されたタイプ以外の文字を含んでいる
return false;
}
}
return true;
}
/**
* 指定したchar型文字の種類を取得します。
*
* @param ch
* @return
*/
protected int getType(char ch) {
byte[] chars;
try {
chars =
(Character.valueOf(ch).toString()).getBytes(ENCORDE_CONFIRM_CHARTYPE);
} catch (UnsupportedEncodingException ex) {
return TYPE_ALL;
}
if (chars.length == 2) {
// 全角文字
return TYPE_MULTIBYTE;
}
if (Character.isDigit(ch)) {
// 半角数字
return TYPE_NUMBER;
}
if (Character.isLetter(ch)) {
// 半角英字
return TYPE_ALPHABET;
}
// 半角記号
return TYPE_SYMBOL;
}
/**
* 入力フィールド値の文字列の長さを取得します。
*
* @return
*/
protected int valueByteLength() {
int len = 0;
if (value == null) {
return len;
}
try {
len = (value.getBytes(ENCORDE_CONFIRM_CHARTYPE)).length;
} catch (UnsupportedEncodingException ex) {
len = 0;
}
return len;
}
/**
* 入力フィールド値がNullではないかどうかを判定します。
*
* @return
*/
protected boolean isNotNullValue() {
if (value == null || value.length() <= 0) {
return false;
}
return true;
}
protected boolean isUTF8() {
Matcher m = PATTERN.matcher(value);
return m.matches();
}
/**
* 文字の種類の表示名を取得します。
*
* @return
*/
protected String getCharTypeByName() {
switch (characterType) {
case TYPE_ALPHABET:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_ALPHABET");
case TYPE_NUMBER:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_NUMBER");
case TYPE_HANKAKUKANA:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_HANKAKUKANA");
case TYPE_MULTIBYTE:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_MULTIBYTE");
case TYPE_ALPHABET_NUMBER:
return ALLocalizationUtils
.getl10n("COMMONS_FIELD_TYPE_ALPHABET_NUMBER");
case TYPE_ALPHABET_NUMBER_HANKAKUKANA:
return ALLocalizationUtils
.getl10n("COMMONS_FIELD_TYPE_ALPHABET_NUMBER_HANKAKUKANA");
case TYPE_SYMBOL:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_SYMBOL");
case TYPE_ASCII:
return ALLocalizationUtils.getl10n("COMMONS_FIELD_TYPE_ASCII");
}
// 文字種別無指定
return "";
}
/**
* 入力フィールド値の左右の全角スペースを削除します。
*
* @param str
* @return
*/
private static String removeSpace(String str) {
int len = str.length();
int st = 0;
char[] val = str.toCharArray();
while ((st < len) && (val[st] <= ' ' || val[st] == 0x3000)) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == 0x3000)) {
len--;
}
return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str;
}
/**
* 入力フィールド値の文字列表現を取得します。
*
*/
@Override
public String toString() {
return ALStringUtil.sanitizing(value);
}
}