Commit 96d20b073b29e0d46733a2dde52cb24449a8e2fb

Authored by Andrew Shvayka
Committed by GitHub
2 parents c88a4426 2d4ac40e

Merge pull request #5351 from ViacheslavKlimov/fix/rule-chains-import

Rule chains import refactoring
... ... @@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired;
25 25 import org.springframework.beans.factory.annotation.Value;
26 26 import org.springframework.http.HttpStatus;
27 27 import org.springframework.security.access.prepost.PreAuthorize;
28   -import org.springframework.util.CollectionUtils;
29 28 import org.springframework.util.StringUtils;
30 29 import org.springframework.web.bind.annotation.PathVariable;
31 30 import org.springframework.web.bind.annotation.RequestBody;
... ... @@ -450,15 +449,17 @@ public class RuleChainController extends BaseController {
450 449 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
451 450 @RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST)
452 451 @ResponseBody
453   - public void importRuleChains(@RequestBody RuleChainData ruleChainData, @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException {
  452 + public List<RuleChainImportResult> importRuleChains(@RequestBody RuleChainData ruleChainData, @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException {
454 453 try {
455 454 TenantId tenantId = getCurrentUser().getTenantId();
456   - List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, RuleChainType.CORE, overwrite);
457   - if (!CollectionUtils.isEmpty(importResults)) {
458   - for (RuleChainImportResult importResult : importResults) {
459   - tbClusterService.broadcastEntityStateChangeEvent(importResult.getTenantId(), importResult.getRuleChainId(), importResult.getLifecycleEvent());
  455 + List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, overwrite);
  456 + for (RuleChainImportResult importResult : importResults) {
  457 + if (importResult.getError() == null) {
  458 + tbClusterService.broadcastEntityStateChangeEvent(importResult.getTenantId(), importResult.getRuleChainId(),
  459 + importResult.isUpdated() ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED);
460 460 }
461 461 }
  462 + return importResults;
462 463 } catch (Exception e) {
463 464 throw handleException(e);
464 465 }
... ...
... ... @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId;
23 23 import org.thingsboard.server.common.data.id.TenantId;
24 24 import org.thingsboard.server.common.data.page.PageData;
25 25 import org.thingsboard.server.common.data.page.PageLink;
26   -import org.thingsboard.server.common.data.page.TimePageLink;
27 26 import org.thingsboard.server.common.data.relation.EntityRelation;
28 27 import org.thingsboard.server.common.data.rule.RuleChain;
29 28 import org.thingsboard.server.common.data.rule.RuleChainData;
... ... @@ -71,7 +70,7 @@ public interface RuleChainService {
71 70
72 71 RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) throws ThingsboardException;
73 72
74   - List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, RuleChainType type, boolean overwrite);
  73 + List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, boolean overwrite);
75 74
76 75 RuleChain assignRuleChainToEdge(TenantId tenantId, RuleChainId ruleChainId, EdgeId edgeId);
77 76
... ...
... ... @@ -15,17 +15,22 @@
15 15 */
16 16 package org.thingsboard.server.common.data.rule;
17 17
18   -import lombok.AllArgsConstructor;
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.annotation.JsonInclude;
19 20 import lombok.Data;
20 21 import org.thingsboard.server.common.data.id.RuleChainId;
21 22 import org.thingsboard.server.common.data.id.TenantId;
22   -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
23 23
24 24 @Data
25   -@AllArgsConstructor
26 25 public class RuleChainImportResult {
27 26
  27 + @JsonIgnore
28 28 private TenantId tenantId;
29 29 private RuleChainId ruleChainId;
30   - private ComponentLifecycleEvent lifecycleEvent;
  30 + private String ruleChainName;
  31 + @JsonInclude(JsonInclude.Include.NON_DEFAULT)
  32 + private boolean updated;
  33 + @JsonInclude(JsonInclude.Include.NON_NULL)
  34 + private String error;
  35 +
31 36 }
... ...
... ... @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.apache.commons.collections.CollectionUtils;
24 24 import org.apache.commons.lang3.StringUtils;
  25 +import org.apache.commons.lang3.exception.ExceptionUtils;
25 26 import org.hibernate.exception.ConstraintViolationException;
26 27 import org.springframework.beans.factory.annotation.Autowired;
27 28 import org.springframework.context.annotation.Lazy;
... ... @@ -38,7 +39,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId;
38 39 import org.thingsboard.server.common.data.id.TenantId;
39 40 import org.thingsboard.server.common.data.page.PageData;
40 41 import org.thingsboard.server.common.data.page.PageLink;
41   -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
42 42 import org.thingsboard.server.common.data.relation.EntityRelation;
43 43 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
44 44 import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
... ... @@ -59,6 +59,7 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
59 59 import org.thingsboard.server.dao.tenant.TenantDao;
60 60
61 61 import java.util.ArrayList;
  62 +import java.util.Collection;
62 63 import java.util.HashMap;
63 64 import java.util.HashSet;
64 65 import java.util.Iterator;
... ... @@ -416,41 +417,46 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
416 417 }
417 418
418 419 @Override
419   - public List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, RuleChainType type, boolean overwrite) {
  420 + public List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, boolean overwrite) {
420 421 List<RuleChainImportResult> importResults = new ArrayList<>();
  422 +
421 423 setRandomRuleChainIds(ruleChainData);
422 424 resetRuleNodeIds(ruleChainData.getMetadata());
423 425 resetRuleChainMetadataTenantIds(tenantId, ruleChainData.getMetadata());
424   - if (overwrite) {
425   - List<RuleChain> persistentRuleChains = findAllTenantRuleChains(tenantId, type);
426   - for (RuleChain ruleChain : ruleChainData.getRuleChains()) {
427   - ComponentLifecycleEvent lifecycleEvent;
428   - Optional<RuleChain> persistentRuleChainOpt = persistentRuleChains.stream().filter(rc -> rc.getName().equals(ruleChain.getName())).findFirst();
429   - if (persistentRuleChainOpt.isPresent()) {
430   - setNewRuleChainId(ruleChain, ruleChainData.getMetadata(), ruleChain.getId(), persistentRuleChainOpt.get().getId());
431   - ruleChain.setRoot(persistentRuleChainOpt.get().isRoot());
432   - lifecycleEvent = ComponentLifecycleEvent.UPDATED;
433   - } else {
434   - ruleChain.setRoot(false);
435   - lifecycleEvent = ComponentLifecycleEvent.CREATED;
  426 +
  427 + for (RuleChain ruleChain : ruleChainData.getRuleChains()) {
  428 + RuleChainImportResult importResult = new RuleChainImportResult();
  429 +
  430 + ruleChain.setTenantId(tenantId);
  431 + ruleChain.setRoot(false);
  432 +
  433 + if (overwrite) {
  434 + Collection<RuleChain> existingRuleChains = ruleChainDao.findByTenantIdAndTypeAndName(tenantId,
  435 + Optional.ofNullable(ruleChain.getType()).orElse(RuleChainType.CORE), ruleChain.getName());
  436 + Optional<RuleChain> existingRuleChain = existingRuleChains.stream().findFirst();
  437 + if (existingRuleChain.isPresent()) {
  438 + setNewRuleChainId(ruleChain, ruleChainData.getMetadata(), ruleChain.getId(), existingRuleChain.get().getId());
  439 + ruleChain.setRoot(existingRuleChain.get().isRoot());
  440 + importResult.setUpdated(true);
436 441 }
437   - ruleChain.setTenantId(tenantId);
438   - ruleChainDao.save(tenantId, ruleChain);
439   - importResults.add(new RuleChainImportResult(tenantId, ruleChain.getId(), lifecycleEvent));
440 442 }
441   - } else {
442   - if (!CollectionUtils.isEmpty(ruleChainData.getRuleChains())) {
443   - ruleChainData.getRuleChains().forEach(rc -> {
444   - rc.setTenantId(tenantId);
445   - rc.setRoot(false);
446   - RuleChain savedRc = ruleChainDao.save(tenantId, rc);
447   - importResults.add(new RuleChainImportResult(tenantId, savedRc.getId(), ComponentLifecycleEvent.CREATED));
448   - });
  443 +
  444 + try {
  445 + ruleChain = saveRuleChain(ruleChain);
  446 + } catch (Exception e) {
  447 + importResult.setError(ExceptionUtils.getRootCauseMessage(e));
449 448 }
  449 +
  450 + importResult.setTenantId(tenantId);
  451 + importResult.setRuleChainId(ruleChain.getId());
  452 + importResult.setRuleChainName(ruleChain.getName());
  453 + importResults.add(importResult);
450 454 }
451   - if (!CollectionUtils.isEmpty(ruleChainData.getMetadata())) {
  455 +
  456 + if (CollectionUtils.isNotEmpty(ruleChainData.getMetadata())) {
452 457 ruleChainData.getMetadata().forEach(md -> saveRuleChainMetaData(tenantId, md));
453 458 }
  459 +
454 460 return importResults;
455 461 }
456 462
... ... @@ -475,7 +481,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
475 481 }
476 482 if (isTenantId) {
477 483 ObjectNode objNode = (ObjectNode) node;
478   - objNode.put("id", tenantId.getId().toString());
  484 + if (objNode.has("id")) {
  485 + objNode.put("id", tenantId.getId().toString());
  486 + }
479 487 } else {
480 488 for (JsonNode jsonNode : node) {
481 489 searchTenantIdRecursive(tenantId, jsonNode);
... ... @@ -723,4 +731,5 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
723 731 checkRuleNodesAndDelete(tenantId, entity.getId());
724 732 }
725 733 };
  734 +
726 735 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.dao.rule;
17 17
  18 +import org.thingsboard.server.common.data.id.TenantId;
18 19 import org.thingsboard.server.common.data.page.PageData;
19 20 import org.thingsboard.server.common.data.page.PageLink;
20 21 import org.thingsboard.server.common.data.rule.RuleChain;
... ... @@ -22,6 +23,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
22 23 import org.thingsboard.server.dao.Dao;
23 24 import org.thingsboard.server.dao.TenantEntityDao;
24 25
  26 +import java.util.Collection;
25 27 import java.util.UUID;
26 28
27 29 /**
... ... @@ -74,4 +76,7 @@ public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao {
74 76 * @return the list of rule chain objects
75 77 */
76 78 PageData<RuleChain> findAutoAssignToEdgeRuleChainsByTenantId(UUID tenantId, PageLink pageLink);
  79 +
  80 + Collection<RuleChain> findByTenantIdAndTypeAndName(TenantId tenantId, RuleChainType type, String name);
  81 +
77 82 }
... ...
... ... @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.RuleChainEntity;
29 29 import org.thingsboard.server.dao.rule.RuleChainDao;
30 30 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
31 31
  32 +import java.util.Collection;
32 33 import java.util.Objects;
33 34 import java.util.UUID;
34 35
... ... @@ -98,7 +99,13 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
98 99 }
99 100
100 101 @Override
  102 + public Collection<RuleChain> findByTenantIdAndTypeAndName(TenantId tenantId, RuleChainType type, String name) {
  103 + return DaoUtil.convertDataList(ruleChainRepository.findByTenantIdAndTypeAndName(tenantId.getId(), type, name));
  104 + }
  105 +
  106 + @Override
101 107 public Long countByTenantId(TenantId tenantId) {
102 108 return ruleChainRepository.countByTenantId(tenantId.getId());
103 109 }
  110 +
104 111 }
... ...
... ... @@ -23,6 +23,7 @@ import org.springframework.data.repository.query.Param;
23 23 import org.thingsboard.server.common.data.rule.RuleChainType;
24 24 import org.thingsboard.server.dao.model.sql.RuleChainEntity;
25 25
  26 +import java.util.List;
26 27 import java.util.UUID;
27 28
28 29 public interface RuleChainRepository extends PagingAndSortingRepository<RuleChainEntity, UUID> {
... ... @@ -55,10 +56,13 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai
55 56 "AND re.relationType = 'Contains' AND re.fromId = :tenantId AND re.fromType = 'TENANT' " +
56 57 "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
57 58 Page<RuleChainEntity> findAutoAssignByTenantId(@Param("tenantId") UUID tenantId,
58   - @Param("searchText") String searchText,
59   - Pageable pageable);
  59 + @Param("searchText") String searchText,
  60 + Pageable pageable);
60 61
61 62 RuleChainEntity findByTenantIdAndTypeAndRootIsTrue(UUID tenantId, RuleChainType ruleChainType);
62 63
63 64 Long countByTenantId(UUID tenantId);
  65 +
  66 + List<RuleChainEntity> findByTenantIdAndTypeAndName(UUID tenantId, RuleChainType type, String name);
  67 +
64 68 }
... ...