ConditionalTagHandler.java
/*
* Copyright 2004-2022 the original author or authors.
*
* 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
*
* https://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 com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements;
import com.ibatis.common.beans.Probe;
import com.ibatis.common.beans.ProbeFactory;
import com.ibatis.sqlmap.engine.type.SimpleDateFormatter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
/**
* The Class ConditionalTagHandler.
*/
public abstract class ConditionalTagHandler extends BaseTagHandler {
/** The Constant PROBE. */
private static final Probe PROBE = ProbeFactory.getProbe();
/** The Constant NOT_COMPARABLE. */
public static final long NOT_COMPARABLE = Long.MIN_VALUE;
/** The Constant DATE_MASK. */
private static final String DATE_MASK = "yyyy/MM/dd hh:mm:ss";
/** The Constant START_INDEX. */
private static final String START_INDEX = "[";
/**
* Checks if is condition.
*
* @param ctx
* the ctx
* @param tag
* the tag
* @param parameterObject
* the parameter object
*
* @return true, if is condition
*/
public abstract boolean isCondition(SqlTagContext ctx, SqlTag tag, Object parameterObject);
@Override
public int doStartFragment(SqlTagContext ctx, SqlTag tag, Object parameterObject) {
ctx.pushRemoveFirstPrependMarker(tag);
if (isCondition(ctx, tag, parameterObject)) {
return SqlTagHandler.INCLUDE_BODY;
} else {
return SqlTagHandler.SKIP_BODY;
}
}
@Override
public int doEndFragment(SqlTagContext ctx, SqlTag tag, Object parameterObject, StringBuilder bodyContent) {
IterateContext iterate = ctx.peekIterateContext();
if (null != iterate && iterate.isAllowNext()) {
iterate.next();
iterate.setAllowNext(false);
if (!iterate.hasNext()) {
iterate.setFinal(true);
}
}
// iteratePropertyReplace(bodyContent,ctx.peekIterateContext());
return super.doEndFragment(ctx, tag, parameterObject, bodyContent);
}
/**
* Compare.
*
* @param ctx
* the ctx
* @param tag
* the tag
* @param parameterObject
* the parameter object
*
* @return the long
*/
protected long compare(SqlTagContext ctx, SqlTag tag, Object parameterObject) {
String comparePropertyName = tag.getComparePropertyAttr();
String compareValue = tag.getCompareValueAttr();
String prop = getResolvedProperty(ctx, tag);
Object value1;
Class type;
if (prop != null) {
value1 = PROBE.getObject(parameterObject, prop);
type = PROBE.getPropertyTypeForGetter(parameterObject, prop);
} else {
value1 = parameterObject;
if (value1 != null) {
type = parameterObject.getClass();
} else {
type = Object.class;
}
}
if (comparePropertyName != null) {
Object value2 = PROBE.getObject(parameterObject, comparePropertyName);
return compareValues(type, value1, value2);
} else if (compareValue != null) {
return compareValues(type, value1, compareValue);
} else {
throw new RuntimeException("Error comparing in conditional fragment. Uknown 'compare to' values.");
}
}
/**
* Compare values.
*
* @param type
* the type
* @param value1
* the value 1
* @param value2
* the value 2
*
* @return the long
*/
protected long compareValues(Class type, Object value1, Object value2) {
long result = NOT_COMPARABLE;
if (value1 == null || value2 == null) {
result = value1 == value2 ? 0 : NOT_COMPARABLE;
} else {
if (value2.getClass() != type) {
value2 = convertValue(type, value2.toString());
}
if (value2 instanceof String && type != String.class) {
value1 = value1.toString();
}
if (!(value1 instanceof Comparable && value2 instanceof Comparable)) {
value1 = value1.toString();
value2 = value2.toString();
}
result = ((Comparable) value1).compareTo(value2);
}
return result;
}
/**
* Convert value.
*
* @param type
* the type
* @param value
* the value
*
* @return the object
*/
protected Object convertValue(Class type, String value) {
if (type == String.class) {
return value;
} else if (type == Byte.class || type == byte.class) {
return Byte.valueOf(value);
} else if (type == Short.class || type == short.class) {
return Short.valueOf(value);
} else if (type == Character.class || type == char.class) {
return Character.valueOf(value.charAt(0));
} else if (type == Integer.class || type == int.class) {
return Integer.valueOf(value);
} else if (type == Long.class || type == long.class) {
return Long.valueOf(value);
} else if (type == Float.class || type == float.class) {
return Float.valueOf(value);
} else if (type == Double.class || type == double.class) {
return Double.valueOf(value);
} else if (type == Boolean.class || type == boolean.class) {
return Boolean.valueOf(value);
} else if (type == Date.class) {
return SimpleDateFormatter.format(DATE_MASK, value);
} else if (type == BigInteger.class) {
return new BigInteger(value);
} else if (type == BigDecimal.class) {
return new BigDecimal(value);
} else {
return value;
}
}
/**
* This method will add the proper index values to an indexed property string if we are inside an iterate tag.
*
* @param ctx
* the ctx
* @param tag
* the tag
*
* @return the resolved property
*/
protected String getResolvedProperty(SqlTagContext ctx, SqlTag tag) {
String prop = tag.getPropertyAttr();
IterateContext itCtx = ctx.peekIterateContext();
if (prop != null) {
if (null != itCtx && itCtx.isAllowNext()) {
itCtx.next();
itCtx.setAllowNext(false);
if (!itCtx.hasNext()) {
itCtx.setFinal(true);
}
}
if (prop.indexOf(START_INDEX) > -1) {
if (itCtx != null) {
prop = itCtx.addIndexToTagProperty(prop);
}
}
}
return prop;
}
}