diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 2908a4a39a..541d35b899 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -23,6 +23,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.plugin.PluginService; +import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleService; import org.thingsboard.server.dao.timeseries.TimeseriesService; @@ -71,4 +72,6 @@ public interface TbContext { TimeseriesService getTimeseriesService(); + RelationService getRelationService(); + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttrNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttrNodeConfiguration.java new file mode 100644 index 0000000000..40987daeaa --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttrNodeConfiguration.java @@ -0,0 +1,11 @@ +package org.thingsboard.rule.engine.metadata; + +import lombok.Data; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; + +@Data +public class TbGetRelatedAttrNodeConfiguration { + + private String relationType; + private EntitySearchDirection direction; +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java new file mode 100644 index 0000000000..596b1dfee5 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java @@ -0,0 +1,47 @@ +package org.thingsboard.rule.engine.metadata; + +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import org.apache.commons.collections.CollectionUtils; +import org.thingsboard.rule.engine.TbNodeUtils; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.TbNodeState; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.dao.relation.RelationService; + +import java.util.List; + +import static org.thingsboard.server.common.data.relation.RelationTypeGroup.COMMON; + +public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode { + + private TbGetRelatedAttrNodeConfiguration config; + + @Override + public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException { + this.config = TbNodeUtils.convert(configuration, TbGetRelatedAttrNodeConfiguration.class); + } + + @Override + protected ListenableFuture findEntityAsync(TbContext ctx, EntityId originator) { + RelationService relationService = ctx.getRelationService(); + if (config.getDirection() == EntitySearchDirection.FROM) { + ListenableFuture> asyncRelation = relationService.findByFromAndTypeAsync(originator, config.getRelationType(), COMMON); + return Futures.transform(asyncRelation, (AsyncFunction, EntityId>) + r -> CollectionUtils.isNotEmpty(r) ? Futures.immediateFuture(r.get(0).getTo()) + : Futures.immediateFailedFuture(new IllegalStateException("Relation not found"))); + } else if (config.getDirection() == EntitySearchDirection.TO) { + ListenableFuture> asyncRelation = relationService.findByToAndTypeAsync(originator, config.getRelationType(), COMMON); + return Futures.transform(asyncRelation, (AsyncFunction, EntityId>) + r -> CollectionUtils.isNotEmpty(r) ? Futures.immediateFuture(r.get(0).getFrom()) + : Futures.immediateFailedFuture(new IllegalStateException("Relation not found"))); + } + + return Futures.immediateFailedFuture(new IllegalStateException("Unknown direction")); + } +}