package com.dounine.corgi.mongo.dao;
import com.dounine.corgi.mongo.dto.BaseDto;
import com.dounine.corgi.mongo.dto.Condition;
import com.dounine.corgi.mongo.entity.BaseEntity;
import com.dounine.corgi.mongo.enums.DataType;
import com.dounine.corgi.mongo.enums.RestrictionType;
import com.dounine.corgi.utils.GenericsUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
/**
* Created by lgq on 16/9/3.
*/
public class RepImpl<Entity extends BaseEntity, Dto extends BaseDto> implements IRep<Entity, Dto> {
@Autowired
protected MongoTemplate mongoTemplate;
protected Class<Entity> clazz;
private static final Logger CONSOLE = LoggerFactory.getLogger(RepImpl.class);
public RepImpl() {
clazz = GenericsUtils.getSuperClassGenricType(this.getClass());
}
@Override
public List<Entity> findAll() {
return mongoTemplate.findAll(clazz);
}
@Override
public List<Entity> findByPage(Dto dto) {
Query query = new Query();
query = init_sort(query, dto);
query = init_search(query, dto);
query.skip(dto.getSkip());
query.limit(dto.getLimit());
return mongoTemplate.find(query, clazz);
}
@Override
public Long count(Dto dto) {
Query query = new Query();
query = init_search(query, dto);
return mongoTemplate.count(query, clazz);
}
@Override
public Entity findOne(Dto dto) {
Query query = new Query();
query = init_search(query, dto);
return mongoTemplate.findOne(query, clazz);
}
@Override
public List<Entity> findByCriteria(Criteria criteria) {
Query query = new Query();
query.addCriteria(criteria);
return mongoTemplate.find(query, clazz);
}
@Override
public List<Entity> findByCis(Dto dto, boolean pageAndSort) {
Query query = new Query();
query = init_search(query, dto);
if (pageAndSort) {
query = init_sort(query, dto);
query.skip(dto.getSkip());
query.limit(dto.getLimit());
}
return mongoTemplate.find(query, clazz);
}
@Override
public Entity findById(String id) {
Entity entity = mongoTemplate.findById(id, clazz);
return mongoTemplate.findById(id, clazz);
}
@Override
public void save(Entity entity) {
mongoTemplate.insert(entity);
}
@Override
public void save(List<Entity> entities) {
mongoTemplate.insert(entities, clazz);
}
@Override
public void remove(String id) {
mongoTemplate.remove(new Query(Criteria.where("id").is(id)), clazz);
}
@Override
public void remove(Entity entity) {
mongoTemplate.remove(entity);
}
@Override
public void remove(List<Entity> entities) {
Stream<Entity> stream = entities.stream();
stream.forEach(entity -> {
mongoTemplate.remove(entity);
});
}
@Override
public void update(Entity entity) {
mongoTemplate.save(entity);
}
@Override
public void update(List<Entity> entities) {
Stream<Entity> stream = entities.stream();
stream.forEach(entity -> {
mongoTemplate.save(entity);
});
}
@Override
public List<Entity> findByCis(Map<String, Object> conditions) {
Query query = new Query();
if (null != conditions && conditions.size() > 0) {
for (Map.Entry<String, Object> entry : conditions.entrySet()) {
query.addCriteria(Criteria.where(entry.getKey()).is(entry.getValue()));
}
}
return mongoTemplate.find(query, clazz);
}
private Query init_search(Query query, Dto dto) {
List<Condition> conditions = dto.getConditions();
Stream<Condition> stream = conditions.stream();
stream.forEach(model -> {
String[] values = model.getValues();
RestrictionType restrict = model.getRestrict();
DataType dataType = model.getFieldType();
String field = model.getField();
switch (restrict) {
case EQ:
query.addCriteria(Criteria.where(field).is(switchSearchType(dataType, values[0])));
break;
case LIKE:
if (dataType.equals(DataType.STRING)) {
query.addCriteria(Criteria.where(field).regex(switchSearchType(dataType, values[0]).toString()));
}
break;
case BETWEEN:
if (null != values && values.length == 2) {
query.addCriteria(Criteria.where(field).gt(switchSearchType(dataType, values[0])).lt(switchSearchType(dataType, values[1])));
}
break;
case GT:
query.addCriteria(Criteria.where(field).gt(switchSearchType(dataType, values[0])));
break;
case GTEQ:
query.addCriteria(Criteria.where(field).gte(switchSearchType(dataType, values[0])));
break;
case LTEQ:
query.addCriteria(Criteria.where(field).lte(switchSearchType(dataType, values[0])));
break;
case LT:
query.addCriteria(Criteria.where(field).lt(switchSearchType(dataType, values[0])));
break;
case IN:
Object[] objects = values;
query.addCriteria(Criteria.where(field).in(objects));
break;
default:
break;
}
});
return query;
}
private Query init_sort(Query query, Dto dto) {
if (null != dto.getSort() && dto.getSort().size() > 0) {
Sort.Direction direction = Sort.Direction.DESC;
if (dto.getOrder().equals("asc")) {
direction = Sort.Direction.ASC;
}
query.with(new Sort(direction, dto.getSort()));
}
return query;
}
public Object switchSearchType(DataType type, Object value) {
Object field_value = null;
if (StringUtils.isNotBlank(String.valueOf(value))) {
switch (type) {
case STRING:
field_value = String.valueOf(value);
break;
case LOCALDATE:
field_value = LocalDate.parse(String.valueOf(value), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
break;
case LOCALTIME:
field_value = LocalTime.parse(String.valueOf(value), DateTimeFormatter.ofPattern("HH:mm:ss"));
break;
case LOCALDATETIME:
field_value = LocalDateTime.parse(String.valueOf(value), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
break;
case INT:
field_value = NumberUtils.createInteger(value.toString());
break;
case LONG:
field_value = NumberUtils.createLong(value.toString());
break;
case FLOAT:
field_value = NumberUtils.createFloat(value.toString());
break;
case DOUBLE:
field_value = NumberUtils.createDouble(value.toString());
break;
case BOOLEAN:
field_value = Boolean.parseBoolean(value.toString());
break;
default:
field_value = value;
CONSOLE.info("value type not defined:" + value);
break;
}
}
return field_value;
}
}