From 1974843557c0dbc818ad23c4beb73c45c0e50ec0 Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Mon, 23 Jan 2023 15:48:21 +0200 Subject: [PATCH] develop -> master --- .../filter/TbAbstractTypeSwitchNode.java | 10 ++---- .../engine/filter/TbAssetTypeSwitchNode.java | 17 +++++++--- .../engine/filter/TbDeviceTypeSwitchNode.java | 19 +++++++---- .../filter/TbOriginatorTypeSwitchNode.java | 20 +++--------- .../filter/TbAssetTypeSwitchNodeTest.java | 32 +++++++++++-------- .../filter/TbDeviceTypeSwitchNodeTest.java | 32 +++++++++++-------- 6 files changed, 69 insertions(+), 61 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAbstractTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAbstractTypeSwitchNode.java index 7fa1b12db4..a745b04c99 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAbstractTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAbstractTypeSwitchNode.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.msg.TbMsg; @Slf4j public abstract class TbAbstractTypeSwitchNode implements TbNode { - protected EmptyNodeConfiguration config; + private EmptyNodeConfiguration config; @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { @@ -36,14 +36,10 @@ public abstract class TbAbstractTypeSwitchNode implements TbNode { } @Override - public void onMsg(TbContext ctx, TbMsg msg) { + public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { ctx.tellNext(msg, getRelationType(ctx, msg.getOriginator())); } - @Override - public void destroy() { - } - - protected abstract String getRelationType(TbContext ctx, EntityId originator); + protected abstract String getRelationType(TbContext ctx, EntityId originator) throws TbNodeException; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java index 95d4918449..1243c9b28e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java @@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; @@ -31,17 +33,22 @@ import org.thingsboard.server.common.data.plugin.ComponentType; customRelations = true, relationTypes = {}, configClazz = EmptyNodeConfiguration.class, - nodeDescription = "Route incoming messages by Asset Type", - nodeDetails = "Routes messages to chain according to the asset type", + nodeDescription = "Route incoming messages based on the name of the asset profile", + nodeDetails = "Route incoming messages based on the name of the asset profile. The asset profile name is case-sensitive", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbAssetTypeSwitchNode extends TbAbstractTypeSwitchNode { - protected String getRelationType(TbContext ctx, EntityId originator) { + @Override + protected String getRelationType(TbContext ctx, EntityId originator) throws TbNodeException { if (!EntityType.ASSET.equals(originator.getEntityType())) { - throw new RuntimeException("Unsupported originator type: " + originator.getEntityType() + "!"); + throw new TbNodeException("Unsupported originator type: " + originator.getEntityType() + "! Only 'ASSET' type is allowed."); } - return ctx.getAssetProfileCache().get(ctx.getTenantId(), (AssetId) originator).getName(); + AssetProfile assetProfile = ctx.getAssetProfileCache().get(ctx.getTenantId(), (AssetId) originator); + if (assetProfile == null) { + throw new TbNodeException("Asset profile for entity id: " + originator.getId() + " wasn't found!"); + } + return assetProfile.getName(); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java index 5998b777a6..9a2d04d0e3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java @@ -19,6 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; @@ -29,19 +31,24 @@ import org.thingsboard.server.common.data.plugin.ComponentType; type = ComponentType.FILTER, name = "device type switch", customRelations = true, - relationTypes = {}, + relationTypes = {"default"}, configClazz = EmptyNodeConfiguration.class, - nodeDescription = "Route incoming messages by Device Type", - nodeDetails = "Routes messages to chain according to the device type", + nodeDescription = "Route incoming messages based on the name of the device profile", + nodeDetails = "Route incoming messages based on the name of the device profile. The device profile name is case-sensitive", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbDeviceTypeSwitchNode extends TbAbstractTypeSwitchNode { - protected String getRelationType(TbContext ctx, EntityId originator) { + @Override + protected String getRelationType(TbContext ctx, EntityId originator) throws TbNodeException { if (!EntityType.DEVICE.equals(originator.getEntityType())) { - throw new RuntimeException("Unsupported originator type: " + originator.getEntityType() + "!"); + throw new TbNodeException("Unsupported originator type: " + originator.getEntityType() + "! Only 'DEVICE' type is allowed."); } - return ctx.getDeviceProfileCache().get(ctx.getTenantId(), (DeviceId) originator).getName(); + DeviceProfile deviceProfile = ctx.getDeviceProfileCache().get(ctx.getTenantId(), (DeviceId) originator); + if (deviceProfile == null) { + throw new TbNodeException("Device profile for entity id: " + originator.getId() + " wasn't found!"); + } + return deviceProfile.getName(); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java index eb444b097a..2d1e92f179 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java @@ -19,13 +19,10 @@ import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; -import org.thingsboard.rule.engine.api.TbNode; -import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.msg.TbMsg; @Slf4j @RuleNode( @@ -37,19 +34,12 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "Routes messages to chain according to the entity type ('Device', 'Asset', etc.).", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") -public class TbOriginatorTypeSwitchNode implements TbNode { - - EmptyNodeConfiguration config; - - @Override - public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { - this.config = TbNodeUtils.convert(configuration, EmptyNodeConfiguration.class); - } +public class TbOriginatorTypeSwitchNode extends TbAbstractTypeSwitchNode { @Override - public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { + protected String getRelationType(TbContext ctx, EntityId originator) throws TbNodeException { String relationType; - EntityType originatorType = msg.getOriginator().getEntityType(); + EntityType originatorType = originator.getEntityType(); switch (originatorType) { case TENANT: relationType = "Tenant"; @@ -87,7 +77,7 @@ public class TbOriginatorTypeSwitchNode implements TbNode { default: throw new TbNodeException("Unsupported originator type: " + originatorType); } - ctx.tellNext(msg, relationType); + return relationType; } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java index 779d34b437..4747a3c18c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java @@ -34,7 +34,6 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.TbMsgCallback; -import java.util.Map; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +43,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -53,6 +51,7 @@ class TbAssetTypeSwitchNodeTest { TenantId tenantId; AssetId assetId; + AssetId assetIdDeleted; AssetProfile assetProfile; TbContext ctx; TbAssetTypeSwitchNode node; @@ -64,6 +63,7 @@ class TbAssetTypeSwitchNodeTest { void setUp() throws TbNodeException { tenantId = new TenantId(UUID.randomUUID()); assetId = new AssetId(UUID.randomUUID()); + assetIdDeleted = new AssetId(UUID.randomUUID()); assetProfile = new AssetProfile(); assetProfile.setTenantId(tenantId); @@ -71,7 +71,7 @@ class TbAssetTypeSwitchNodeTest { //node config = new EmptyNodeConfiguration(); - node = spy(new TbAssetTypeSwitchNode()); + node = new TbAssetTypeSwitchNode(); node.init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); //init mock @@ -83,6 +83,7 @@ class TbAssetTypeSwitchNodeTest { when(ctx.getAssetProfileCache()).thenReturn(assetProfileCache); doReturn(assetProfile).when(assetProfileCache).get(tenantId, assetId); + doReturn(null).when(assetProfileCache).get(tenantId, assetIdDeleted); } @AfterEach @@ -93,12 +94,21 @@ class TbAssetTypeSwitchNodeTest { @Test void givenMsg_whenOnMsg_then_Fail() { CustomerId customerId = new CustomerId(UUID.randomUUID()); - assertThatThrownBy(() -> node.onMsg(ctx, getTbMsg(customerId, "{}"))).isInstanceOf(RuntimeException.class); + assertThatThrownBy(() -> { + node.onMsg(ctx, getTbMsg(customerId)); + }).isInstanceOf(TbNodeException.class).hasMessageContaining("Unsupported originator type"); } @Test - void givenMsg_whenOnMsg_then_Success() { - TbMsg msg = getTbMsg(assetId, "{}"); + void givenMsg_whenOnMsg_EntityIdDeleted_then_Fail() { + assertThatThrownBy(() -> { + node.onMsg(ctx, getTbMsg(assetIdDeleted)); + }).isInstanceOf(TbNodeException.class).hasMessageContaining("Asset profile for entity id"); + } + + @Test + void givenMsg_whenOnMsg_then_Success() throws TbNodeException { + TbMsg msg = getTbMsg(assetId); node.onMsg(ctx, msg); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); @@ -110,13 +120,7 @@ class TbAssetTypeSwitchNodeTest { assertThat(newMsg).isSameAs(msg); } - private TbMsg getTbMsg(EntityId entityId, String data) { - final Map mdMap = Map.of( - "TestKey_1", "Test", - "country", "US", - "voltageDataValue", "220", - "city", "NY" - ); - return TbMsg.newMsg("POST_ATTRIBUTES_REQUEST", entityId, new TbMsgMetaData(mdMap), data, callback); + private TbMsg getTbMsg(EntityId entityId) { + return TbMsg.newMsg("POST_ATTRIBUTES_REQUEST", entityId, new TbMsgMetaData(), "{}", callback); } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java index 20e0750cf2..ed07a332ca 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java @@ -34,7 +34,6 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.TbMsgCallback; -import java.util.Map; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +43,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -53,6 +51,7 @@ class TbDeviceTypeSwitchNodeTest { TenantId tenantId; DeviceId deviceId; + DeviceId deviceIdDeleted; DeviceProfile deviceProfile; TbContext ctx; TbDeviceTypeSwitchNode node; @@ -64,6 +63,7 @@ class TbDeviceTypeSwitchNodeTest { void setUp() throws TbNodeException { tenantId = new TenantId(UUID.randomUUID()); deviceId = new DeviceId(UUID.randomUUID()); + deviceIdDeleted = new DeviceId(UUID.randomUUID()); deviceProfile = new DeviceProfile(); deviceProfile.setTenantId(tenantId); @@ -71,7 +71,7 @@ class TbDeviceTypeSwitchNodeTest { //node config = new EmptyNodeConfiguration(); - node = spy(new TbDeviceTypeSwitchNode()); + node = new TbDeviceTypeSwitchNode(); node.init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); //init mock @@ -83,6 +83,7 @@ class TbDeviceTypeSwitchNodeTest { when(ctx.getDeviceProfileCache()).thenReturn(deviceProfileCache); doReturn(deviceProfile).when(deviceProfileCache).get(tenantId, deviceId); + doReturn(null).when(deviceProfileCache).get(tenantId, deviceIdDeleted); } @AfterEach @@ -93,12 +94,21 @@ class TbDeviceTypeSwitchNodeTest { @Test void givenMsg_whenOnMsg_then_Fail() { CustomerId customerId = new CustomerId(UUID.randomUUID()); - assertThatThrownBy(() -> node.onMsg(ctx, getTbMsg(customerId, "{}"))).isInstanceOf(RuntimeException.class); + assertThatThrownBy(() -> { + node.onMsg(ctx, getTbMsg(customerId)); + }).isInstanceOf(TbNodeException.class).hasMessageContaining("Unsupported originator type"); } @Test - void givenMsg_whenOnMsg_then_Success() { - TbMsg msg = getTbMsg(deviceId, "{}"); + void givenMsg_whenOnMsg_EntityIdDeleted_then_Fail() { + assertThatThrownBy(() -> { + node.onMsg(ctx, getTbMsg(deviceIdDeleted)); + }).isInstanceOf(TbNodeException.class).hasMessageContaining("Device profile for entity id"); + } + + @Test + void givenMsg_whenOnMsg_then_Success() throws TbNodeException { + TbMsg msg = getTbMsg(deviceId); node.onMsg(ctx, msg); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); @@ -110,13 +120,7 @@ class TbDeviceTypeSwitchNodeTest { assertThat(newMsg).isSameAs(msg); } - private TbMsg getTbMsg(EntityId entityId, String data) { - final Map mdMap = Map.of( - "TestKey_1", "Test", - "country", "US", - "voltageDataValue", "220", - "city", "NY" - ); - return TbMsg.newMsg("POST_ATTRIBUTES_REQUEST", entityId, new TbMsgMetaData(mdMap), data, callback); + private TbMsg getTbMsg(EntityId entityId) { + return TbMsg.newMsg("POST_ATTRIBUTES_REQUEST", entityId, new TbMsgMetaData(), "{}", callback); } }