package org.infinispan.objectfilter.impl.syntax;
import java.text.ParseException;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import org.infinispan.objectfilter.impl.util.DateHelper;
/**
* A constant comparable value, to be used as right or left side in a comparison expression.
*
* @author anistor@redhat.com
* @since 7.0
*/
public final class ConstantValueExpr implements ValueExpr {
public static final class ParamPlaceholder implements Comparable {
private final String name;
public ParamPlaceholder(String name) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
}
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return ":" + getName();
}
@Override
public int compareTo(Object o) {
return name.compareTo(((ParamPlaceholder) o).getName());
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj == this || obj != null && obj.getClass() == ParamPlaceholder.class && name.equals(((ParamPlaceholder) obj).getName());
}
}
private final Comparable constantValue;
public ConstantValueExpr(Comparable constantValue) {
if (constantValue == null) {
throw new IllegalArgumentException("constantValue cannot be null");
}
this.constantValue = constantValue;
}
public Comparable getConstantValue() {
if (isParameter()) {
throw new IllegalStateException("The value is a parameter " + constantValue);
}
return constantValue;
}
public boolean isParameter() {
return constantValue instanceof ParamPlaceholder;
}
public Comparable getConstantValueAs(Class<?> targetType, Map<String, Object> namedParameters) {
Comparable value;
if (constantValue instanceof ParamPlaceholder) {
String paramName = ((ParamPlaceholder) constantValue).getName();
if (namedParameters == null) {
throw new IllegalStateException("Missing value for parameter " + paramName);
}
value = (Comparable) namedParameters.get(paramName);
if (value == null) {
throw new IllegalStateException("Missing value for parameter " + paramName);
}
} else {
value = constantValue;
}
Class<?> type = value.getClass();
if (type != targetType) {
if (targetType == String.class) {
return value.toString();
} else if (targetType == Boolean.class) {
if (type == String.class) {
return Boolean.valueOf((String) value);
}
} else if (targetType == Double.class) {
if (type == String.class) {
return Double.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).doubleValue();
}
} else if (targetType == Float.class) {
if (type == String.class) {
return Float.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).floatValue();
}
} else if (targetType == Long.class) {
if (type == String.class) {
return Long.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).longValue();
}
} else if (targetType == Integer.class) {
if (type == String.class) {
return Integer.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).intValue();
}
} else if (targetType == Short.class) {
if (type == String.class) {
return Short.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).shortValue();
}
} else if (targetType == Byte.class) {
if (type == String.class) {
return Byte.valueOf((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return ((Number) value).byteValue();
}
} else if (targetType == Date.class) {
if (type == String.class) {
try {
return DateHelper.getJpaDateFormat().parse((String) value);
} catch (ParseException e) {
throw new RuntimeException(e);
}
} else if (Number.class.isAssignableFrom(type)) {
return new Date(((Number) value).longValue());
}
} else if (targetType == Instant.class) {
if (type == String.class) {
return Instant.parse((String) value);
} else if (Number.class.isAssignableFrom(type)) {
return Instant.ofEpochMilli(((Number) value).longValue());
}
}
//todo [anistor] continue with other commonsense conversions
//todo [anistor] report illegal conversion
}
return value;
}
@Override
public <T> T acceptVisitor(Visitor<?, ?> visitor) {
return (T) visitor.visit(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConstantValueExpr other = (ConstantValueExpr) o;
return constantValue.equals(other.constantValue);
}
@Override
public int hashCode() {
return constantValue.hashCode();
}
@Override
public String toString() {
String strVal;
if (constantValue instanceof ParamPlaceholder) {
strVal = constantValue.toString();
} else if (constantValue instanceof String) {
strVal = "\"" + constantValue + "\"";
} else if (constantValue instanceof Character) {
strVal = "'" + constantValue + "'";
} else if (constantValue instanceof Date) {
strVal = DateHelper.getJpaDateFormat().format((Date) constantValue);
} else if (constantValue instanceof Instant) {
strVal = constantValue.toString();
} else {
strVal = String.valueOf(constantValue);
}
return "CONST(" + strVal + ')';
}
@Override
public String toQueryString() {
if (constantValue instanceof ParamPlaceholder) {
return constantValue.toString();
}
if (constantValue instanceof String) {
return "\"" + constantValue + "\"";
}
if (constantValue instanceof Character) {
return "'" + constantValue + "'";
}
if (constantValue instanceof Date) {
return "'" + DateHelper.getJpaDateFormat().format((Date) constantValue) + "'";
}
if (constantValue instanceof Instant) {
return "'" + constantValue.toString() + "'";
}
return "" + constantValue;
}
}