Browse Source

Merge branch 'develop/3.2' of https://github.com/thingsboard/thingsboard into feature/device-provision-3.2-onlyProfileVersion

pull/3518/head
zbeacon 6 years ago
parent
commit
6eac10d60c
  1. 33
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  2. 7
      common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java
  3. 27
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java
  4. 31
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainImportResult.java
  5. 148
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

33
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@ -49,6 +50,8 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.rule.DefaultRuleChainCreateRequest;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainData;
import org.thingsboard.server.common.data.rule.RuleChainImportResult;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.msg.TbMsg;
@ -386,6 +389,36 @@ public class RuleChainController extends BaseController {
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChains/export", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public RuleChainData exportRuleChains(@RequestParam("limit") int limit) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = new PageLink(limit);
return checkNotNull(ruleChainService.exportTenantRuleChains(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST)
@ResponseBody
public void importRuleChains(@RequestBody RuleChainData ruleChainData, @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, overwrite);
if (!CollectionUtils.isEmpty(importResults)) {
for (RuleChainImportResult importResult : importResults) {
tbClusterService.onEntityStateChange(importResult.getTenantId(), importResult.getRuleChainId(), importResult.getLifecycleEvent());
}
}
} catch (Exception e) {
throw handleException(e);
}
}
private String msgToOutput(TbMsg msg) throws Exception {
ObjectNode msgData = objectMapper.createObjectNode();
if (!StringUtils.isEmpty(msg.getData())) {

7
common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.rule;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId;
@ -23,6 +24,8 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainData;
import org.thingsboard.server.common.data.rule.RuleChainImportResult;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
@ -63,4 +66,8 @@ public interface RuleChainService {
void deleteRuleChainsByTenantId(TenantId tenantId);
RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) throws ThingsboardException;
List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, boolean overwrite);
}

27
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.rule;
import lombok.Data;
import java.util.List;
@Data
public class RuleChainData {
List<RuleChain> ruleChains;
List<RuleChainMetaData> metadata;
}

31
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainImportResult.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.rule;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
@Data
@AllArgsConstructor
public class RuleChainImportResult {
private TenantId tenantId;
private RuleChainId ruleChainId;
private ComponentLifecycleEvent lifecycleEvent;
}

148
dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

