/**
* Copyright 2014 Duan Bingnan
*
* 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.pinus4j.api.query.impl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.management.Query;
import org.pinus4j.api.SQL;
import org.pinus4j.api.query.IQuery;
import org.pinus4j.cluster.beans.IShardingKey;
import org.pinus4j.cluster.enums.EnumDBMasterSlave;
import org.pinus4j.utils.BeansUtil;
import org.pinus4j.utils.StringUtil;
import com.google.common.collect.Lists;
/**
* 查询对象实现.
*
* @author duanbn
*/
public class DefaultQueryImpl<T> implements IQuery<T>, Cloneable {
protected Class<T> clazz;
/**
* 保存取值的字段.
*/
protected String[] fields;
/**
* 保存查询条件.
*/
protected List<Condition> condList = new ArrayList<Condition>();
/**
* 保存排序条件
*/
protected List<OrderBy> orderList = new ArrayList<OrderBy>();
/**
* 分页开始偏移量
*/
protected int start = -1;
/**
* 分页大小
*/
protected int limit = -1;
@Override
public T load() {
throw new UnsupportedOperationException("not support");
}
@Override
public List<T> list() {
throw new UnsupportedOperationException("not support");
}
@Override
public Number count() {
throw new UnsupportedOperationException("not support");
}
@Override
public IQuery<T> setShardingKey(IShardingKey<?> shardingKey) {
throw new UnsupportedOperationException("not support");
}
@Override
public IQuery<T> setMasterSlave(EnumDBMasterSlave masterSlave) {
throw new UnsupportedOperationException("not support");
}
@Override
public IQuery<T> setUseCache(boolean useCache) {
throw new UnsupportedOperationException("not support");
}
@Override
public IQuery<T> setFields(String... fields) {
if (fields != null && fields.length > 0) {
this.fields = fields;
}
return this;
}
@Override
public IQuery<T> setFields(Class<?> clazz, String... fields) {
if (fields != null && fields.length > 0) {
for (String field : fields) {
field = BeansUtil.getFieldName(BeansUtil.getField(clazz, field));
}
this.fields = fields;
}
return this;
}
@Deprecated
@Override
public IQuery<T> add(Condition cond) {
return and(cond);
}
@Override
public IQuery<T> and(Condition cond) {
if (cond == null) {
throw new IllegalArgumentException("param should not be null");
}
if (!condList.isEmpty())
cond.setConditionRelation(ConditionRelation.AND);
condList.add(cond);
return this;
}
@Override
public IQuery<T> or(Condition cond) {
if (cond == null) {
throw new IllegalArgumentException("param should not be null");
}
if (!condList.isEmpty())
cond.setConditionRelation(ConditionRelation.OR);
condList.add(cond);
return this;
}
@Override
public IQuery<T> orderBy(String field, Order order) {
return orderBy(field, order, clazz);
}
@Override
public IQuery<T> orderBy(String field, Order order, Class<?> clazz) {
if (StringUtil.isBlank(field)) {
throw new IllegalArgumentException("参数错误, field=" + field);
}
if (order == null) {
throw new IllegalArgumentException("参数错误, order=null");
}
orderList.add(new OrderBy(field, order, clazz));
return this;
}
@Override
public IQuery<T> limit(int start, int limit) {
if (start < 0 || limit <= 0) {
throw new IllegalArgumentException("分页参数错误, start" + start + ", limit=" + limit);
}
this.start = start;
this.limit = limit;
return this;
}
@Override
public IQuery<T> limit(int limit) {
if (limit <= 0) {
throw new IllegalArgumentException("设置limit参数错误, limit=" + limit);
}
this.limit = limit;
return this;
}
@Override
public void clean() {
this.fields = null;
this.condList.clear();
this.orderList.clear();
this.start = -1;
this.limit = -1;
}
public String[] getFields() {
return this.fields;
}
public List<Condition> getCondList() {
return this.condList;
}
public List<OrderBy> getOrderList() {
return this.orderList;
}
public int getStart() {
return this.start;
}
public int getLimit() {
return this.limit;
}
public boolean hasQueryFields() {
return this.fields != null && this.fields.length > 0;
}
public boolean isEffect() {
if (this.condList.isEmpty() && this.orderList.isEmpty() && start == -1 && limit == -1) {
return false;
}
return true;
}
public IQuery<T> clone() {
DefaultQueryImpl<T> clone = new DefaultQueryImpl<T>();
clone.fields = this.fields;
clone.condList.addAll(this.condList);
clone.orderList.addAll(this.orderList);
clone.start = this.start;
clone.limit = this.limit;
return clone;
}
public SQL getWhereSql() {
StringBuilder sqlText = new StringBuilder();
StringBuilder whereSql = new StringBuilder();
StringBuilder orderSql = new StringBuilder();
StringBuilder findInSet = new StringBuilder();
List<Object> paramList = Lists.newArrayList();
// 添加查询条件
// 当查询条件中只有一个in查询,则需要对此in查询进行排序
List<Condition> inConditionList = Lists.newArrayList();
if (!condList.isEmpty()) {
whereSql.append(" where ");
Condition cond = null;
for (int i = 0; i < condList.size(); i++) {
cond = condList.get(i);
if (i > 0) {
whereSql.append(" ").append(cond.getConditionRelation().getValue()).append(" ")
.append(cond.getSql().getSql());
} else {
whereSql.append(cond.getSql().getSql()); // first one
}
if (QueryOpt.IN == cond.getOpt()) {
inConditionList.add(cond);
}
paramList.addAll(cond.getSql().getParams());
}
// sort by find in set
if (!inConditionList.isEmpty() && inConditionList.size() == 1) {
Condition inCondition = inConditionList.get(0);
findInSet.append("find_in_set(").append(inCondition.getField()).append(",'");
for (Object param : inCondition.getSql().getParams()) {
findInSet.append(param).append(',');
}
findInSet.deleteCharAt(findInSet.length() - 1);
findInSet.append("')");
}
}
// 添加排序条件
if (orderList != null && !orderList.isEmpty()) {
orderSql.append(" order by ");
for (OrderBy orderBy : orderList) {
orderSql.append('`').append(orderBy.getField()).append('`');
orderSql.append(" ");
orderSql.append(orderBy.getOrder().getValue());
orderSql.append(",");
}
orderSql.deleteCharAt(orderSql.length() - 1);
} else if (StringUtil.isNotBlank(findInSet.toString())) {
orderSql.append(" order by ");
orderSql.append(findInSet);
}
sqlText.append(whereSql);
sqlText.append(orderSql);
// 添加分页
if (start > -1 && limit > -1) {
sqlText.append(" limit ?,?");
paramList.add(start);
paramList.add(limit);
} else if (limit != -1) {
sqlText.append(" limit ?");
paramList.add(limit);
}
return SQL.valueOf(sqlText.toString(), paramList);
}
@Override
public String toString() {
StringBuilder info = new StringBuilder();
if (fields != null && fields.length > 0) {
info.append("fields:");
for (String field : fields) {
info.append(field).append(",");
}
info.deleteCharAt(info.length() - 1);
}
if (StringUtil.isNotBlank(getWhereSql().getSql())) {
info.append(" wheresql:").append(getWhereSql());
}
return info.toString();
}
public void setCondList(List<Condition> condList) {
this.condList = condList;
}
public void setOrderList(List<OrderBy> orderList) {
this.orderList = orderList;
}
public void setStart(int start) {
this.start = start;
}
public void setLimit(int limit) {
this.limit = limit;
}
/**
* 排序条件.
*/
public static class OrderBy {
private String field;
private Class<?> fieldType;
private Order order;
public OrderBy(String field, Order order, Class<?> clazz) {
Field f = BeansUtil.getField(clazz, field);
if (clazz != null)
this.field = BeansUtil.getFieldName(f);
else
this.field = field;
this.fieldType = f.getType();
this.order = order;
}
public String getField() {
return field;
}
public Class<?> getFieldType() {
return this.fieldType;
}
public Order getOrder() {
return order;
}
@Override
public String toString() {
return "OrderBy [field=" + field + ", fieldType=" + fieldType + ", order=" + order + "]";
}
}
/**
* 只给Condition使用.
*
* @author shanwei Jul 29, 2015 7:06:33 PM
*/
enum ConditionRelation {
AND("and"),
OR("or");
private String value;
private ConditionRelation(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}