|
|
|
@ -15,23 +15,39 @@ |
|
|
|
*/ |
|
|
|
package org.thingsboard.server.dao.service.validator; |
|
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.apache.commons.collections.CollectionUtils; |
|
|
|
import org.apache.commons.lang3.exception.ExceptionUtils; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.context.annotation.Lazy; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
import org.thingsboard.common.util.JacksonUtil; |
|
|
|
import org.thingsboard.server.common.data.EntityType; |
|
|
|
import org.thingsboard.server.common.data.StringUtils; |
|
|
|
import org.thingsboard.server.common.data.id.TenantId; |
|
|
|
import org.thingsboard.server.common.data.rule.NodeConnectionInfo; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChain; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChainType; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleNode; |
|
|
|
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; |
|
|
|
import org.thingsboard.server.common.data.util.ReflectionUtils; |
|
|
|
import org.thingsboard.server.dao.exception.DataValidationException; |
|
|
|
import org.thingsboard.server.dao.rule.RuleChainDao; |
|
|
|
import org.thingsboard.server.dao.rule.RuleChainService; |
|
|
|
import org.thingsboard.server.dao.service.ConstraintValidator; |
|
|
|
import org.thingsboard.server.dao.service.DataValidator; |
|
|
|
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
|
|
|
import org.thingsboard.server.dao.tenant.TenantService; |
|
|
|
|
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
@Component |
|
|
|
@Slf4j |
|
|
|
public class RuleChainDataValidator extends DataValidator<RuleChain> { |
|
|
|
|
|
|
|
@Autowired |
|
|
|
@ -83,4 +99,53 @@ public class RuleChainDataValidator extends DataValidator<RuleChain> { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static void validateMetaData(RuleChainMetaData ruleChainMetaData) { |
|
|
|
ConstraintValidator.validateFields(ruleChainMetaData); |
|
|
|
ruleChainMetaData.getNodes().forEach(RuleChainDataValidator::validateRuleNode); |
|
|
|
if (CollectionUtils.isNotEmpty(ruleChainMetaData.getConnections())) { |
|
|
|
validateCircles(ruleChainMetaData.getConnections()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static void validateRuleNode(RuleNode ruleNode) { |
|
|
|
String errorPrefix = "'" + ruleNode.getName() + "' node configuration is invalid: "; |
|
|
|
ConstraintValidator.validateFields(ruleNode, errorPrefix); |
|
|
|
Object nodeConfig; |
|
|
|
try { |
|
|
|
Class<Object> nodeConfigType = ReflectionUtils.getAnnotationProperty(ruleNode.getType(), |
|
|
|
"org.thingsboard.rule.engine.api.RuleNode", "configClazz"); |
|
|
|
nodeConfig = JacksonUtil.treeToValue(ruleNode.getConfiguration(), nodeConfigType); |
|
|
|
} catch (Exception e) { |
|
|
|
log.warn("Failed to validate node configuration: {}", ExceptionUtils.getRootCauseMessage(e)); |
|
|
|
return; |
|
|
|
} |
|
|
|
ConstraintValidator.validateFields(nodeConfig, errorPrefix); |
|
|
|
} |
|
|
|
|
|
|
|
private static void validateCircles(List<NodeConnectionInfo> connectionInfos) { |
|
|
|
Map<Integer, Set<Integer>> connectionsMap = new HashMap<>(); |
|
|
|
for (NodeConnectionInfo nodeConnection : connectionInfos) { |
|
|
|
if (nodeConnection.getFromIndex() == nodeConnection.getToIndex()) { |
|
|
|
throw new DataValidationException("Can't create the relation to yourself."); |
|
|
|
} |
|
|
|
connectionsMap |
|
|
|
.computeIfAbsent(nodeConnection.getFromIndex(), from -> new HashSet<>()) |
|
|
|
.add(nodeConnection.getToIndex()); |
|
|
|
} |
|
|
|
connectionsMap.keySet().forEach(key -> validateCircles(key, connectionsMap.get(key), connectionsMap)); |
|
|
|
} |
|
|
|
|
|
|
|
private static void validateCircles(int from, Set<Integer> toList, Map<Integer, Set<Integer>> connectionsMap) { |
|
|
|
if (toList == null) { |
|
|
|
return; |
|
|
|
} |
|
|
|
for (Integer to : toList) { |
|
|
|
if (from == to) { |
|
|
|
throw new DataValidationException("Can't create circling relations in rule chain."); |
|
|
|
} |
|
|
|
validateCircles(from, connectionsMap.get(to), connectionsMap); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|