@ -15,12 +15,16 @@
*/
package org.thingsboard.server.dao.rule;
import com.datastax.oss.driver.api.core.uuid.Uuids;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
@ -30,11 +34,14 @@ import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainData;
import org.thingsboard.server.common.data.rule.RuleChainImportResult;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.entity.AbstractEntityService;
@ -46,9 +53,14 @@ import org.thingsboard.server.dao.tenant.TenantDao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.DataConstants.TENANT;
/**
* Created by igor on 3/12/18.
@ -57,6 +69,7 @@ import java.util.concurrent.ExecutionException;
@Slf4j
public class BaseRuleChainService extends AbstractEntityService implements RuleChainService {
private static final int DEFAULT_PAGE_SIZE = 1000;
@Autowired
private RuleChainDao ruleChainDao;
@ -358,6 +371,141 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
tenantRuleChainsRemover.removeEntities(tenantId, tenantId);
}
@Override
public RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) {
Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request.");
Validator.validatePageLink(pageLink);
PageData<RuleChain> ruleChainData = ruleChainDao.findRuleChainsByTenantId(tenantId.getId(), pageLink);
List<RuleChain> ruleChains = ruleChainData.getData();
List<RuleChainMetaData> metadata = ruleChains.stream().map(rc -> loadRuleChainMetaData(tenantId, rc.getId())).collect(Collectors.toList());
RuleChainData rcData = new RuleChainData();
rcData.setRuleChains(ruleChains);
rcData.setMetadata(metadata);
setRandomRuleChainIds(rcData);
resetRuleNodeIds(metadata);
return rcData;
}
@Override
public List<RuleChainImportResult> importTenantRuleChains(TenantId tenantId, RuleChainData ruleChainData, boolean overwrite) {
List<RuleChainImportResult> importResults = new ArrayList<>();
setRandomRuleChainIds(ruleChainData);
resetRuleNodeIds(ruleChainData.getMetadata());
resetRuleChainMetadataTenantIds(tenantId, ruleChainData.getMetadata());
if (overwrite) {
List<RuleChain> persistentRuleChains = findAllTenantRuleChains(tenantId);
for (RuleChain ruleChain : ruleChainData.getRuleChains()) {
ComponentLifecycleEvent lifecycleEvent;
Optional<RuleChain> persistentRuleChainOpt = persistentRuleChains.stream().filter(rc -> rc.getName().equals(ruleChain.getName())).findFirst();
if (persistentRuleChainOpt.isPresent()) {
setNewRuleChainId(ruleChain, ruleChainData.getMetadata(), ruleChain.getId(), persistentRuleChainOpt.get().getId());
ruleChain.setRoot(persistentRuleChainOpt.get().isRoot());
lifecycleEvent = ComponentLifecycleEvent.UPDATED;
} else {
ruleChain.setRoot(false);
lifecycleEvent = ComponentLifecycleEvent.CREATED;
}
ruleChain.setTenantId(tenantId);
ruleChainDao.save(tenantId, ruleChain);
importResults.add(new RuleChainImportResult(tenantId, ruleChain.getId(), lifecycleEvent));
}
} else {
if (!CollectionUtils.isEmpty(ruleChainData.getRuleChains())) {
ruleChainData.getRuleChains().forEach(rc -> {
rc.setTenantId(tenantId);
rc.setRoot(false);
RuleChain savedRc = ruleChainDao.save(tenantId, rc);
importResults.add(new RuleChainImportResult(tenantId, savedRc.getId(), ComponentLifecycleEvent.CREATED));
});
}
}
if (!CollectionUtils.isEmpty(ruleChainData.getMetadata())) {
ruleChainData.getMetadata().forEach(md -> saveRuleChainMetaData(tenantId, md));
}
return importResults;
}
private void resetRuleChainMetadataTenantIds(TenantId tenantId, List<RuleChainMetaData> metaData) {
for (RuleChainMetaData md : metaData) {
for (RuleNode node : md.getNodes()) {
JsonNode nodeConfiguration = node.getConfiguration();
searchTenantIdRecursive(tenantId, nodeConfiguration);
}
}
}
private void searchTenantIdRecursive(TenantId tenantId, JsonNode node) {
Iterator<String> iter = node.fieldNames();
boolean isTenantId = false;
while (iter.hasNext()) {
String field = iter.next();
if ("entityType".equals(field) && TENANT.equals(node.get(field).asText())) {
isTenantId = true;
break;
}
}
if (isTenantId) {
ObjectNode objNode = (ObjectNode) node;
objNode.put("id", tenantId.getId().toString());
} else {
Iterator<JsonNode> childIter = node.iterator();
while (childIter.hasNext()) {
searchTenantIdRecursive(tenantId, childIter.next());
}
}
}
private void setRandomRuleChainIds(RuleChainData ruleChainData) {
for (RuleChain ruleChain : ruleChainData.getRuleChains()) {
RuleChainId oldRuleChainId = ruleChain.getId();
RuleChainId newRuleChainId = new RuleChainId(Uuids.timeBased());
setNewRuleChainId(ruleChain, ruleChainData.getMetadata(), oldRuleChainId, newRuleChainId);
ruleChain.setTenantId(null);
}
}
private void resetRuleNodeIds(List<RuleChainMetaData> metaData) {
for (RuleChainMetaData md : metaData) {
for (RuleNode node : md.getNodes()) {
node.setId(null);
node.setRuleChainId(null);
}
}
}
private List<RuleChain> findAllTenantRuleChains(TenantId tenantId) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
return findAllTenantRuleChainsRecursive(tenantId, new ArrayList<>(), pageLink);
}
private List<RuleChain> findAllTenantRuleChainsRecursive(TenantId tenantId, List<RuleChain> accumulator, PageLink pageLink) {
PageData<RuleChain> persistentRuleChainData = findTenantRuleChains(tenantId, pageLink);
List<RuleChain> ruleChains = persistentRuleChainData.getData();
if (!CollectionUtils.isEmpty(ruleChains)) {
accumulator.addAll(ruleChains);
}
if (persistentRuleChainData.hasNext()) {
return findAllTenantRuleChainsRecursive(tenantId, accumulator, pageLink.nextPageLink());
}
return accumulator;
}
private void setNewRuleChainId(RuleChain ruleChain, List<RuleChainMetaData> metadata, RuleChainId oldRuleChainId, RuleChainId newRuleChainId) {
ruleChain.setId(newRuleChainId);
for (RuleChainMetaData metaData : metadata) {
if (metaData.getRuleChainId().equals(oldRuleChainId)) {
metaData.setRuleChainId(newRuleChainId);
}
if (!CollectionUtils.isEmpty(metaData.getRuleChainConnections())) {
for (RuleChainConnectionInfo rcConnInfo : metaData.getRuleChainConnections()) {
if (rcConnInfo.getTargetRuleChainId().equals(oldRuleChainId)) {
rcConnInfo.setTargetRuleChainId(newRuleChainId);
}
}
}
}
}
private void checkRuleNodesAndDelete(TenantId tenantId, RuleChainId ruleChainId) {
try{
ruleChainDao.removeById(tenantId, ruleChainId.getId());

Loading…
Cancel
Save