package com.mossle.keyvalue.support;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import com.mossle.api.keyvalue.KeyValueConnector;
import com.mossle.api.keyvalue.Prop;
import com.mossle.api.keyvalue.Record;
import com.mossle.core.id.IdGenerator;
import com.mossle.core.page.Page;
import com.mossle.core.query.PropertyFilter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class DatabaseKeyValueConnector implements KeyValueConnector {
private static Logger logger = LoggerFactory
.getLogger(DatabaseKeyValueConnector.class);
public static final int STATUS_DRAFT_PROCESS = 0;
private JdbcTemplate jdbcTemplate;
private IdGenerator idGenerator;
/**
* 根据code获得记录.
*/
public Record findByCode(String code) {
if (StringUtils.isBlank(code)) {
return null;
}
Record record = null;
try {
Map<String, Object> map = jdbcTemplate.queryForMap(
"select * from KV_RECORD where id=?", code);
record = convertRecord(map);
} catch (EmptyResultDataAccessException ex) {
logger.info("cannot find record by code : {}", code);
return null;
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return record;
}
/**
* 根据ref获得记录.
*/
public Record findByRef(String ref) {
if (StringUtils.isBlank(ref)) {
return null;
}
Record record = null;
try {
Map<String, Object> map = jdbcTemplate.queryForMap(
"select * from KV_RECORD where ref=?", ref);
record = convertRecord(map);
} catch (EmptyResultDataAccessException ex) {
logger.info("cannot find record by ref : {}", ref);
return null;
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return record;
}
/**
* 根据businessKey获得记录.
*/
public Record findByBusinessKey(String businessKey) {
if (StringUtils.isBlank(businessKey)) {
return null;
}
Record record = null;
try {
Map<String, Object> map = jdbcTemplate
.queryForMap(
"select * from KV_RECORD where BUSINESS_KEY=?",
businessKey);
record = this.convertRecord(map);
} catch (EmptyResultDataAccessException ex) {
logger.info("cannot find record by businessKey : {}", businessKey);
return null;
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return record;
}
/**
* 如果code为null,就执行insert,否则执行update.
*/
public void save(Record record) {
if (record.getCode() == null) {
insert(record);
} else {
update(record);
}
}
/**
* 根据code删除记录.
*/
public void removeByCode(String code) {
jdbcTemplate.update("DELETE FROM KV_PROP WHERE RECORD_ID=?", code);
jdbcTemplate.update("DELETE FROM KV_RECORD WHERE ID=?", code);
}
/**
* 根据businessKey删除记录.
*/
public void removeByBusinessKey(String businessKey) {
Long id = jdbcTemplate.queryForObject(
"SELECT ID FROM KV_RECORD WHERE BUSINESS_KEY=?", Long.class,
businessKey);
jdbcTemplate.update("DELETE FROM KV_PROP WHERE RECORD_ID=?", id);
jdbcTemplate.update("DELETE FROM KV_RECORD WHERE ID=?", id);
}
/**
* 根据status查询记录.
*/
public List<Record> findByStatus(int status, String userId, String tenantId) {
List<Map<String, Object>> list = jdbcTemplate
.queryForList(
"SELECT * FROM KV_RECORD WHERE STATUS=? AND USER_ID=? AND TENANT_ID=?",
status, userId, tenantId);
List<Record> records = new ArrayList<Record>();
for (Map<String, Object> map : list) {
Record record = convertRecord(map);
records.add(record);
}
return records;
}
/**
* 分页.
*/
public Page pagedQuery(Page page, int status, String userId, String tenantId) {
long totalCount = jdbcTemplate
.queryForObject(
"select count(*) from KV_RECORD WHERE STATUS=? AND USER_ID=? AND TENANT_ID=?",
Long.class, status, userId, tenantId);
List<Map<String, Object>> list = jdbcTemplate
.queryForList(
"SELECT * FROM KV_RECORD WHERE STATUS=? AND USER_ID=? AND TENANT_ID=? limit ?,?",
status, userId, tenantId, page.getStart(),
page.getPageSize());
List<Record> records = new ArrayList<Record>();
for (Map<String, Object> map : list) {
Record record = convertRecord(map);
records.add(record);
}
page.setTotalCount(totalCount);
page.setResult(records);
return page;
}
// ~ ======================================================================
/**
* 把map转换成Record.
*/
public Record convertRecord(Map<String, Object> recordMap) {
Record record = new Record();
record.setCode(getStringValue(recordMap, "id"));
record.setBusinessKey(getStringValue(recordMap, "BUSINESS_KEY"));
record.setName(getStringValue(recordMap, "name"));
record.setFormTemplateCode(getStringValue(recordMap,
"form_template_code"));
record.setCategory(getStringValue(recordMap, "category"));
record.setStatus(getIntValue(recordMap, "status"));
record.setRef(getStringValue(recordMap, "ref"));
record.setCreateTime(getDateValue(recordMap, "create_time"));
record.setUserId(getStringValue(recordMap, "user_id"));
record.setTenantId(getStringValue(recordMap, "tenant_id"));
List<Map<String, Object>> list = jdbcTemplate.queryForList(
"select * from KV_PROP where record_id=?", record.getCode());
for (Map<String, Object> propMap : list) {
Prop prop = new Prop();
prop.setCode(getStringValue(propMap, "code"));
prop.setType(getIntValue(propMap, "type"));
prop.setValue(getStringValue(propMap, "value"));
record.getProps().put(prop.getCode(), prop);
}
return record;
}
/**
* 获得string值.
*/
public String getStringValue(Map<String, Object> map, String name) {
Object value = map.get(name);
if (value == null) {
return null;
}
if (value instanceof String) {
return (String) value;
}
return value.toString();
}
/**
* 获得int值.
*/
public Integer getIntValue(Map<String, Object> map, String name) {
Object value = map.get(name);
if (value == null) {
return null;
}
if (value instanceof Integer) {
return (Integer) value;
}
return Integer.parseInt(value.toString());
}
/**
* 获得date值.
*/
public Date getDateValue(Map<String, Object> map, String name) {
Object value = map.get(name);
if (value == null) {
return null;
}
if (value instanceof Date) {
return (Date) value;
}
return null;
}
/**
* 新建一条数据.
*/
public void insert(Record record) {
String sqlRecordInsert = "insert into KV_RECORD(id,business_key,name,form_template_code,category,status,ref,create_time,user_id,tenant_id)"
+ " values(?,?,?,?,?,?,?,?,?,?)";
Long id = idGenerator.generateId();
String businessKey = record.getBusinessKey();
String name = record.getName();
String formTemplateCode = record.getFormTemplateCode();
String originalRef = record.getRef();
String ref = originalRef;
Date createTime = record.getCreateTime();
String userId = record.getUserId();
String tenantId = record.getTenantId();
if (originalRef == null) {
ref = UUID.randomUUID().toString();
}
jdbcTemplate.update(sqlRecordInsert, id, businessKey, name,
formTemplateCode, record.getCategory(), record.getStatus(),
ref, createTime, userId, tenantId);
Record resultRecord = this.findByRef(ref);
String code = resultRecord.getCode();
if (originalRef == null) {
String sqlRecordUpdate = "update KV_RECORD set ref=null where id=?";
jdbcTemplate.update(sqlRecordUpdate, code);
}
record.setCode(resultRecord.getCode());
String sqlProp = "insert into KV_PROP(id,code,type,value,record_id) values(?,?,?,?,?)";
for (Prop prop : record.getProps().values()) {
jdbcTemplate.update(sqlProp, idGenerator.generateId(),
prop.getCode(), prop.getType(), prop.getValue(),
record.getCode());
}
}
/**
* 更新一条数据.
*/
public void update(Record record) {
String sqlRecord = "update KV_RECORD set business_key=?,name=?,form_template_code=?,category=?,status=?,ref=? where id=?";
jdbcTemplate.update(sqlRecord, record.getBusinessKey(),
record.getName(), record.getFormTemplateCode(),
record.getCategory(), record.getStatus(), record.getRef(),
record.getCode());
Record resultRecord = findByCode(record.getCode());
String sqlPropInsert = "insert into KV_PROP(id,code,type,value,record_id) values(?,?,?,?,?)";
String sqlPropUpdate = "update KV_PROP set type=?,value=? where code=? and record_id=?";
for (Prop prop : record.getProps().values()) {
// only append, won't delete
if (resultRecord.getProps().containsKey(prop.getCode())) {
jdbcTemplate.update(sqlPropUpdate, prop.getType(),
prop.getValue(), prop.getCode(), record.getCode());
} else {
jdbcTemplate.update(sqlPropInsert, idGenerator.generateId(),
prop.getCode(), prop.getType(), prop.getValue(),
record.getCode());
}
}
}
public long findTotalCount(String category, String tenantId, String q) {
List<PropertyFilter> propertyFilters = new ArrayList<PropertyFilter>();
if (StringUtils.isNotBlank(q)) {
for (String text : q.split("\\|")) {
String name = text.split("=")[0];
String value = text.split("=")[1];
propertyFilters.add(new PropertyFilter("LIKES_" + name, value));
}
}
return this.findTotalCount(category, tenantId, propertyFilters);
}
public List<Map<String, Object>> findResult(Page page, String category,
String tenantId, Map<String, String> headers, String q) {
List<PropertyFilter> propertyFilters = new ArrayList<PropertyFilter>();
if (StringUtils.isNotBlank(q)) {
for (String text : q.split("\\|")) {
String name = text.split("=")[0];
String value = text.split("=")[1];
propertyFilters.add(new PropertyFilter("LIKES_" + name, value));
}
}
return this.findResult(page, category, tenantId, headers,
propertyFilters);
}
public long findTotalCount(String category, String tenantId,
List<PropertyFilter> propertyFilters) {
String sqlPrefix = null;
List<Object> params = new ArrayList<Object>();
if (propertyFilters.isEmpty()) {
sqlPrefix = "select count(*) from KV_RECORD r where r.CATEGORY=? and r.TENANT_ID=?";
} else {
sqlPrefix = "select count(distinct r.ID) from KV_RECORD r";
int index = 0;
for (PropertyFilter propertyFilter : propertyFilters) {
String propName = "p" + (index++);
sqlPrefix += (" join KV_PROP " + propName + " on r.ID="
+ propName + ".RECORD_ID and " + propName
+ ".CODE=? and " + propName + ".VALUE like ?");
params.add(propertyFilter.getPropertyName());
params.add("%" + propertyFilter.getMatchValue() + "%");
}
sqlPrefix += " where r.CATEGORY=? and r.TENANT_ID=?";
}
params.add(category);
params.add(tenantId);
long totalCount = jdbcTemplate.queryForObject(sqlPrefix, Long.class,
params.toArray(new Object[0]));
return totalCount;
}
public List<Map<String, Object>> findResult(Page page, String category,
String tenantId, Map<String, String> headers,
List<PropertyFilter> propertyFilters) {
String sqlPrefix = null;
List<Object> params = new ArrayList<Object>();
Map<String, String> usedFieldMap = new HashMap<String, String>();
if (propertyFilters.isEmpty()) {
sqlPrefix = "select r.ID from KV_RECORD r";
} else {
sqlPrefix = "select r.ID from KV_RECORD r";
int index = 0;
for (PropertyFilter propertyFilter : propertyFilters) {
String propName = "p" + index;
sqlPrefix += (" join KV_PROP " + propName + " on r.ID="
+ propName + ".RECORD_ID and " + propName
+ ".CODE=? and " + propName + ".VALUE like ?");
params.add(propertyFilter.getPropertyName());
params.add("%" + propertyFilter.getMatchValue() + "%");
usedFieldMap.put(propertyFilter.getPropertyName(), propName);
index++;
}
}
String sqlOrder = null;
if (page.isOrderEnabled()) {
String orderBy = page.getOrderBy();
String order = page.getOrder();
if (usedFieldMap.containsKey(orderBy)) {
String propName = usedFieldMap.get(orderBy);
sqlOrder = " order by " + propName + ".VALUE " + order;
} else {
String propName = "p";
sqlPrefix += (" join KV_PROP " + propName + " on r.ID="
+ propName + ".RECORD_ID and " + propName + ".CODE='"
+ orderBy + "'");
sqlOrder = " order by " + propName + ".VALUE " + order;
}
}
sqlPrefix += " where r.CATEGORY=? and r.TENANT_ID=?";
params.add(category);
params.add(tenantId);
if (sqlOrder != null) {
sqlPrefix += sqlOrder;
}
String sql = sqlPrefix + " limit " + page.getStart() + ","
+ page.getPageSize();
logger.debug("sql : {}", sql);
List<Map<String, Object>> records = jdbcTemplate.queryForList(sql,
params.toArray(new Object[0]));
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for (Map<String, Object> record : records) {
Map<String, Object> map = new HashMap<String, Object>();
list.add(map);
Long recordId = (Long) record.get("id");
List<Map<String, Object>> props = jdbcTemplate.queryForList(
"select * from KV_PROP where RECORD_ID=?", recordId);
for (Map<String, Object> prop : props) {
if (headers.containsKey(prop.get("code"))) {
map.put((String) prop.get("code"), prop.get("value"));
}
}
}
return list;
}
/**
* 复制数据.
*/
public Record copyRecord(Record original, List<String> fields) {
Record record = new Record();
//
record.setBusinessKey(original.getBusinessKey());
record.setName(original.getName());
record.setFormTemplateCode(original.getFormTemplateCode());
// bpmProcessId
record.setCategory(original.getCategory());
record.setStatus(STATUS_DRAFT_PROCESS);
// processInstanceId
record.setRef(null);
record.setCreateTime(new Date());
record.setUserId(original.getUserId());
record.setTenantId(original.getTenantId());
List<Map<String, Object>> list = jdbcTemplate.queryForList(
"select * from KV_PROP where record_id=?", original.getCode());
for (Map<String, Object> propMap : list) {
logger.debug("prop map : {}", propMap);
String code = getStringValue(propMap, "code");
if (!fields.contains(code)) {
continue;
}
Prop prop = new Prop();
prop.setCode(code);
prop.setType(getIntValue(propMap, "type"));
prop.setValue(getStringValue(propMap, "value"));
record.getProps().put(prop.getCode(), prop);
}
this.insert(record);
return record;
}
@Resource
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Resource
public void setIdGenerator(IdGenerator idGenerator) {
this.idGenerator = idGenerator;
}
}