/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.extension.jdbc;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.seasar.extension.jdbc.exception.NonArrayInConditionRuntimeException;
import org.seasar.extension.jdbc.exception.NonBooleanIsNullConditionRuntimeException;
import org.seasar.framework.util.StringUtil;
/**
* where句の条件タイプです。
*
* @author higa
*
*/
public enum ConditionType {
/**
* =です。
*/
EQ {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, "=");
}
},
/**
* <>です。
*/
NE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, "<>");
}
},
/**
* <です。
*/
LT {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, "<");
}
},
/**
* <=です。
*/
LE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, "<=");
}
},
/**
* >です。
*/
GT {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, ">");
}
},
/**
* >=です。
*/
GE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeCondition(tableAlias, columnName, ">=");
}
},
/**
* inです。
*/
IN {
@Override
public boolean isTarget(Object value) {
return isTargetForIn("in", value);
}
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForIn(tableAlias, columnName, "in", value);
}
@Override
public int addValue(List<Object> paramList, Object value) {
return addValueForIn(paramList, value);
}
},
/**
* not inです。
*/
NOT_IN {
@Override
public boolean isTarget(Object value) {
return isTargetForIn("not in", value);
}
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForIn(tableAlias, columnName, "not in", value);
}
@Override
public int addValue(List<Object> paramList, Object value) {
return addValueForIn(paramList, value);
}
},
/**
* like ?です。
*/
LIKE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", null);
}
},
/**
* like ? escape ?です。
*/
LIKE_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", "?");
}
@Override
public int addValue(List<Object> valueList, Object value) {
final Object[] values = Object[].class.cast(value);
super.addValue(valueList, values[0]);
super.addValue(valueList, values[1]);
return 2;
}
},
/**
* not like ?です。
*/
NOT_LIKE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
null);
}
},
/**
* not like ? escape ?です。
*/
NOT_LIKE_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like", "?");
}
@Override
public int addValue(List<Object> valueList, Object value) {
final Object[] values = Object[].class.cast(value);
super.addValue(valueList, values[0]);
super.addValue(valueList, values[1]);
return 2;
}
},
/**
* like '?%'です。
*/
STARTS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, value + "%");
}
},
/**
* like '?%' escape '$'です。
*/
STARTS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", "'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, value + "%");
}
},
/**
* not like '?%'です。
*/
NOT_STARTS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, value + "%");
}
},
/**
* not like '?%' escape '$'です。
*/
NOT_STARTS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
"'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, value + "%");
}
},
/**
* like '%?'です。
*/
ENDS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value);
}
},
/**
* like '%?' escape '$'です。
*/
ENDS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", "'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value);
}
},
/**
* not like '%?'です。
*/
NOT_ENDS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value);
}
},
/**
* not like '%?' escape '$'です。
*/
NOT_ENDS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
"'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value);
}
},
/**
* like '%?%'です。
*/
CONTAINS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value + "%");
}
},
/**
* like '%?%' escape '$'です。
*/
CONTAINS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "like", "'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value + "%");
}
},
/**
* not like '%?%'です。
*/
NOT_CONTAINS {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
null);
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value + "%");
}
},
/**
* not like '%?%' escape '$'です。
*/
NOT_CONTAINS_ESCAPE {
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForLike(tableAlias, columnName, "not like",
"'$'");
}
@Override
public int addValue(List<Object> valueList, Object value) {
return super.addValue(valueList, "%" + value + "%");
}
},
/**
* is nullです。
*/
IS_NULL {
@Override
public boolean isTarget(Object value) {
return isTargetForIsNull("is null", value);
}
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForIsNull(tableAlias, columnName, "is null");
}
@Override
public int addValue(List<Object> paramList, Object value) {
return 0;
}
},
/**
* is not nullです。
*/
IS_NOT_NULL {
@Override
public boolean isTarget(Object value) {
return isTargetForIsNull("is not null", value);
}
@Override
public String getCondition(String tableAlias, String columnName,
Object value) {
return makeConditionForIsNull(tableAlias, columnName, "is not null");
}
@Override
public int addValue(List<Object> paramList, Object value) {
return 0;
}
};
/**
* 名前に応じた条件タイプを返します。
*
* @param name
* 名前
* @return 条件タイプ
*/
public static ConditionType getConditionType(String name) {
if (NE.hasSuffix(name)) {
return NE;
} else if (LT.hasSuffix(name)) {
return LT;
} else if (LE.hasSuffix(name)) {
return LE;
} else if (GT.hasSuffix(name)) {
return GT;
} else if (GE.hasSuffix(name)) {
return GE;
} else if (NOT_IN.hasSuffix(name)) {
return NOT_IN;
} else if (IN.hasSuffix(name)) {
return IN;
} else if (LIKE.hasSuffix(name)) {
return LIKE;
} else if (STARTS.hasSuffix(name)) {
return STARTS;
} else if (ENDS.hasSuffix(name)) {
return ENDS;
} else if (CONTAINS.hasSuffix(name)) {
return CONTAINS;
} else if (IS_NULL.hasSuffix(name)) {
return IS_NULL;
} else if (IS_NOT_NULL.hasSuffix(name)) {
return IS_NOT_NULL;
}
return EQ;
}
/**
* サフィックスを返します。
*
* @return サフィックス
*/
public String getSuffix() {
return "_" + name();
}
/**
* サフィックスを持っているかどうかを返します。
*
* @param name
* 名前
* @return サフィックスを持っているかどうか
*/
public boolean hasSuffix(String name) {
return name.endsWith(getSuffix());
}
/**
* サフィックスを削除します。
*
* @param s
* 文字列
* @return サフィックスが削除された文字列
*/
public String removeSuffix(String s) {
String suffix = getSuffix();
if (s.endsWith(suffix)) {
return s.substring(0, s.length() - getSuffix().length());
}
return s;
}
/**
* 条件を追加します。
*
* @param name
* 名前
* @param value
* 値
* @param whereClause
* where句
* @param valueList
* 値のリスト
* @return 追加した値の数
*/
public int addCondition(String name, Object value, WhereClause whereClause,
List<Object> valueList) {
return addCondition(null, name, value, whereClause, valueList);
}
/**
* 条件を追加します。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param value
* 値
* @param whereClause
* where句
* @param valueList
* 値のリスト
* @return 追加した値の数
*/
public int addCondition(String tableAlias, String columnName, Object value,
WhereClause whereClause, List<Object> valueList) {
if (isTarget(value)) {
whereClause.addAndSql(getCondition(tableAlias, columnName, value));
return addValue(valueList, value);
}
return 0;
}
/**
* 条件に追加する対象かどうかを返します。
*
* @param value
* 値
* @return 条件に追加する対象かどうか
*/
public boolean isTarget(Object value) {
return value != null;
}
/**
* 条件を返します。
*
* @param name
* 名前
* @param value
* 値
* @return 条件
*/
public String getCondition(String name, Object value) {
return getCondition(null, name, value);
}
/**
* 条件を返します。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param value
* 値
* @return 条件
*/
public abstract String getCondition(String tableAlias, String columnName,
Object value);
/**
* 値を追加します。
*
* @param valueList
* 値のリスト
* @param value
* 値
* @return 追加した値の数
*/
public int addValue(List<Object> valueList, Object value) {
valueList.add(value);
return 1;
}
/**
* 条件を組み立てます。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param operator
* 演算子
* @return 条件
*/
protected String makeCondition(String tableAlias, String columnName,
String operator) {
final StringBuilder buf = new StringBuilder(32);
if (!StringUtil.isEmpty(tableAlias)) {
buf.append(tableAlias).append('.');
}
buf.append(columnName).append(' ').append(operator).append(" ?");
return new String(buf);
}
/**
* <code>in, not in</code>の条件に追加する対象かどうかを返します。
*
* @param conditionName
* 条件名
* @param value
* 値
* @return 条件に追加する対象かどうか
*/
protected boolean isTargetForIn(String conditionName, Object value) {
Collection<?> values = null;
if (value == null) {
return false;
} else if (value.getClass().isArray()) {
values = Arrays.asList((Object[]) value);
} else if (value instanceof Collection) {
values = (Collection<?>) value;
} else {
throw new NonArrayInConditionRuntimeException(conditionName, value
.getClass());
}
if (values.isEmpty()) {
return false;
}
for (Object element : values) {
if (element != null) {
return true;
}
}
return false;
}
/**
* <code>in, not in</code>用の条件を組み立てます。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param conditionName
* 条件名
* @param value
* 値
* @return 条件
*/
protected String makeConditionForIn(String tableAlias, String columnName,
String conditionName, Object value) {
int size = value instanceof Collection ? ((Collection<?>) value).size()
: Array.getLength(value);
StringBuilder buf = new StringBuilder(30);
if (!StringUtil.isEmpty(tableAlias)) {
buf.append(tableAlias).append('.');
}
buf.append(columnName).append(' ').append(conditionName).append(" (");
for (int i = 0; i < size; i++) {
if (i != 0) {
buf.append(", ");
}
buf.append("?");
}
buf.append(")");
return buf.toString();
}
/**
* <code>in, not in</code>用に値を追加します。
*
* @param valueList
* 値のリスト
* @param value
* 値
* @return 追加した値の数
*/
protected int addValueForIn(List<Object> valueList, Object value) {
final Collection<?> list = value instanceof Collection ? (Collection<?>) value
: Arrays.asList((Object[]) value);
valueList.addAll(list);
return list.size();
}
/**
* <code>like</code>の条件を組み立てます。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param operator
* 演算子
* @param escape
* エスケープ
* @return 条件
*/
protected String makeConditionForLike(String tableAlias, String columnName,
String operator, String escape) {
final StringBuilder buf = new StringBuilder(32);
if (!StringUtil.isEmpty(tableAlias)) {
buf.append(tableAlias).append('.');
}
buf.append(columnName).append(' ').append(operator).append(" ?");
if (escape != null) {
buf.append(" escape ").append(escape);
}
return new String(buf);
}
/**
* <code>in, not in</code>の条件に追加する対象かどうかを返します。
*
* @param conditionName
* 条件名
* @param value
* 値
* @return 条件に追加する対象かどうか
*/
protected boolean isTargetForIsNull(String conditionName, Object value) {
if (value != null && value.getClass() != Boolean.class) {
throw new NonBooleanIsNullConditionRuntimeException(conditionName,
value.getClass());
}
return value != null && Boolean.TRUE.equals(value);
}
/**
* <code>is null, is not null</code>用の条件を組み立てます。
*
* @param tableAlias
* テーブルエイリアス
* @param columnName
* カラム名
* @param operator
* 演算子
* @param escape
* エスケープ
* @return 条件
*/
protected String makeConditionForIsNull(String tableAlias,
String columnName, String operator) {
final StringBuilder buf = new StringBuilder(32);
if (!StringUtil.isEmpty(tableAlias)) {
buf.append(tableAlias).append('.');
}
buf.append(columnName).append(' ').append(operator);
return new String(buf);
}
}