Commit 96d20b073b29e0d46733a2dde52cb24449a8e2fb
Committed by
GitHub
Merge pull request #5351 from ViacheslavKlimov/fix/rule-chains-import
Rule chains import refactoring
Showing
7 changed files
with
71 additions
and
41 deletions
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
25 | import org.springframework.beans.factory.annotation.Value; | 25 | import org.springframework.beans.factory.annotation.Value; |
26 | import org.springframework.http.HttpStatus; | 26 | import org.springframework.http.HttpStatus; |
27 | import org.springframework.security.access.prepost.PreAuthorize; | 27 | import org.springframework.security.access.prepost.PreAuthorize; |
28 | -import org.springframework.util.CollectionUtils; | ||
29 | import org.springframework.util.StringUtils; | 28 | import org.springframework.util.StringUtils; |
30 | import org.springframework.web.bind.annotation.PathVariable; | 29 | import org.springframework.web.bind.annotation.PathVariable; |
31 | import org.springframework.web.bind.annotation.RequestBody; | 30 | import org.springframework.web.bind.annotation.RequestBody; |
@@ -450,15 +449,17 @@ public class RuleChainController extends BaseController { | @@ -450,15 +449,17 @@ public class RuleChainController extends BaseController { | ||
450 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 449 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
451 | @RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST) | 450 | @RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST) |
452 | @ResponseBody | 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 | try { | 453 | try { |
455 | TenantId tenantId = getCurrentUser().getTenantId(); | 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 | } catch (Exception e) { | 463 | } catch (Exception e) { |
463 | throw handleException(e); | 464 | throw handleException(e); |
464 | } | 465 | } |
@@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId; | @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId; | ||
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | import org.thingsboard.server.common.data.page.PageData; | 24 | import org.thingsboard.server.common.data.page.PageData; |
25 | import org.thingsboard.server.common.data.page.PageLink; | 25 | import org.thingsboard.server.common.data.page.PageLink; |
26 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
27 | import org.thingsboard.server.common.data.relation.EntityRelation; | 26 | import org.thingsboard.server.common.data.relation.EntityRelation; |
28 | import org.thingsboard.server.common.data.rule.RuleChain; | 27 | import org.thingsboard.server.common.data.rule.RuleChain; |
29 | import org.thingsboard.server.common.data.rule.RuleChainData; | 28 | import org.thingsboard.server.common.data.rule.RuleChainData; |
@@ -71,7 +70,7 @@ public interface RuleChainService { | @@ -71,7 +70,7 @@ public interface RuleChainService { | ||
71 | 70 | ||
72 | RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) throws ThingsboardException; | 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 | RuleChain assignRuleChainToEdge(TenantId tenantId, RuleChainId ruleChainId, EdgeId edgeId); | 75 | RuleChain assignRuleChainToEdge(TenantId tenantId, RuleChainId ruleChainId, EdgeId edgeId); |
77 | 76 |
@@ -15,17 +15,22 @@ | @@ -15,17 +15,22 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.rule; | 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 | import lombok.Data; | 20 | import lombok.Data; |
20 | import org.thingsboard.server.common.data.id.RuleChainId; | 21 | import org.thingsboard.server.common.data.id.RuleChainId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 22 | import org.thingsboard.server.common.data.id.TenantId; |
22 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
23 | 23 | ||
24 | @Data | 24 | @Data |
25 | -@AllArgsConstructor | ||
26 | public class RuleChainImportResult { | 25 | public class RuleChainImportResult { |
27 | 26 | ||
27 | + @JsonIgnore | ||
28 | private TenantId tenantId; | 28 | private TenantId tenantId; |
29 | private RuleChainId ruleChainId; | 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,6 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
22 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
23 | import org.apache.commons.collections.CollectionUtils; | 23 | import org.apache.commons.collections.CollectionUtils; |
24 | import org.apache.commons.lang3.StringUtils; | 24 | import org.apache.commons.lang3.StringUtils; |
25 | +import org.apache.commons.lang3.exception.ExceptionUtils; | ||
25 | import org.hibernate.exception.ConstraintViolationException; | 26 | import org.hibernate.exception.ConstraintViolationException; |
26 | import org.springframework.beans.factory.annotation.Autowired; | 27 | import org.springframework.beans.factory.annotation.Autowired; |
27 | import org.springframework.context.annotation.Lazy; | 28 | import org.springframework.context.annotation.Lazy; |
@@ -38,7 +39,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId; | @@ -38,7 +39,6 @@ import org.thingsboard.server.common.data.id.RuleNodeId; | ||
38 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
39 | import org.thingsboard.server.common.data.page.PageData; | 40 | import org.thingsboard.server.common.data.page.PageData; |
40 | import org.thingsboard.server.common.data.page.PageLink; | 41 | import org.thingsboard.server.common.data.page.PageLink; |
41 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
42 | import org.thingsboard.server.common.data.relation.EntityRelation; | 42 | import org.thingsboard.server.common.data.relation.EntityRelation; |
43 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 43 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
44 | import org.thingsboard.server.common.data.rule.NodeConnectionInfo; | 44 | import org.thingsboard.server.common.data.rule.NodeConnectionInfo; |
@@ -59,6 +59,7 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | @@ -59,6 +59,7 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | ||
59 | import org.thingsboard.server.dao.tenant.TenantDao; | 59 | import org.thingsboard.server.dao.tenant.TenantDao; |
60 | 60 | ||
61 | import java.util.ArrayList; | 61 | import java.util.ArrayList; |
62 | +import java.util.Collection; | ||
62 | import java.util.HashMap; | 63 | import java.util.HashMap; |
63 | import java.util.HashSet; | 64 | import java.util.HashSet; |
64 | import java.util.Iterator; | 65 | import java.util.Iterator; |
@@ -416,41 +417,46 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | @@ -416,41 +417,46 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | ||
416 | } | 417 | } |
417 | 418 | ||
418 | @Override | 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 | List<RuleChainImportResult> importResults = new ArrayList<>(); | 421 | List<RuleChainImportResult> importResults = new ArrayList<>(); |
422 | + | ||
421 | setRandomRuleChainIds(ruleChainData); | 423 | setRandomRuleChainIds(ruleChainData); |
422 | resetRuleNodeIds(ruleChainData.getMetadata()); | 424 | resetRuleNodeIds(ruleChainData.getMetadata()); |
423 | resetRuleChainMetadataTenantIds(tenantId, ruleChainData.getMetadata()); | 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 | ruleChainData.getMetadata().forEach(md -> saveRuleChainMetaData(tenantId, md)); | 457 | ruleChainData.getMetadata().forEach(md -> saveRuleChainMetaData(tenantId, md)); |
453 | } | 458 | } |
459 | + | ||
454 | return importResults; | 460 | return importResults; |
455 | } | 461 | } |
456 | 462 | ||
@@ -475,7 +481,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | @@ -475,7 +481,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | ||
475 | } | 481 | } |
476 | if (isTenantId) { | 482 | if (isTenantId) { |
477 | ObjectNode objNode = (ObjectNode) node; | 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 | } else { | 487 | } else { |
480 | for (JsonNode jsonNode : node) { | 488 | for (JsonNode jsonNode : node) { |
481 | searchTenantIdRecursive(tenantId, jsonNode); | 489 | searchTenantIdRecursive(tenantId, jsonNode); |
@@ -723,4 +731,5 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | @@ -723,4 +731,5 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | ||
723 | checkRuleNodesAndDelete(tenantId, entity.getId()); | 731 | checkRuleNodesAndDelete(tenantId, entity.getId()); |
724 | } | 732 | } |
725 | }; | 733 | }; |
734 | + | ||
726 | } | 735 | } |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.rule; | 16 | package org.thingsboard.server.dao.rule; |
17 | 17 | ||
18 | +import org.thingsboard.server.common.data.id.TenantId; | ||
18 | import org.thingsboard.server.common.data.page.PageData; | 19 | import org.thingsboard.server.common.data.page.PageData; |
19 | import org.thingsboard.server.common.data.page.PageLink; | 20 | import org.thingsboard.server.common.data.page.PageLink; |
20 | import org.thingsboard.server.common.data.rule.RuleChain; | 21 | import org.thingsboard.server.common.data.rule.RuleChain; |
@@ -22,6 +23,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; | @@ -22,6 +23,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; | ||
22 | import org.thingsboard.server.dao.Dao; | 23 | import org.thingsboard.server.dao.Dao; |
23 | import org.thingsboard.server.dao.TenantEntityDao; | 24 | import org.thingsboard.server.dao.TenantEntityDao; |
24 | 25 | ||
26 | +import java.util.Collection; | ||
25 | import java.util.UUID; | 27 | import java.util.UUID; |
26 | 28 | ||
27 | /** | 29 | /** |
@@ -74,4 +76,7 @@ public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao { | @@ -74,4 +76,7 @@ public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao { | ||
74 | * @return the list of rule chain objects | 76 | * @return the list of rule chain objects |
75 | */ | 77 | */ |
76 | PageData<RuleChain> findAutoAssignToEdgeRuleChainsByTenantId(UUID tenantId, PageLink pageLink); | 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,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.RuleChainEntity; | ||
29 | import org.thingsboard.server.dao.rule.RuleChainDao; | 29 | import org.thingsboard.server.dao.rule.RuleChainDao; |
30 | import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | 30 | import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
31 | 31 | ||
32 | +import java.util.Collection; | ||
32 | import java.util.Objects; | 33 | import java.util.Objects; |
33 | import java.util.UUID; | 34 | import java.util.UUID; |
34 | 35 | ||
@@ -98,7 +99,13 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | @@ -98,7 +99,13 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | ||
98 | } | 99 | } |
99 | 100 | ||
100 | @Override | 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 | public Long countByTenantId(TenantId tenantId) { | 107 | public Long countByTenantId(TenantId tenantId) { |
102 | return ruleChainRepository.countByTenantId(tenantId.getId()); | 108 | return ruleChainRepository.countByTenantId(tenantId.getId()); |
103 | } | 109 | } |
110 | + | ||
104 | } | 111 | } |
@@ -23,6 +23,7 @@ import org.springframework.data.repository.query.Param; | @@ -23,6 +23,7 @@ import org.springframework.data.repository.query.Param; | ||
23 | import org.thingsboard.server.common.data.rule.RuleChainType; | 23 | import org.thingsboard.server.common.data.rule.RuleChainType; |
24 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; | 24 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; |
25 | 25 | ||
26 | +import java.util.List; | ||
26 | import java.util.UUID; | 27 | import java.util.UUID; |
27 | 28 | ||
28 | public interface RuleChainRepository extends PagingAndSortingRepository<RuleChainEntity, UUID> { | 29 | public interface RuleChainRepository extends PagingAndSortingRepository<RuleChainEntity, UUID> { |
@@ -55,10 +56,13 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai | @@ -55,10 +56,13 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai | ||
55 | "AND re.relationType = 'Contains' AND re.fromId = :tenantId AND re.fromType = 'TENANT' " + | 56 | "AND re.relationType = 'Contains' AND re.fromId = :tenantId AND re.fromType = 'TENANT' " + |
56 | "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") | 57 | "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
57 | Page<RuleChainEntity> findAutoAssignByTenantId(@Param("tenantId") UUID tenantId, | 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 | RuleChainEntity findByTenantIdAndTypeAndRootIsTrue(UUID tenantId, RuleChainType ruleChainType); | 62 | RuleChainEntity findByTenantIdAndTypeAndRootIsTrue(UUID tenantId, RuleChainType ruleChainType); |
62 | 63 | ||
63 | Long countByTenantId(UUID tenantId); | 64 | Long countByTenantId(UUID tenantId); |
65 | + | ||
66 | + List<RuleChainEntity> findByTenantIdAndTypeAndName(UUID tenantId, RuleChainType type, String name); | ||
67 | + | ||
64 | } | 68 | } |