Merge branch 'develop/1.5' of github.com:thingsboard/thingsboard into develop/1.5
This commit is contained in:
		
						commit
						017881cbec
					
				@ -19,6 +19,8 @@ public enum RelationTypeGroup {
 | 
			
		||||
 | 
			
		||||
    COMMON,
 | 
			
		||||
    ALARM,
 | 
			
		||||
    DASHBOARD
 | 
			
		||||
    DASHBOARD,
 | 
			
		||||
    RULE_CHAIN,
 | 
			
		||||
    RULE_NODE
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,75 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2018 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 org.thingsboard.server.common.data.id.RuleChainId;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by igor on 3/13/18.
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class RuleChainMetaData {
 | 
			
		||||
 | 
			
		||||
    private RuleChainId ruleChainId;
 | 
			
		||||
 | 
			
		||||
    private Integer firstNodeIndex;
 | 
			
		||||
 | 
			
		||||
    private List<RuleNode> nodes;
 | 
			
		||||
 | 
			
		||||
    private List<NodeConnectionInfo> connections;
 | 
			
		||||
 | 
			
		||||
    private List<RuleChainConnectionInfo> ruleChainConnections;
 | 
			
		||||
 | 
			
		||||
    public void addConnectionInfo(int fromIndex, int toIndex, String type) {
 | 
			
		||||
        NodeConnectionInfo connectionInfo = new NodeConnectionInfo();
 | 
			
		||||
        connectionInfo.setFromIndex(fromIndex);
 | 
			
		||||
        connectionInfo.setToIndex(toIndex);
 | 
			
		||||
        connectionInfo.setType(type);
 | 
			
		||||
        if (connections == null) {
 | 
			
		||||
            connections = new ArrayList<>();
 | 
			
		||||
        }
 | 
			
		||||
        connections.add(connectionInfo);
 | 
			
		||||
    }
 | 
			
		||||
    public void addRuleChainConnectionInfo(int fromIndex, RuleChainId targetRuleChainId, String type) {
 | 
			
		||||
        RuleChainConnectionInfo connectionInfo = new RuleChainConnectionInfo();
 | 
			
		||||
        connectionInfo.setFromIndex(fromIndex);
 | 
			
		||||
        connectionInfo.setTargetRuleChainId(targetRuleChainId);
 | 
			
		||||
        connectionInfo.setType(type);
 | 
			
		||||
        if (ruleChainConnections == null) {
 | 
			
		||||
            ruleChainConnections = new ArrayList<>();
 | 
			
		||||
        }
 | 
			
		||||
        ruleChainConnections.add(connectionInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Data
 | 
			
		||||
    public class NodeConnectionInfo {
 | 
			
		||||
        private int fromIndex;
 | 
			
		||||
        private int toIndex;
 | 
			
		||||
        private String type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Data
 | 
			
		||||
    public class RuleChainConnectionInfo {
 | 
			
		||||
        private int fromIndex;
 | 
			
		||||
        private RuleChainId targetRuleChainId;
 | 
			
		||||
        private String type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,343 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2018 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.dao.rule;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RuleChainId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RuleNodeId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageData;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageLink;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
 | 
			
		||||
import org.thingsboard.server.dao.exception.DataValidationException;
 | 
			
		||||
import org.thingsboard.server.dao.model.ModelConstants;
 | 
			
		||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
import org.thingsboard.server.dao.service.PaginatedRemover;
 | 
			
		||||
import org.thingsboard.server.dao.service.Validator;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantDao;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.ExecutionException;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by igor on 3/12/18.
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class BaseRuleChainService extends AbstractEntityService implements RuleChainService {
 | 
			
		||||
 | 
			
		||||
    public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID);
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RuleChainDao ruleChainDao;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RuleNodeDao ruleNodeDao;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private TenantDao tenantDao;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleChain saveRuleChain(RuleChain ruleChain) {
 | 
			
		||||
        ruleChainValidator.validate(ruleChain);
 | 
			
		||||
        if (ruleChain.getTenantId() == null) {
 | 
			
		||||
            log.trace("Save system rule chain with predefined id {}", SYSTEM_TENANT);
 | 
			
		||||
            ruleChain.setTenantId(SYSTEM_TENANT);
 | 
			
		||||
        }
 | 
			
		||||
        RuleChain savedRuleChain = ruleChainDao.save(ruleChain);
 | 
			
		||||
        if (ruleChain.isRoot() && ruleChain.getTenantId() != null && ruleChain.getId() == null) {
 | 
			
		||||
            try {
 | 
			
		||||
                createRelation(new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
 | 
			
		||||
                        EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
 | 
			
		||||
            } catch (ExecutionException | InterruptedException e) {
 | 
			
		||||
                log.warn("[{}] Failed to create tenant to root rule chain relation. from: [{}], to: [{}]",
 | 
			
		||||
                        savedRuleChain.getTenantId(), savedRuleChain.getId());
 | 
			
		||||
                throw new RuntimeException(e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return savedRuleChain;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData) {
 | 
			
		||||
        Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id.");
 | 
			
		||||
        RuleChain ruleChain = findRuleChainById(ruleChainMetaData.getRuleChainId());
 | 
			
		||||
        if (ruleChain == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<RuleNode> nodes = ruleChainMetaData.getNodes();
 | 
			
		||||
        List<RuleNode> toAdd = new ArrayList<>();
 | 
			
		||||
        List<RuleNode> toUpdate = new ArrayList<>();
 | 
			
		||||
        List<RuleNode> toDelete = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        Map<RuleNodeId, Integer> ruleNodeIndexMap = new HashMap<>();
 | 
			
		||||
        if (nodes != null) {
 | 
			
		||||
            for (RuleNode node : nodes) {
 | 
			
		||||
                if (node.getId() != null) {
 | 
			
		||||
                    ruleNodeIndexMap.put(node.getId(), nodes.indexOf(node));
 | 
			
		||||
                } else {
 | 
			
		||||
                    toAdd.add(node);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<RuleNode> existingRuleNodes = getRuleChainNodes(ruleChainMetaData.getRuleChainId());
 | 
			
		||||
        for (RuleNode existingNode : existingRuleNodes) {
 | 
			
		||||
            deleteEntityRelations(existingNode.getId());
 | 
			
		||||
            Integer index = ruleNodeIndexMap.get(existingNode.getId());
 | 
			
		||||
            if (index != null) {
 | 
			
		||||
                toUpdate.add(ruleChainMetaData.getNodes().get(index));
 | 
			
		||||
            } else {
 | 
			
		||||
                toDelete.add(existingNode);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (RuleNode node : toAdd) {
 | 
			
		||||
            RuleNode savedNode = ruleNodeDao.save(node);
 | 
			
		||||
            try {
 | 
			
		||||
                createRelation(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
 | 
			
		||||
                        EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
 | 
			
		||||
            } catch (ExecutionException | InterruptedException e) {
 | 
			
		||||
                log.warn("[{}] Failed to create rule chain to rule node relation. from: [{}], to: [{}]",
 | 
			
		||||
                        ruleChainMetaData.getRuleChainId(), savedNode.getId());
 | 
			
		||||
                throw new RuntimeException(e);
 | 
			
		||||
            }
 | 
			
		||||
            int index = nodes.indexOf(node);
 | 
			
		||||
            nodes.set(index, savedNode);
 | 
			
		||||
            ruleNodeIndexMap.put(savedNode.getId(), index);
 | 
			
		||||
        }
 | 
			
		||||
        for (RuleNode node: toDelete) {
 | 
			
		||||
            deleteRuleNode(node.getId());
 | 
			
		||||
        }
 | 
			
		||||
        RuleNodeId firstRuleNodeId = null;
 | 
			
		||||
        if (ruleChainMetaData.getFirstNodeIndex() != null) {
 | 
			
		||||
            firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId();
 | 
			
		||||
        }
 | 
			
		||||
        if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId))
 | 
			
		||||
                || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {
 | 
			
		||||
            ruleChain.setFirstRuleNodeId(firstRuleNodeId);
 | 
			
		||||
            ruleChainDao.save(ruleChain);
 | 
			
		||||
        }
 | 
			
		||||
        if (ruleChainMetaData.getConnections() != null) {
 | 
			
		||||
            for (RuleChainMetaData.NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) {
 | 
			
		||||
                EntityId from = nodes.get(nodeConnection.getFromIndex()).getId();
 | 
			
		||||
                EntityId to = nodes.get(nodeConnection.getToIndex()).getId();
 | 
			
		||||
                String type = nodeConnection.getType();
 | 
			
		||||
                try {
 | 
			
		||||
                    createRelation(new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
 | 
			
		||||
                } catch (ExecutionException | InterruptedException e) {
 | 
			
		||||
                    log.warn("[{}] Failed to create rule node relation. from: [{}], to: [{}]", from, to);
 | 
			
		||||
                    throw new RuntimeException(e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (ruleChainMetaData.getRuleChainConnections() != null) {
 | 
			
		||||
            for (RuleChainMetaData.RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) {
 | 
			
		||||
                EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId();
 | 
			
		||||
                EntityId to = nodeToRuleChainConnection.getTargetRuleChainId();
 | 
			
		||||
                String type = nodeToRuleChainConnection.getType();
 | 
			
		||||
                try {
 | 
			
		||||
                    createRelation(new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
 | 
			
		||||
                } catch (ExecutionException | InterruptedException e) {
 | 
			
		||||
                    log.warn("[{}] Failed to create rule node to rule chain relation. from: [{}], to: [{}]", from, to);
 | 
			
		||||
                    throw new RuntimeException(e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return loadRuleChainMetaData(ruleChainMetaData.getRuleChainId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleChainMetaData loadRuleChainMetaData(RuleChainId ruleChainId) {
 | 
			
		||||
        Validator.validateId(ruleChainId, "Incorrect rule chain id.");
 | 
			
		||||
        RuleChain ruleChain = findRuleChainById(ruleChainId);
 | 
			
		||||
        if (ruleChain == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
 | 
			
		||||
        ruleChainMetaData.setRuleChainId(ruleChainId);
 | 
			
		||||
        List<RuleNode> ruleNodes = getRuleChainNodes(ruleChainId);
 | 
			
		||||
        Map<RuleNodeId, Integer> ruleNodeIndexMap = new HashMap<>();
 | 
			
		||||
        for (RuleNode node : ruleNodes) {
 | 
			
		||||
            ruleNodeIndexMap.put(node.getId(), ruleNodes.indexOf(node));
 | 
			
		||||
        }
 | 
			
		||||
        ruleChainMetaData.setNodes(ruleNodes);
 | 
			
		||||
        if (ruleChain.getFirstRuleNodeId() != null) {
 | 
			
		||||
            ruleChainMetaData.setFirstNodeIndex(ruleNodeIndexMap.get(ruleChain.getFirstRuleNodeId()));
 | 
			
		||||
        }
 | 
			
		||||
        for (RuleNode node : ruleNodes) {
 | 
			
		||||
            int fromIndex = ruleNodeIndexMap.get(node.getId());
 | 
			
		||||
            List<EntityRelation> nodeRelations = getRuleNodeRelations(node.getId());
 | 
			
		||||
            for (EntityRelation nodeRelation : nodeRelations) {
 | 
			
		||||
                String type = nodeRelation.getType();
 | 
			
		||||
                if (nodeRelation.getTo().getEntityType() == EntityType.RULE_NODE) {
 | 
			
		||||
                    RuleNodeId toNodeId = new RuleNodeId(nodeRelation.getTo().getId());
 | 
			
		||||
                    int toIndex = ruleNodeIndexMap.get(toNodeId);
 | 
			
		||||
                    ruleChainMetaData.addConnectionInfo(fromIndex, toIndex, type);
 | 
			
		||||
                } else if (nodeRelation.getTo().getEntityType() == EntityType.RULE_CHAIN) {
 | 
			
		||||
                    RuleChainId targetRuleChainId = new RuleChainId(nodeRelation.getTo().getId());
 | 
			
		||||
                    ruleChainMetaData.addRuleChainConnectionInfo(fromIndex, targetRuleChainId, type);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return ruleChainMetaData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleChain findRuleChainById(RuleChainId ruleChainId) {
 | 
			
		||||
        Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
 | 
			
		||||
        return ruleChainDao.findById(ruleChainId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleChain getRootTenantRuleChain(TenantId tenantId) {
 | 
			
		||||
        Validator.validateId(tenantId, "Incorrect tenant id for search request.");
 | 
			
		||||
        List<EntityRelation> relations = relationService.findByFrom(tenantId, RelationTypeGroup.RULE_CHAIN);
 | 
			
		||||
        if (relations != null && !relations.isEmpty()) {
 | 
			
		||||
            EntityRelation relation = relations.get(0);
 | 
			
		||||
            RuleChainId ruleChainId = new RuleChainId(relation.getTo().getId());
 | 
			
		||||
            return findRuleChainById(ruleChainId);
 | 
			
		||||
        } else {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<RuleNode> getRuleChainNodes(RuleChainId ruleChainId) {
 | 
			
		||||
        Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
 | 
			
		||||
        List<EntityRelation> relations = getRuleChainToNodeRelations(ruleChainId);
 | 
			
		||||
        List<RuleNode> ruleNodes = relations.stream().map(relation -> ruleNodeDao.findById(relation.getTo().getId())).collect(Collectors.toList());
 | 
			
		||||
        return ruleNodes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<EntityRelation> getRuleNodeRelations(RuleNodeId ruleNodeId) {
 | 
			
		||||
        Validator.validateId(ruleNodeId, "Incorrect rule node id for search request.");
 | 
			
		||||
        return relationService.findByFrom(ruleNodeId, RelationTypeGroup.RULE_NODE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<RuleChain> findSystemRuleChains(TextPageLink pageLink) {
 | 
			
		||||
        Validator.validatePageLink(pageLink, "Incorrect PageLink object for search system rule chain request.");
 | 
			
		||||
        List<RuleChain> ruleChains = ruleChainDao.findRuleChainsByTenantId(SYSTEM_TENANT.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(ruleChains, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink) {
 | 
			
		||||
        Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request.");
 | 
			
		||||
        Validator.validatePageLink(pageLink, "Incorrect PageLink object for search rule chain request.");
 | 
			
		||||
        List<RuleChain> ruleChains = ruleChainDao.findRuleChainsByTenantId(tenantId.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(ruleChains, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<RuleChain> findAllTenantRuleChainsByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink) {
 | 
			
		||||
        log.trace("Executing findAllTenantRuleChainsByTenantIdAndPageLink, tenantId [{}], pageLink [{}]", tenantId, pageLink);
 | 
			
		||||
        Validator.validateId(tenantId, "Incorrect tenantId " + tenantId);
 | 
			
		||||
        Validator.validatePageLink(pageLink, "Incorrect page link " + pageLink);
 | 
			
		||||
        List<RuleChain> ruleChains = ruleChainDao.findAllRuleChainsByTenantId(tenantId.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(ruleChains, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteRuleChainById(RuleChainId ruleChainId) {
 | 
			
		||||
        Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request.");
 | 
			
		||||
        checkRuleNodesAndDelete(ruleChainId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteRuleChainsByTenantId(TenantId tenantId) {
 | 
			
		||||
        Validator.validateId(tenantId, "Incorrect tenant id for delete rule chains request.");
 | 
			
		||||
        tenantRuleChainsRemover.removeEntities(tenantId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkRuleNodesAndDelete(RuleChainId ruleChainId) {
 | 
			
		||||
        List<EntityRelation> nodeRelations = getRuleChainToNodeRelations(ruleChainId);
 | 
			
		||||
        for (EntityRelation relation : nodeRelations) {
 | 
			
		||||
            deleteRuleNode(relation.getTo());
 | 
			
		||||
        }
 | 
			
		||||
        deleteEntityRelations(ruleChainId);
 | 
			
		||||
        ruleChainDao.removeById(ruleChainId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<EntityRelation> getRuleChainToNodeRelations(RuleChainId ruleChainId) {
 | 
			
		||||
        return relationService.findByFrom(ruleChainId, RelationTypeGroup.RULE_CHAIN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void deleteRuleNode(EntityId entityId) {
 | 
			
		||||
        deleteEntityRelations(entityId);
 | 
			
		||||
        ruleNodeDao.removeById(entityId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void createRelation(EntityRelation relation) throws ExecutionException, InterruptedException {
 | 
			
		||||
        log.debug("Creating relation: {}", relation);
 | 
			
		||||
        relationService.saveRelationAsync(relation).get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private DataValidator<RuleChain> ruleChainValidator =
 | 
			
		||||
            new DataValidator<RuleChain>() {
 | 
			
		||||
                @Override
 | 
			
		||||
                protected void validateDataImpl(RuleChain ruleChain) {
 | 
			
		||||
                    if (StringUtils.isEmpty(ruleChain.getName())) {
 | 
			
		||||
                        throw new DataValidationException("Rule chain name should be specified!.");
 | 
			
		||||
                    }
 | 
			
		||||
                    if (ruleChain.getTenantId() != null && !ruleChain.getTenantId().isNullUid()) {
 | 
			
		||||
                        Tenant tenant = tenantDao.findById(ruleChain.getTenantId().getId());
 | 
			
		||||
                        if (tenant == null) {
 | 
			
		||||
                            throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
 | 
			
		||||
                        }
 | 
			
		||||
                        if (ruleChain.isRoot()) {
 | 
			
		||||
                            RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
 | 
			
		||||
                            if (ruleChain.getId() == null || !ruleChain.getId().equals(rootRuleChain.getId())) {
 | 
			
		||||
                                throw new DataValidationException("Another root rule chain is present in scope of current tenant!");
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
    private PaginatedRemover<TenantId, RuleChain> tenantRuleChainsRemover =
 | 
			
		||||
            new PaginatedRemover<TenantId, RuleChain>() {
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                protected List<RuleChain> findEntities(TenantId id, TextPageLink pageLink) {
 | 
			
		||||
                    return ruleChainDao.findRuleChainsByTenantId(id.getId(), pageLink);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                protected void removeEntity(RuleChain entity) {
 | 
			
		||||
                    checkRuleNodesAndDelete(entity.getId());
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
}
 | 
			
		||||
@ -20,15 +20,18 @@ import org.springframework.stereotype.Component;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageLink;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.dao.DaoUtil;
 | 
			
		||||
import org.thingsboard.server.dao.model.ModelConstants;
 | 
			
		||||
import org.thingsboard.server.dao.model.nosql.RuleChainEntity;
 | 
			
		||||
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
 | 
			
		||||
import org.thingsboard.server.dao.util.NoSqlDao;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
 | 
			
		||||
import static com.datastax.driver.core.querybuilder.QueryBuilder.in;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.*;
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
@ -57,4 +60,15 @@ public class CassandraRuleChainDao extends CassandraAbstractSearchTextDao<RuleCh
 | 
			
		||||
        return DaoUtil.convertDataList(ruleChainEntities);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
        log.debug("Try to find all rule chains by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
 | 
			
		||||
        List<RuleChainEntity> ruleChainEntities = findPageWithTextSearch(RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
 | 
			
		||||
                Arrays.asList(in(ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY, Arrays.asList(NULL_UUID, tenantId))),
 | 
			
		||||
                pageLink);
 | 
			
		||||
 | 
			
		||||
        log.trace("Found rule chains [{}] by tenantId [{}] and pageLink [{}]", ruleChainEntities, tenantId, pageLink);
 | 
			
		||||
        return DaoUtil.convertDataList(ruleChainEntities);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -37,4 +37,13 @@ public interface RuleChainDao extends Dao<RuleChain> {
 | 
			
		||||
     */
 | 
			
		||||
    List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Find all rule chains by tenantId and page link.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tenantId the tenantId
 | 
			
		||||
     * @param pageLink the page link
 | 
			
		||||
     * @return the list of rule chain objects
 | 
			
		||||
     */
 | 
			
		||||
    List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,19 @@
 | 
			
		||||
 | 
			
		||||
package org.thingsboard.server.dao.rule;
 | 
			
		||||
 | 
			
		||||
import org.thingsboard.server.common.data.id.PluginId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RuleChainId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RuleNodeId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageData;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageLink;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.PluginMetaData;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by igor on 3/12/18.
 | 
			
		||||
@ -25,4 +37,26 @@ public interface RuleChainService {
 | 
			
		||||
 | 
			
		||||
    RuleChain saveRuleChain(RuleChain ruleChain);
 | 
			
		||||
 | 
			
		||||
    RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData);
 | 
			
		||||
 | 
			
		||||
    RuleChainMetaData loadRuleChainMetaData(RuleChainId ruleChainId);
 | 
			
		||||
 | 
			
		||||
    RuleChain findRuleChainById(RuleChainId ruleChainId);
 | 
			
		||||
 | 
			
		||||
    RuleChain getRootTenantRuleChain(TenantId tenantId);
 | 
			
		||||
 | 
			
		||||
    List<RuleNode> getRuleChainNodes(RuleChainId ruleChainId);
 | 
			
		||||
 | 
			
		||||
    List<EntityRelation> getRuleNodeRelations(RuleNodeId ruleNodeId);
 | 
			
		||||
 | 
			
		||||
    TextPageData<RuleChain> findSystemRuleChains(TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    TextPageData<RuleChain> findAllTenantRuleChainsByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    void deleteRuleChainById(RuleChainId ruleChainId);
 | 
			
		||||
 | 
			
		||||
    void deleteRuleChainsByTenantId(TenantId tenantId);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -63,4 +63,15 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
 | 
			
		||||
                        new PageRequest(0, pageLink.getLimit())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
        return DaoUtil.convertDataList(ruleChainRepository
 | 
			
		||||
                .findAllTenantRuleChainsByTenantId(
 | 
			
		||||
                        UUIDConverter.fromTimeUUID(tenantId),
 | 
			
		||||
                        NULL_UUID_STR,
 | 
			
		||||
                        Objects.toString(pageLink.getTextSearch(), ""),
 | 
			
		||||
                        pageLink.getIdOffset() == null ? NULL_UUID_STR :  UUIDConverter.fromTimeUUID(pageLink.getIdOffset()),
 | 
			
		||||
                        new PageRequest(0, pageLink.getLimit())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -35,4 +35,12 @@ public interface RuleChainRepository extends CrudRepository<RuleChainEntity, Str
 | 
			
		||||
                                         @Param("idOffset") String idOffset,
 | 
			
		||||
                                         Pageable pageable);
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT rc FROM RuleChainEntity rc WHERE rc.tenantId IN (:tenantId, :nullTenantId) " +
 | 
			
		||||
            "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " +
 | 
			
		||||
            "AND rc.id > :idOffset ORDER BY rc.id")
 | 
			
		||||
    List<RuleChainEntity> findAllTenantRuleChainsByTenantId(@Param("tenantId") String tenantId,
 | 
			
		||||
                                                            @Param("nullTenantId") String nullTenantId,
 | 
			
		||||
                                                            @Param("searchText") String searchText,
 | 
			
		||||
                                                            @Param("idOffset") String idOffset,
 | 
			
		||||
                                                            Pageable pageable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@ import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
 | 
			
		||||
import org.thingsboard.server.dao.exception.DataValidationException;
 | 
			
		||||
import org.thingsboard.server.dao.plugin.PluginService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleService;
 | 
			
		||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
import org.thingsboard.server.dao.service.PaginatedRemover;
 | 
			
		||||
@ -76,6 +77,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private PluginService pluginService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RuleChainService ruleChainService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Tenant findTenantById(TenantId tenantId) {
 | 
			
		||||
        log.trace("Executing findTenantById [{}]", tenantId);
 | 
			
		||||
@ -108,6 +112,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
 | 
			
		||||
        assetService.deleteAssetsByTenantId(tenantId);
 | 
			
		||||
        deviceService.deleteDevicesByTenantId(tenantId);
 | 
			
		||||
        userService.deleteTenantAdmins(tenantId);
 | 
			
		||||
        ruleChainService.deleteRuleChainsByTenantId(tenantId);
 | 
			
		||||
        ruleService.deleteRulesByTenantId(tenantId);
 | 
			
		||||
        pluginService.deletePluginsByTenantId(tenantId);
 | 
			
		||||
        tenantDao.removeById(tenantId.getId());
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user