Improve config of 'originator fields' node. Add UI config for 'originator fields' and 'check relation' nodes.

This commit is contained in:
Igor Kulikov 2018-06-01 13:49:09 +03:00
parent 7a687f373c
commit 9ea4fcce6f
6 changed files with 90 additions and 41 deletions

View File

@ -15,10 +15,18 @@
*/
package org.thingsboard.server.common.data;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.id.EntityId;
import java.io.IOException;
/**
* Created by ashvayka on 01.06.18.
*/
@ -26,13 +34,54 @@ import org.thingsboard.server.common.data.id.EntityId;
@AllArgsConstructor
public class EntityFieldsData {
public static final String DEFAULT = "default";
private static final ObjectMapper mapper = new ObjectMapper();
private final EntityId entityId;
private final String name;
private final String type;
public EntityFieldsData(EntityId entityId, String name) {
this(entityId, name, DEFAULT);
static {
SimpleModule entityFieldsModule = new SimpleModule("EntityFieldsModule", new Version(1, 0, 0, null, null, null));
entityFieldsModule.addSerializer(EntityId.class, new EntityIdFieldSerializer());
mapper.disable(MapperFeature.USE_ANNOTATIONS);
mapper.registerModule(entityFieldsModule);
}
private ObjectNode fieldsData;
public EntityFieldsData(BaseData data) {
fieldsData = mapper.valueToTree(data);
}
public String getFieldValue(String field) {
String[] fieldsTree = field.split("\\.");
JsonNode current = fieldsData;
for (String key : fieldsTree) {
if (current.has(key)) {
current = current.get(key);
} else {
current = null;
break;
}
}
if (current != null) {
if (current.isValueNode()) {
return current.asText();
} else {
try {
return mapper.writeValueAsString(current);
} catch (JsonProcessingException e) {
return null;
}
}
} else {
return null;
}
}
private static class EntityIdFieldSerializer extends JsonSerializer<EntityId> {
@Override
public void serialize(EntityId value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeObject(value.getId());
}
}
}

View File

@ -44,7 +44,9 @@ import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback;
configClazz = TbCheckRelationNodeConfiguration.class,
relationTypes = {"True", "False"},
nodeDescription = "Checks the relation from the selected entity to originator of the message by type and direction",
nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.")
nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckRelationConfig")
public class TbCheckRelationNode implements TbNode {
private TbCheckRelationNodeConfiguration config;

View File

@ -18,21 +18,21 @@ package org.thingsboard.rule.engine.metadata;
import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import java.util.HashMap;
import java.util.Map;
@Data
public class TbGetOriginatorFieldsConfiguration implements NodeConfiguration<TbGetOriginatorFieldsConfiguration> {
private boolean fetchName;
private String nameMetadataKey;
private boolean fetchType;
private String typeMetadataKey;
private Map<String, String> fieldsMapping;
@Override
public TbGetOriginatorFieldsConfiguration defaultConfiguration() {
TbGetOriginatorFieldsConfiguration configuration = new TbGetOriginatorFieldsConfiguration();
configuration.setFetchName(true);
configuration.setNameMetadataKey("entityName");
configuration.setFetchType(true);
configuration.setTypeMetadataKey("entityType");
Map<String, String> fieldsMapping = new HashMap<>();
fieldsMapping.put("name", "originatorName");
fieldsMapping.put("type", "originatorType");
configuration.setFieldsMapping(fieldsMapping);
return configuration;
}
}

View File

@ -18,11 +18,7 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
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.*;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.util.EntitiesFieldsAsyncLoader;
import org.thingsboard.server.common.data.id.EntityId;
@ -37,10 +33,12 @@ import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback;
*/
@Slf4j
@RuleNode(type = ComponentType.ENRICHMENT,
name = "entity fields",
name = "originator fields",
configClazz = TbGetOriginatorFieldsConfiguration.class,
nodeDescription = "Add Message Originator Name and Type into Message Metadata",
nodeDetails = "If originator is Asset, Device or Alarm, both name and type are added. In all other cases type will always be \"default\"")
nodeDescription = "Add Message Originator fields values into Message Metadata",
nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorFieldsConfig")
public class TbGetOriginatorFieldsNode implements TbNode {
private TbGetOriginatorFieldsConfiguration config;
@ -61,17 +59,17 @@ public class TbGetOriginatorFieldsNode implements TbNode {
}
private ListenableFuture<Void> putEntityFields(TbContext ctx, EntityId entityId, TbMsg msg) {
if (!config.isFetchName() && !config.isFetchType()) {
if (config.getFieldsMapping().isEmpty()) {
return Futures.immediateFuture(null);
} else {
return Futures.transform(EntitiesFieldsAsyncLoader.findAsync(ctx, entityId),
data -> {
if (config.isFetchName()) {
msg.getMetaData().putValue(config.getNameMetadataKey(), data.getName());
}
if (config.isFetchType()) {
msg.getMetaData().putValue(config.getTypeMetadataKey(), data.getType());
}
config.getFieldsMapping().forEach((field, metaKey) -> {
String val = data.getFieldValue(field);
if (val != null) {
msg.getMetaData().putValue(metaKey, val);
}
});
return null;
}
);

View File

@ -38,25 +38,25 @@ public class EntitiesFieldsAsyncLoader {
switch (original.getEntityType()) {
case TENANT:
return getAsync(ctx.getTenantService().findTenantByIdAsync((TenantId) original),
t -> new EntityFieldsData(t.getId(), t.getName()));
t -> new EntityFieldsData(t));
case CUSTOMER:
return getAsync(ctx.getCustomerService().findCustomerByIdAsync((CustomerId) original),
t -> new EntityFieldsData(t.getId(), t.getName()));
t -> new EntityFieldsData(t));
case USER:
return getAsync(ctx.getUserService().findUserByIdAsync((UserId) original),
t -> new EntityFieldsData(t.getId(), t.getName()));
t -> new EntityFieldsData(t));
case ASSET:
return getAsync(ctx.getAssetService().findAssetByIdAsync((AssetId) original),
t -> new EntityFieldsData(t.getId(), t.getName(), t.getType()));
t -> new EntityFieldsData(t));
case DEVICE:
return getAsync(ctx.getDeviceService().findDeviceByIdAsync((DeviceId) original),
t -> new EntityFieldsData(t.getId(), t.getName(), t.getType()));
t -> new EntityFieldsData(t));
case ALARM:
return getAsync(ctx.getAlarmService().findAlarmByIdAsync((AlarmId) original),
t -> new EntityFieldsData(t.getId(), t.getName(), t.getType()));
t -> new EntityFieldsData(t));
case RULE_CHAIN:
return getAsync(ctx.getRuleChainService().findRuleChainByIdAsync((RuleChainId) original),
t -> new EntityFieldsData(t.getId(), t.getName()));
t -> new EntityFieldsData(t));
default:
return Futures.immediateFailedFuture(new TbNodeException("Unexpected original EntityType " + original));
}