|
|
@@ -1,414 +0,0 @@
|
|
|
-package com.uas.kanban.service.impl;
|
|
|
-
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
-import com.uas.kanban.annotation.NotEmpty;
|
|
|
-import com.uas.kanban.base.BaseService;
|
|
|
-import com.uas.kanban.dao.GlobalParameterDao;
|
|
|
-import com.uas.kanban.dao.KanbanDao;
|
|
|
-import com.uas.kanban.dao.KanbanInstanceDao;
|
|
|
-import com.uas.kanban.dao.TemplateDao;
|
|
|
-import com.uas.kanban.exception.OperationException;
|
|
|
-import com.uas.kanban.model.*;
|
|
|
-import com.uas.kanban.service.KanbanInstanceService;
|
|
|
-import com.uas.kanban.support.DataSourceManager;
|
|
|
-import com.uas.kanban.support.TemplateParser;
|
|
|
-import com.uas.kanban.util.CollectionUtils;
|
|
|
-import com.uas.kanban.util.ObjectUtils;
|
|
|
-import com.uas.kanban.util.StringUtils;
|
|
|
-import me.chyxion.jdbc.NewbieJdbcSupport;
|
|
|
-import org.dom4j.DocumentException;
|
|
|
-import org.mongodb.morphia.query.Query;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import javax.xml.transform.TransformerException;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.NotSerializableException;
|
|
|
-import java.sql.SQLException;
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-/**
|
|
|
- * 看板实例
|
|
|
- *
|
|
|
- * @author sunyj
|
|
|
- * @since 2017年9月3日 下午4:25:43
|
|
|
- */
|
|
|
-@Service
|
|
|
-public class KanbanInstanceServiceImpl extends BaseService<KanbanInstance> implements KanbanInstanceService {
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private KanbanInstanceDao kanbanInstanceDao;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private KanbanDao kanbanDao;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private TemplateDao templateDao;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private TemplateParser templateParser;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private DataSourceManager dataSourceManager;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private GlobalParameterDao globalParameterDao;
|
|
|
-
|
|
|
- @Override
|
|
|
- public KanbanInstance save(@NotEmpty("json") String json) {
|
|
|
- // TODO 一个资源点只能为某个看板维护一个看板实例
|
|
|
- KanbanInstance kanbanInstance = kanbanInstanceDao.parse(json);
|
|
|
- checkParameters(kanbanInstance);
|
|
|
- initSwitchFrequence(kanbanInstance);
|
|
|
- return kanbanInstanceDao.save(kanbanInstance);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public KanbanInstance savePart(@NotEmpty("json") String json) {
|
|
|
- return save(json);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int update(@NotEmpty("json") String json) throws IllegalArgumentException, OperationException {
|
|
|
- // TODO 一个资源点只能为某个看板维护一个看板实例
|
|
|
- KanbanInstance kanbanInstance = kanbanInstanceDao.parse(json);
|
|
|
- checkParameters(kanbanInstance);
|
|
|
- return kanbanInstanceDao.update(kanbanInstance);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int updatePart(@NotEmpty("json") String json) throws IllegalArgumentException, OperationException {
|
|
|
- return update(json);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查公共参数、模版参数等是否正确填写(没有遗漏参数、每个参数都有值并且类型匹配)
|
|
|
- *
|
|
|
- * @param kanbanInstance 看板实例
|
|
|
- */
|
|
|
- private void checkParameters(@NotEmpty("kanbanInstance") KanbanInstance kanbanInstance) {
|
|
|
- List<GlobalParameter> globalParameters = kanbanInstance.fromGlobalParameters();
|
|
|
- Map<String, List<TemplateParameter>> parameters = kanbanInstance.getParameters();
|
|
|
- if (!CollectionUtils.isEmpty(globalParameters) || !CollectionUtils.isEmpty(parameters)) {
|
|
|
- for (GlobalParameter globalParameter : globalParameters) {
|
|
|
- globalParameter.mayInitValue();
|
|
|
- }
|
|
|
- try {
|
|
|
- KanbanInstance kanbanInstanceClone = ObjectUtils.clone(kanbanInstance);
|
|
|
- generateParameters(kanbanInstanceClone);
|
|
|
- // 检查公共参数值
|
|
|
- if (!CollectionUtils.isEmpty(globalParameters)) {
|
|
|
- compare(globalParameters, kanbanInstanceClone.fromGlobalParameters());
|
|
|
- }
|
|
|
- // 检查模版参数值
|
|
|
- if (!CollectionUtils.isEmpty(parameters)) {
|
|
|
- compare(parameters, kanbanInstanceClone.getParameters());
|
|
|
- }
|
|
|
- } catch (ClassNotFoundException | IOException | InstantiationException | IllegalAccessException e) {
|
|
|
- throw new IllegalStateException("深克隆对象时失败", e);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 比较公共参数数量、名称等是否一致
|
|
|
- *
|
|
|
- * @param parameters 比较的对象
|
|
|
- * @param references 参考对象
|
|
|
- */
|
|
|
- private void compare(@NotEmpty("parameters") List<GlobalParameter> parameters, List<GlobalParameter> references)
|
|
|
- throws NotSerializableException, InstantiationException, IllegalAccessException, ClassNotFoundException,
|
|
|
- IOException {
|
|
|
- if (CollectionUtils.isEmpty(references)) {
|
|
|
- throw new IllegalArgumentException("不需要填写公共参数:" + parameters);
|
|
|
- }
|
|
|
- // 因为对象会被修改,所以先进行深克隆,参照对象不需要克隆
|
|
|
- List<GlobalParameter> parametersClone = (List<GlobalParameter>) ObjectUtils.clone(parameters);
|
|
|
- for (int i = parametersClone.size() - 1; i >= 0; i--) {
|
|
|
- GlobalParameter parameter = parametersClone.get(i);
|
|
|
- // 先检查值
|
|
|
- parameter.checkValue();
|
|
|
- // 再去除 code 相同的参数,以找出不一样的参数
|
|
|
- for (int j = references.size() - 1; j >= 0; j--) {
|
|
|
- GlobalParameter reference = references.get(j);
|
|
|
- if (Objects.equals(parameter.getCode(), reference.getCode())) {
|
|
|
- // 排除值的干扰
|
|
|
- reference.setValue(parameter.getValue());
|
|
|
- // 与参照对象不一致,说明填写的参数不规范
|
|
|
- if (!parameter.equals(reference)) {
|
|
|
- throw new IllegalArgumentException("公共参数属性不一致:" + parameter + ",应为:" + reference);
|
|
|
- }
|
|
|
- // 移除比较对象中通过检查的参数,最终剩下的全是不合法的参数
|
|
|
- parametersClone.remove(parameter);
|
|
|
- references.remove(reference);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(parametersClone)) {
|
|
|
- throw new IllegalArgumentException("不需要填写公共参数:" + parametersClone);
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(references)) {
|
|
|
- throw new IllegalArgumentException("未填写公共参数:" + references);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 比较模版参数数量、名称等是否一致
|
|
|
- *
|
|
|
- * @param parameters 比较的对象
|
|
|
- * @param references 参考对象
|
|
|
- */
|
|
|
- private void compare(@NotEmpty("parameters") Map<String, List<TemplateParameter>> parameters,
|
|
|
- Map<String, List<TemplateParameter>> references) throws NotSerializableException, InstantiationException,
|
|
|
- IllegalAccessException, ClassNotFoundException, IOException {
|
|
|
- if (CollectionUtils.isEmpty(references)) {
|
|
|
- throw new IllegalArgumentException("不需要填写参数:" + parameters);
|
|
|
- }
|
|
|
- // 因为对象会被修改,所以先进行深克隆,参照对象不需要克隆
|
|
|
- Map<String, List<TemplateParameter>> parametersClone = ObjectUtils.clone(parameters);
|
|
|
- // 先拷贝,否则之后修改 map 时,会报错 ConcurrentModificationException
|
|
|
- Set<String> keySetCopy = new HashSet<>(references.keySet());
|
|
|
- for (String templateCode : keySetCopy) {
|
|
|
- // 参照对象中的模版参数必须填写
|
|
|
- List<TemplateParameter> templateParameters = parametersClone.get(templateCode);
|
|
|
- if (CollectionUtils.isEmpty(templateParameters)) {
|
|
|
- throw new IllegalArgumentException("未填写模版 " + templateCode + " 的参数");
|
|
|
- }
|
|
|
- List<TemplateParameter> referenceTemplateParameters = references.get(templateCode);
|
|
|
- // 因为参考对象 references 必须是规范的,因此不必判断键值对中的值为空
|
|
|
- for (int i = referenceTemplateParameters.size() - 1; i >= 0; i--) {
|
|
|
- TemplateParameter referenceTemplateParameter = referenceTemplateParameters.get(i);
|
|
|
- for (int j = templateParameters.size() - 1; j >= 0; j--) {
|
|
|
- TemplateParameter templateParameter = templateParameters.get(j);
|
|
|
- if (Objects.equals(referenceTemplateParameter.getCode(), templateParameter.getCode())) {
|
|
|
- // 排除值的干扰
|
|
|
- referenceTemplateParameter.setValue(templateParameter.getValue());
|
|
|
- // 与参照对象不一致,说明填写的参数不规范
|
|
|
- if (!referenceTemplateParameter.equals(templateParameter)) {
|
|
|
- throw new IllegalArgumentException(
|
|
|
- "模版参数属性不一致:" + templateParameter + ",应为:" + referenceTemplateParameter);
|
|
|
- }
|
|
|
- // 移除比较对象中通过检查的参数,最终剩下的全是不合法的参数
|
|
|
- templateParameters.remove(templateParameter);
|
|
|
- referenceTemplateParameters.remove(referenceTemplateParameter);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 如果某个模版的参数全部通过检查,将其移除
|
|
|
- if (CollectionUtils.isEmpty(templateParameters)) {
|
|
|
- parametersClone.remove(templateCode);
|
|
|
- }
|
|
|
- if (CollectionUtils.isEmpty(referenceTemplateParameters)) {
|
|
|
- references.remove(templateCode);
|
|
|
- }
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(parametersClone)) {
|
|
|
- throw new IllegalArgumentException("不需要填写模版参数:" + parametersClone);
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(references)) {
|
|
|
- throw new IllegalArgumentException("未填写模版参数:" + references);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据看板绑定的模版,自动生成模版相应的看板实例参数和公共参数
|
|
|
- *
|
|
|
- * @param kanbanInstance 看板实例
|
|
|
- */
|
|
|
- private void generateParameters(@NotEmpty("kanbanInstance") KanbanInstance kanbanInstance) {
|
|
|
- Kanban kanban = checkKanban(kanbanInstance.getKanbanCode());
|
|
|
- List<String> templateCodes = kanban.getTemplateCodes();
|
|
|
- List<Template> templates = templateDao.findIn(templateCodes);
|
|
|
- Map<String, List<TemplateParameter>> parameters = new HashMap<>();
|
|
|
- List<GlobalParameter> globalParameters = new ArrayList<>();
|
|
|
- Set<String> globalParameterCodeSet = new HashSet<>();
|
|
|
- for (Template template : templates) {
|
|
|
- // 提取公共参数
|
|
|
- List<String> globalParameterCodes = template.getGlobalParameterCodes();
|
|
|
- if (!CollectionUtils.isEmpty(globalParameterCodes)) {
|
|
|
- for (String globalParameterCode : globalParameterCodes) {
|
|
|
- if (!globalParameterCodeSet.contains(globalParameterCode)) {
|
|
|
- globalParameterCodeSet.add(globalParameterCode);
|
|
|
- GlobalParameter globalParameter = checkGlobalParameter(globalParameterCode);
|
|
|
- globalParameter.mayInitValue();
|
|
|
- // 如果是 SQL 类型,需要解析公共参数
|
|
|
- if (globalParameter.getType() == Type.SQL) {
|
|
|
- try {
|
|
|
- NewbieJdbcSupport jdbc = dataSourceManager.getJdbc(template.getDataSourceCode());
|
|
|
- List<Map<String, Object>> listMap = jdbc.listMap(String.valueOf(globalParameter.getValue()));
|
|
|
- if (listMap == null) {
|
|
|
- listMap = new ArrayList<>();
|
|
|
- }
|
|
|
- globalParameter.setValue(JSONObject.toJSONString(listMap));
|
|
|
- } catch (SQLException e) {
|
|
|
- throw new IllegalStateException("公共参数解析错误", e);
|
|
|
- }
|
|
|
- }
|
|
|
- globalParameters.add(globalParameter);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- List<TemplateParameter> templateParameters = template.fromParameters();
|
|
|
- // 如果模版没有参数,则不为其生成看板实例参数
|
|
|
- if (!CollectionUtils.isEmpty(templateParameters)) {
|
|
|
- parameters.put(template.getCode(), templateParameters);
|
|
|
- }
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(globalParameters)) {
|
|
|
- kanbanInstance.toGlobalParameters(globalParameters);
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(parameters)) {
|
|
|
- kanbanInstance.setParameters(parameters);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查看板是否存在
|
|
|
- *
|
|
|
- * @param kanbanCode 看板的 code
|
|
|
- * @return 看板
|
|
|
- * @throws IllegalArgumentException 看板不存在时报错
|
|
|
- */
|
|
|
- private Kanban checkKanban(String kanbanCode) throws IllegalArgumentException {
|
|
|
- if (StringUtils.isEmpty(kanbanCode)) {
|
|
|
- throw new IllegalArgumentException("未指定看板 code");
|
|
|
- }
|
|
|
- Kanban kanban = kanbanDao.findOne(kanbanCode);
|
|
|
- if (kanban == null) {
|
|
|
- throw new IllegalArgumentException("看板不存在:" + kanbanCode);
|
|
|
- }
|
|
|
- return kanban;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化切换频率
|
|
|
- *
|
|
|
- * @param kanbanInstance 看板实例
|
|
|
- */
|
|
|
- private void initSwitchFrequence(@NotEmpty("kanbanInstance") KanbanInstance kanbanInstance)
|
|
|
- throws IllegalArgumentException {
|
|
|
- Kanban kanban = checkKanban(kanbanInstance.getKanbanCode());
|
|
|
- switch (kanban.getDisplay()) {
|
|
|
- case AutoSwitch:
|
|
|
- if (kanbanInstance.getSwitchFrequency() == null) {
|
|
|
- kanbanInstance.setSwitchFrequency(KanbanInstance.DEFAULT_SWITCH_FREQUENCY);
|
|
|
- }
|
|
|
- break;
|
|
|
- case SplitScreen:
|
|
|
- if (kanbanInstance.getSwitchFrequency() != null) {
|
|
|
- kanbanInstance.setSwitchFrequency(null);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查公共参数是否存在
|
|
|
- *
|
|
|
- * @param globalParameterCode 公共参数的 code
|
|
|
- * @return 公共参数
|
|
|
- * @throws IllegalArgumentException 公共参数不存在时报错
|
|
|
- */
|
|
|
- private GlobalParameter checkGlobalParameter(@NotEmpty("globalParameterCode") String globalParameterCode) {
|
|
|
- GlobalParameter globalParameter = globalParameterDao.findOne(globalParameterCode);
|
|
|
- if (globalParameter == null) {
|
|
|
- throw new IllegalArgumentException("公共参数不存在:" + globalParameterCode);
|
|
|
- }
|
|
|
- return globalParameter;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Map<String, Object> parseData(@NotEmpty("code") String code, String templateCode) {
|
|
|
- KanbanInstance kanbanInstance = kanbanInstanceDao.findOne(code);
|
|
|
- if (kanbanInstance == null) {
|
|
|
- throw new IllegalStateException("看板实例不存在");
|
|
|
- }
|
|
|
- Kanban kanban = checkKanban(kanbanInstance.getKanbanCode());
|
|
|
- List<String> templateCodes = kanban.getTemplateCodes();
|
|
|
- // 如果指定了模版,则解析该模版,否则解析该看板下的第一个模版
|
|
|
- if (!StringUtils.isEmpty(templateCode)) {
|
|
|
- if (!templateCodes.contains(templateCode)) {
|
|
|
- throw new IllegalArgumentException("看板下未绑定该模版:" + templateCode);
|
|
|
- }
|
|
|
- } else {
|
|
|
- templateCode = templateCodes.get(0);
|
|
|
- }
|
|
|
- Template template = templateDao.findOne(templateCode);
|
|
|
- if (template == null) {
|
|
|
- throw new IllegalStateException("模版不存在:" + templateCode);
|
|
|
- }
|
|
|
- Map<String, List<TemplateParameter>> parameters = kanbanInstance.getParameters();
|
|
|
- List<TemplateParameter> templateParameters = parameters == null ? null : parameters.get(templateCode);
|
|
|
- if (!CollectionUtils.isEmpty(templateParameters)) {
|
|
|
- // 检查模版参数是否正确填写(必填参数都填写了,并且参数值的类型都相符)
|
|
|
- for (TemplateParameter templateParameter : templateParameters) {
|
|
|
- templateParameter.checkValue();
|
|
|
- }
|
|
|
- }
|
|
|
- String content = template.getContent();
|
|
|
- String title = template.getTitle();
|
|
|
- if (StringUtils.isEmpty(content)) {
|
|
|
- throw new IllegalStateException("模版内容为空:" + templateCode);
|
|
|
- }
|
|
|
- List<GlobalParameter> globalParameters = kanbanInstance.fromGlobalParameters();
|
|
|
- // 解析模版
|
|
|
- String templateContent;
|
|
|
- try {
|
|
|
- NewbieJdbcSupport jdbc = dataSourceManager.getJdbc(template.getDataSourceCode());
|
|
|
- templateContent = templateParser.parseXml(content, title, globalParameters, jdbc);
|
|
|
- } catch (DocumentException e) {
|
|
|
- throw new IllegalStateException("xml 解析出错", e);
|
|
|
- } catch (TransformerException e) {
|
|
|
- throw new IllegalStateException("xml 映射出错", e);
|
|
|
- } catch (IOException e) {
|
|
|
- throw new IllegalStateException("xml 转换出错", e);
|
|
|
- } catch (SQLException e) {
|
|
|
- throw new IllegalStateException("数据库连接错误", e);
|
|
|
- }
|
|
|
- Map<String, Object> result = new HashMap<>();
|
|
|
- Map<String, Object> instance = new HashMap<>();
|
|
|
- instance.put("display", kanban.getDisplay());
|
|
|
- instance.put("globalParameters", globalParameters);
|
|
|
- instance.put("templateCodes", kanban.getTemplateCodes());
|
|
|
- instance.put("switchFrequency", kanbanInstance.getSwitchFrequency());
|
|
|
- instance.put("refreshFrequency", kanbanInstance.getRefreshFrequency());
|
|
|
- result.put("instance", instance);
|
|
|
- List<JSONObject> data = new ArrayList<>();
|
|
|
- data.add(JSONObject.parseObject(templateContent));
|
|
|
- result.put("data", data);
|
|
|
- // TODO 多个模版返回的json
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int deleteByKanbanCodes(@NotEmpty("kanbanCodes") List<String> kanbanCodes) {
|
|
|
- Query<KanbanInstance> query = kanbanInstanceDao.createQuery().field("kanbanCode").in(kanbanCodes);
|
|
|
- return kanbanInstanceDao.delete(query);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public KanbanInstance getByKanbanCode(@NotEmpty("kanbanCode") String kanbanCode) throws IllegalStateException {
|
|
|
- Query<KanbanInstance> query = kanbanInstanceDao.createQuery().field("kanbanCode").equal(kanbanCode);
|
|
|
- if (query.count() > 1) {
|
|
|
- throw new IllegalStateException("找到多个看板实例");
|
|
|
- }
|
|
|
- return query.get();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public KanbanInstance openKanbanInstance(@NotEmpty("kanbanCode") String kanbanCode) throws IllegalStateException {
|
|
|
- // TODO 检查模版、参数等是否有更改
|
|
|
- KanbanInstance kanbanInstance = getByKanbanCode(kanbanCode);
|
|
|
- // 如果有创建的实例,返回该实例,如果没有,提取参数等之后返回
|
|
|
- if (kanbanInstance == null) {
|
|
|
- kanbanInstance = new KanbanInstance();
|
|
|
- kanbanInstance.setKanbanCode(kanbanCode);
|
|
|
- initSwitchFrequence(kanbanInstance);
|
|
|
- kanbanInstance.setRefreshFrequency(KanbanInstance.DEFAULT_REFRESH_FREQUENCY);
|
|
|
- // 生成相应的看板实例参数
|
|
|
- generateParameters(kanbanInstance);
|
|
|
- }
|
|
|
- return kanbanInstance;
|
|
|
- }
|
|
|
-
|
|
|
-}
|