package ameba.db.dsl;
import ameba.core.ws.rs.ParamConverters;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.text.ParsePosition;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* <p>QueryExprMeta class.</p>
*
* @author icode
*
*/
public class QueryExprMeta {
private String field;
private String operator;
private List<Val<?>> arguments;
private QueryExprMeta parent;
private QueryExprMeta() {
}
/**
* <p>create.</p>
*
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
public static QueryExprMeta create() {
return new QueryExprMeta();
}
/**
* <p>operator.</p>
*
* @return a {@link java.lang.String} object.
*/
public String operator() {
return operator;
}
/**
* <p>field.</p>
*
* @return a {@link java.lang.String} object.
*/
public String field() {
return field;
}
/**
* <p>arguments.</p>
*
* @return a {@link java.util.List} object.
*/
public List<Val<?>> arguments() {
return arguments;
}
/**
* <p>parent.</p>
*
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
public QueryExprMeta parent() {
return parent;
}
/**
* <p>field.</p>
*
* @param field a {@link java.lang.String} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta field(String field) {
this.field = field;
return this;
}
/**
* <p>operator.</p>
*
* @param operator a {@link java.lang.String} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta operator(String operator) {
this.operator = operator;
return this;
}
/**
* <p>arguments.</p>
*
* @param arguments a {@link java.util.List} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta arguments(List<Val<?>> arguments) {
this.arguments = arguments;
return this;
}
/**
* <p>arguments.</p>
*
* @param arguments a {@link ameba.db.dsl.QueryExprMeta.Val} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta arguments(Val<?>... arguments) {
if (this.arguments == null) this.arguments = Lists.newArrayList();
Collections.addAll(this.arguments, arguments);
return this;
}
/**
* <p>arguments.</p>
*
* @param meta a {@link ameba.db.dsl.QueryExprMeta} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta arguments(QueryExprMeta meta) {
if (this.arguments == null) this.arguments = Lists.newArrayList();
this.arguments.add(Val.of(meta));
return this;
}
/**
* <p>parent.</p>
*
* @param parent a {@link ameba.db.dsl.QueryExprMeta} object.
* @return a {@link ameba.db.dsl.QueryExprMeta} object.
*/
protected QueryExprMeta parent(QueryExprMeta parent) {
this.parent = parent;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return (field == null ? "" : field + ".") +
operator + "(" +
(arguments == null ? "" :
StringUtils.join(
Collections2.transform(arguments,
input -> {
if (input.object() == null) {
return "nil";
} else if (input.object() instanceof String) {
return "'" + input.string() + "'";
}
return input.object().toString();
}), "!"
)
) +
")";
}
public static class Val<E> {
private static final ParsePosition POS = new ParsePosition(0);
private Object value;
Val(Object value) {
this.value = value;
}
public static <E> Val<E> of() {
return new Val<>(null);
}
public static <E> Val<E> of(String value) {
return new Val<>(value);
}
public static <E> Val<E> of(QueryExprMeta value) {
return new Val<>(value);
}
public static <E> Val<E> of(E value) {
return new Val<>(value);
}
public static <E> Val<E> ofObject(Object value) {
return new Val<>(value);
}
public static <E> Val<E> ofDate(String value) {
return new Val<>(ParamConverters.parseDate(value));
}
public static <E> Val<E> ofDecimal(String s) {
return new Val<>(new BigDecimal(s));
}
public static <E> Val<E> ofBool(String s) {
return new Val<>("true".equals(s));
}
public Double doubleV() {
return ((BigDecimal) value).doubleValue();
}
public Float floatV() {
return ((BigDecimal) value).floatValue();
}
public Long longV() {
return ((BigDecimal) value).longValue();
}
public Integer integer() {
return ((BigDecimal) value).intValue();
}
public Boolean bool() {
if (value instanceof Boolean) {
return ((Boolean) value);
} else if (value instanceof BigDecimal) {
return BooleanUtils.toBooleanObject(integer());
}
return null;
}
public String string() {
return (String) value;
}
public QueryExprMeta meta() {
return (QueryExprMeta) value;
}
public Date date() {
return (Date) value;
}
public <T extends Enum<T>> T enumV(Class<T> eClass) {
if (value instanceof BigDecimal) {
return eClass.getEnumConstants()[integer()];
} else if (value instanceof String) {
return Enum.valueOf(eClass, string());
}
throw new IllegalArgumentException(
"No enum constant " + eClass.getCanonicalName()
);
}
@SuppressWarnings("unchecked")
public E expr() {
return (E) value;
}
public Object object() {
return value;
}
}
}