From 3c43d039e8970d6ae1ebdfc21b41bd2cec7daba4 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 29 May 2017 17:50:33 +0300 Subject: [PATCH] Add relationTypeGroup to relation column family. --- .../controller/EntityRelationController.java | 67 +++++++++++---- .../server/common/data/Customer.java | 3 + .../server/common/data/DashboardInfo.java | 2 + .../server/common/data/Tenant.java | 2 + .../thingsboard/server/common/data/User.java | 2 + .../server/common/data/alarm/Alarm.java | 3 +- .../common/data/relation/EntityRelation.java | 37 +++++++-- .../data/relation/RelationTypeGroup.java | 23 ++++++ .../server/dao/alarm/AlarmDaoImpl.java | 3 +- .../server/dao/alarm/BaseAlarmService.java | 17 ++-- .../server/dao/model/ModelConstants.java | 1 + .../model/type/RelationTypeGroupCodec.java | 28 +++++++ .../server/dao/relation/BaseRelationDao.java | 69 +++++++++++----- .../dao/relation/BaseRelationService.java | 82 +++++++++++-------- .../server/dao/relation/RelationDao.java | 15 ++-- .../server/dao/relation/RelationService.java | 15 ++-- dao/src/main/resources/schema.cql | 17 ++-- .../dao/service/RelationServiceImplTest.java | 43 +++++----- .../dao/service/RelationServiceTest.java | 43 +++++----- pom.xml | 2 +- ui/src/app/entity/entity-select.directive.js | 6 +- ui/src/app/entity/entity-select.tpl.html | 2 +- .../entity/entity-subtype-select.directive.js | 2 +- 23 files changed, 329 insertions(+), 155 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationTypeGroup.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/type/RelationTypeGroupCodec.java diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 04f1c3ffc7..1a08d56a7f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationInfo; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.relation.EntityRelationsQuery; import org.thingsboard.server.exception.ThingsboardErrorCode; import org.thingsboard.server.exception.ThingsboardException; @@ -51,19 +52,23 @@ public class EntityRelationController extends BaseController { @RequestMapping(value = "/relation", method = RequestMethod.DELETE, params = {"fromId", "fromType", "relationType", "toId", "toType"}) @ResponseStatus(value = HttpStatus.OK) public void deleteRelation(@RequestParam("fromId") String strFromId, - @RequestParam("fromType") String strFromType, @RequestParam("relationType") String strRelationType, + @RequestParam("fromType") String strFromType, + @RequestParam("relationType") String strRelationType, + @RequestParam("relationTypeGroup") String strRelationTypeGroup, @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { checkParameter("fromId", strFromId); checkParameter("fromType", strFromType); checkParameter("relationType", strRelationType); + checkParameter("relationTypeGroup", strRelationTypeGroup); checkParameter("toId", strToId); checkParameter("toType", strToType); EntityId fromId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); checkEntityId(fromId); checkEntityId(toId); + RelationTypeGroup relationTypeGroup = RelationTypeGroup.valueOf(strRelationTypeGroup); try { - Boolean found = relationService.deleteRelation(fromId, toId, strRelationType).get(); + Boolean found = relationService.deleteRelation(fromId, toId, strRelationType, relationTypeGroup).get(); if (!found) { throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); } @@ -92,7 +97,9 @@ public class EntityRelationController extends BaseController { @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType", "toId", "toType"}) @ResponseStatus(value = HttpStatus.OK) public void checkRelation(@RequestParam("fromId") String strFromId, - @RequestParam("fromType") String strFromType, @RequestParam("relationType") String strRelationType, + @RequestParam("fromType") String strFromType, + @RequestParam("relationType") String strRelationType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { try { checkParameter("fromId", strFromId); @@ -104,7 +111,8 @@ public class EntityRelationController extends BaseController { EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); checkEntityId(fromId); checkEntityId(toId); - Boolean found = relationService.checkRelation(fromId, toId, strRelationType).get(); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); + Boolean found = relationService.checkRelation(fromId, toId, strRelationType, typeGroup).get(); if (!found) { throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); } @@ -116,13 +124,16 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType"}) @ResponseBody - public List findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException { + public List findByFrom(@RequestParam("fromId") String strFromId, + @RequestParam("fromType") String strFromType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter("fromId", strFromId); checkParameter("fromType", strFromType); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); checkEntityId(entityId); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); try { - return checkNotNull(relationService.findByFrom(entityId).get()); + return checkNotNull(relationService.findByFrom(entityId, typeGroup).get()); } catch (Exception e) { throw handleException(e); } @@ -131,13 +142,16 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {"fromId", "fromType"}) @ResponseBody - public List findInfoByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException { + public List findInfoByFrom(@RequestParam("fromId") String strFromId, + @RequestParam("fromType") String strFromType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter("fromId", strFromId); checkParameter("fromType", strFromType); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); checkEntityId(entityId); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); try { - return checkNotNull(relationService.findInfoByFrom(entityId).get()); + return checkNotNull(relationService.findInfoByFrom(entityId, typeGroup).get()); } catch (Exception e) { throw handleException(e); } @@ -146,15 +160,18 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType"}) @ResponseBody - public List findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType - , @RequestParam("relationType") String strRelationType) throws ThingsboardException { + public List findByFrom(@RequestParam("fromId") String strFromId, + @RequestParam("fromType") String strFromType, + @RequestParam("relationType") String strRelationType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter("fromId", strFromId); checkParameter("fromType", strFromType); checkParameter("relationType", strRelationType); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); checkEntityId(entityId); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); try { - return checkNotNull(relationService.findByFromAndType(entityId, strRelationType).get()); + return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup).get()); } catch (Exception e) { throw handleException(e); } @@ -163,13 +180,16 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType"}) @ResponseBody - public List findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { + public List findByTo(@RequestParam("toId") String strToId, + @RequestParam("toType") String strToType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter("toId", strToId); checkParameter("toType", strToType); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); checkEntityId(entityId); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); try { - return checkNotNull(relationService.findByTo(entityId).get()); + return checkNotNull(relationService.findByTo(entityId, typeGroup).get()); } catch (Exception e) { throw handleException(e); } @@ -178,15 +198,18 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType", "relationType"}) @ResponseBody - public List findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType - , @RequestParam("relationType") String strRelationType) throws ThingsboardException { + public List findByTo(@RequestParam("toId") String strToId, + @RequestParam("toType") String strToType, + @RequestParam("relationType") String strRelationType, + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter("toId", strToId); checkParameter("toType", strToType); checkParameter("relationType", strRelationType); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); checkEntityId(entityId); + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); try { - return checkNotNull(relationService.findByToAndType(entityId, strRelationType).get()); + return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup).get()); } catch (Exception e) { throw handleException(e); } @@ -207,4 +230,16 @@ public class EntityRelationController extends BaseController { } } + private RelationTypeGroup parseRelationTypeGroup(String strRelationTypeGroup, RelationTypeGroup defaultValue) { + RelationTypeGroup result = defaultValue; + if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length()>0) { + try { + result = RelationTypeGroup.valueOf(strRelationTypeGroup); + } catch (IllegalArgumentException e) { + result = defaultValue; + } + } + return result; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java index f8c1e3045a..ec535bf44c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.common.data; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonProperty.Access; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -60,6 +62,7 @@ public class Customer extends ContactBased implements HasName { } @Override + @JsonProperty(access = Access.READ_ONLY) public String getName() { return title; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java index c4daf9d85c..3be3b79d56 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data; +import com.fasterxml.jackson.annotation.JsonProperty; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; @@ -65,6 +66,7 @@ public class DashboardInfo extends SearchTextBased implements HasNa } @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return title; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java b/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java index 3a5f6bf09a..4501759e55 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data; +import com.fasterxml.jackson.annotation.JsonProperty; import org.thingsboard.server.common.data.id.TenantId; import com.fasterxml.jackson.databind.JsonNode; @@ -51,6 +52,7 @@ public class Tenant extends ContactBased implements HasName { } @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return title; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/User.java b/common/data/src/main/java/org/thingsboard/server/common/data/User.java index 0543ef0a38..1b97e2e49f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/User.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/User.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data; +import com.fasterxml.jackson.annotation.JsonProperty; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; @@ -78,6 +79,7 @@ public class User extends SearchTextBased implements HasName { } @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return email; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java index 7bf7a08bd9..09695e5ee8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java @@ -15,12 +15,12 @@ */ package org.thingsboard.server.common.data.alarm; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import org.thingsboard.server.common.data.BaseData; -import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; @@ -54,6 +54,7 @@ public class Alarm extends BaseData implements HasName { } @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return type; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java index 39e7d54978..8dab589596 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java @@ -30,6 +30,7 @@ public class EntityRelation { private EntityId from; private EntityId to; private String type; + private RelationTypeGroup typeGroup; private JsonNode additionalInfo; public EntityRelation() { @@ -37,13 +38,18 @@ public class EntityRelation { } public EntityRelation(EntityId from, EntityId to, String type) { - this(from, to, type, null); + this(from, to, type, RelationTypeGroup.COMMON); } - public EntityRelation(EntityId from, EntityId to, String type, JsonNode additionalInfo) { + public EntityRelation(EntityId from, EntityId to, String type, RelationTypeGroup typeGroup) { + this(from, to, type, typeGroup, null); + } + + public EntityRelation(EntityId from, EntityId to, String type, RelationTypeGroup typeGroup, JsonNode additionalInfo) { this.from = from; this.to = to; this.type = type; + this.typeGroup = typeGroup; this.additionalInfo = additionalInfo; } @@ -51,6 +57,7 @@ public class EntityRelation { this.from = entityRelation.getFrom(); this.to = entityRelation.getTo(); this.type = entityRelation.getType(); + this.typeGroup = entityRelation.getTypeGroup(); this.additionalInfo = entityRelation.getAdditionalInfo(); } @@ -78,6 +85,14 @@ public class EntityRelation { this.type = type; } + public RelationTypeGroup getTypeGroup() { + return typeGroup; + } + + public void setTypeGroup(RelationTypeGroup typeGroup) { + this.typeGroup = typeGroup; + } + public JsonNode getAdditionalInfo() { return additionalInfo; } @@ -90,14 +105,22 @@ public class EntityRelation { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - EntityRelation relation = (EntityRelation) o; - return Objects.equals(from, relation.from) && - Objects.equals(to, relation.to) && - Objects.equals(type, relation.type); + + EntityRelation that = (EntityRelation) o; + + if (from != null ? !from.equals(that.from) : that.from != null) return false; + if (to != null ? !to.equals(that.to) : that.to != null) return false; + if (type != null ? !type.equals(that.type) : that.type != null) return false; + return typeGroup == that.typeGroup; + } @Override public int hashCode() { - return Objects.hash(from, to, type); + int result = from != null ? from.hashCode() : 0; + result = 31 * result + (to != null ? to.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (typeGroup != null ? typeGroup.hashCode() : 0); + return result; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationTypeGroup.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationTypeGroup.java new file mode 100644 index 0000000000..82798ab792 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationTypeGroup.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2017 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.relation; + +public enum RelationTypeGroup { + + COMMON, + ALARM + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java index 994fe8036a..1362e6b3a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.AbstractModelDao; import org.thingsboard.server.dao.AbstractSearchTimeDao; import org.thingsboard.server.dao.model.AlarmEntity; @@ -97,7 +98,7 @@ public class AlarmDaoImpl extends AbstractModelDao implements Alarm log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); EntityId affectedEntity = query.getAffectedEntityId(); String relationType = query.getStatus() == null ? BaseAlarmService.ALARM_RELATION : BaseAlarmService.ALARM_RELATION_PREFIX + query.getStatus().name(); - ListenableFuture> relations = relationDao.findRelations(affectedEntity, relationType, EntityType.ALARM, query.getPageLink()); + ListenableFuture> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); return Futures.transform(relations, (AsyncFunction, List>) input -> { List> alarmFutures = new ArrayList<>(input.size()); for (EntityRelation relation : input) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 5b31a51f22..3981f64701 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entity.BaseEntityService; import org.thingsboard.server.dao.exception.DataValidationException; @@ -115,11 +116,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ query.setParameters(new RelationsSearchParameters(saved.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); List parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); for (EntityId parentId : parentEntities) { - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION)); - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name())); + createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); } - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION)); - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name())); + createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); return saved; } @@ -244,11 +245,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); List parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); for (EntityId parentId : parentEntities) { - deleteRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name())); - createRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name())); + deleteRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); } - deleteRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name())); - createRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name())); + deleteRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); } catch (ExecutionException | InterruptedException e) { log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus); throw new RuntimeException(e); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 967f4d1122..dfad10b05d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -175,6 +175,7 @@ public class ModelConstants { public static final String RELATION_TO_ID_PROPERTY = "to_id"; public static final String RELATION_TO_TYPE_PROPERTY = "to_type"; public static final String RELATION_TYPE_PROPERTY = "relation_type"; + public static final String RELATION_TYPE_GROUP_PROPERTY = "relation_type_group"; public static final String RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME = "relation_by_type_and_child_type"; public static final String RELATION_REVERSE_VIEW_NAME = "reverse_relation"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/type/RelationTypeGroupCodec.java b/dao/src/main/java/org/thingsboard/server/dao/model/type/RelationTypeGroupCodec.java new file mode 100644 index 0000000000..1c0514e2f1 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/type/RelationTypeGroupCodec.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2017 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.model.type; + +import org.thingsboard.server.common.data.relation.RelationTypeGroup; + +import com.datastax.driver.extras.codecs.enums.EnumNameCodec; + +public class RelationTypeGroupCodec extends EnumNameCodec { + + public RelationTypeGroupCodec() { + super(RelationTypeGroup.class); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java index 1b05866c75..9fc2382d8d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java @@ -29,9 +29,11 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.AbstractAsyncDao; import org.thingsboard.server.dao.AbstractSearchTimeDao; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.model.type.RelationTypeGroupCodec; import javax.annotation.Nullable; import javax.annotation.PostConstruct; @@ -54,12 +56,15 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { ModelConstants.RELATION_FROM_TYPE_PROPERTY + "," + ModelConstants.RELATION_TO_ID_PROPERTY + "," + ModelConstants.RELATION_TO_TYPE_PROPERTY + "," + + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + "," + ModelConstants.RELATION_TYPE_PROPERTY + "," + ModelConstants.ADDITIONAL_INFO_PROPERTY; public static final String FROM = " FROM "; public static final String WHERE = " WHERE "; public static final String AND = " AND "; + private static final RelationTypeGroupCodec relationTypeGroupCodec = new RelationTypeGroupCodec(); + private PreparedStatement saveStmt; private PreparedStatement findAllByFromStmt; private PreparedStatement findAllByFromAndTypeStmt; @@ -75,43 +80,52 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { } @Override - public ListenableFuture> findAllByFrom(EntityId from) { - BoundStatement stmt = getFindAllByFromStmt().bind().setUUID(0, from.getId()).setString(1, from.getEntityType().name()); + public ListenableFuture> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) { + BoundStatement stmt = getFindAllByFromStmt().bind() + .setUUID(0, from.getId()) + .setString(1, from.getEntityType().name()) + .set(2, typeGroup, relationTypeGroupCodec); return executeAsyncRead(from, stmt); } @Override - public ListenableFuture> findAllByFromAndType(EntityId from, String relationType) { + public ListenableFuture> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { BoundStatement stmt = getFindAllByFromAndTypeStmt().bind() .setUUID(0, from.getId()) .setString(1, from.getEntityType().name()) - .setString(2, relationType); + .set(2, typeGroup, relationTypeGroupCodec) + .setString(3, relationType); return executeAsyncRead(from, stmt); } @Override - public ListenableFuture> findAllByTo(EntityId to) { - BoundStatement stmt = getFindAllByToStmt().bind().setUUID(0, to.getId()).setString(1, to.getEntityType().name()); + public ListenableFuture> findAllByTo(EntityId to, RelationTypeGroup typeGroup) { + BoundStatement stmt = getFindAllByToStmt().bind() + .setUUID(0, to.getId()) + .setString(1, to.getEntityType().name()) + .set(2, typeGroup, relationTypeGroupCodec); return executeAsyncRead(to, stmt); } @Override - public ListenableFuture> findAllByToAndType(EntityId to, String relationType) { + public ListenableFuture> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { BoundStatement stmt = getFindAllByToAndTypeStmt().bind() .setUUID(0, to.getId()) .setString(1, to.getEntityType().name()) - .setString(2, relationType); + .set(2, typeGroup, relationTypeGroupCodec) + .setString(3, relationType); return executeAsyncRead(to, stmt); } @Override - public ListenableFuture checkRelation(EntityId from, EntityId to, String relationType) { + public ListenableFuture checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { BoundStatement stmt = getCheckRelationStmt().bind() .setUUID(0, from.getId()) .setString(1, from.getEntityType().name()) .setUUID(2, to.getId()) .setString(3, to.getEntityType().name()) - .setString(4, relationType); + .set(4, typeGroup, relationTypeGroupCodec) + .setString(5, relationType); return getFuture(executeAsyncRead(stmt), rs -> rs != null ? rs.one() != null : false); } @@ -122,25 +136,27 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { .setString(1, relation.getFrom().getEntityType().name()) .setUUID(2, relation.getTo().getId()) .setString(3, relation.getTo().getEntityType().name()) - .setString(4, relation.getType()) - .set(5, relation.getAdditionalInfo(), JsonNode.class); + .set(4, relation.getTypeGroup(), relationTypeGroupCodec) + .setString(5, relation.getType()) + .set(6, relation.getAdditionalInfo(), JsonNode.class); ResultSetFuture future = executeAsyncWrite(stmt); return getBooleanListenableFuture(future); } @Override public ListenableFuture deleteRelation(EntityRelation relation) { - return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType()); + return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup()); } @Override - public ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType) { + public ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { BoundStatement stmt = getDeleteStmt().bind() .setUUID(0, from.getId()) .setString(1, from.getEntityType().name()) .setUUID(2, to.getId()) .setString(3, to.getEntityType().name()) - .setString(4, relationType); + .set(4, typeGroup, relationTypeGroupCodec) + .setString(5, relationType); ResultSetFuture future = executeAsyncWrite(stmt); return getBooleanListenableFuture(future); } @@ -155,13 +171,16 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { } @Override - public ListenableFuture> findRelations(EntityId from, String relationType, EntityType childType, TimePageLink pageLink) { + public ListenableFuture> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType, TimePageLink pageLink) { Select.Where query = AbstractSearchTimeDao.buildQuery(ModelConstants.RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME, Arrays.asList(eq(ModelConstants.RELATION_FROM_ID_PROPERTY, from.getId()), eq(ModelConstants.RELATION_FROM_TYPE_PROPERTY, from.getEntityType().name()), + eq(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, typeGroup.name()), eq(ModelConstants.RELATION_TYPE_PROPERTY, relationType), eq(ModelConstants.RELATION_TO_TYPE_PROPERTY, childType.name())), - Arrays.asList(QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)), + Arrays.asList(QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), + QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), + QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)), pageLink, ModelConstants.RELATION_TO_ID_PROPERTY); return getFuture(executeAsyncRead(query), rs -> getEntityRelations(rs)); } @@ -173,9 +192,10 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { "," + ModelConstants.RELATION_FROM_TYPE_PROPERTY + "," + ModelConstants.RELATION_TO_ID_PROPERTY + "," + ModelConstants.RELATION_TO_TYPE_PROPERTY + + "," + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + "," + ModelConstants.RELATION_TYPE_PROPERTY + "," + ModelConstants.ADDITIONAL_INFO_PROPERTY + ")" + - " VALUES(?, ?, ?, ?, ?, ?)"); + " VALUES(?, ?, ?, ?, ?, ?, ?)"); } return saveStmt; } @@ -187,6 +207,7 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ?" + AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ?" + AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ?" + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ?" + AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ?"); } return deleteStmt; @@ -206,7 +227,8 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { findAllByFromStmt = getSession().prepare(SELECT_COLUMNS + " " + FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + - AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? "); + AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? "); } return findAllByFromStmt; } @@ -217,17 +239,20 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); } return findAllByFromAndTypeStmt; } + private PreparedStatement getFindAllByToStmt() { if (findAllByToStmt == null) { findAllByToStmt = getSession().prepare(SELECT_COLUMNS + " " + FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + - AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? "); + AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? "); } return findAllByToStmt; } @@ -238,11 +263,13 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); } return findAllByToAndTypeStmt; } + private PreparedStatement getCheckRelationStmt() { if (checkRelationStmt == null) { checkRelationStmt = getSession().prepare(SELECT_COLUMNS + " " + @@ -251,6 +278,7 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); } return checkRelationStmt; @@ -292,6 +320,7 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { private EntityRelation getEntityRelation(Row row) { EntityRelation relation = new EntityRelation(); + relation.setTypeGroup(row.get(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, relationTypeGroupCodec)); relation.setType(row.getString(ModelConstants.RELATION_TYPE_PROPERTY)); relation.setAdditionalInfo(row.get(ModelConstants.ADDITIONAL_INFO_PROPERTY, JsonNode.class)); relation.setFrom(toEntity(row, ModelConstants.RELATION_FROM_ID_PROPERTY, ModelConstants.RELATION_FROM_TYPE_PROPERTY)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index 9b4f90605d..9559cd3432 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationInfo; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.device.DeviceService; @@ -60,10 +61,10 @@ public class BaseRelationService implements RelationService { private EntityService entityService; @Override - public ListenableFuture checkRelation(EntityId from, EntityId to, String relationType) { - log.trace("Executing checkRelation [{}][{}][{}]", from, to, relationType); - validate(from, to, relationType); - return relationDao.checkRelation(from, to, relationType); + public ListenableFuture checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { + log.trace("Executing checkRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup); + validate(from, to, relationType, typeGroup); + return relationDao.checkRelation(from, to, relationType, typeGroup); } @Override @@ -81,23 +82,28 @@ public class BaseRelationService implements RelationService { } @Override - public ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType) { - log.trace("Executing deleteRelation [{}][{}][{}]", from, to, relationType); - validate(from, to, relationType); - return relationDao.deleteRelation(from, to, relationType); + public ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { + log.trace("Executing deleteRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup); + validate(from, to, relationType, typeGroup); + return relationDao.deleteRelation(from, to, relationType, typeGroup); } @Override public ListenableFuture deleteEntityRelations(EntityId entity) { log.trace("Executing deleteEntityRelations [{}]", entity); validate(entity); - ListenableFuture> inboundRelations = relationDao.findAllByTo(entity); - ListenableFuture> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction, List>() { + List>> inboundRelationsList = new ArrayList<>(); + for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { + inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup)); + } + Futures.allAsList(inboundRelationsList); + ListenableFuture>> inboundRelations = Futures.allAsList(inboundRelationsList); + ListenableFuture> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction>, List>() { @Override - public ListenableFuture> apply(List relations) throws Exception { + public ListenableFuture> apply(List> relations) throws Exception { List> results = new ArrayList<>(); - for (EntityRelation relation : relations) { - results.add(relationDao.deleteRelation(relation)); + for (List relationList : relations) { + relationList.stream().forEach(relation -> results.add(relationDao.deleteRelation(relation))); } return Futures.allAsList(results); } @@ -111,17 +117,19 @@ public class BaseRelationService implements RelationService { } @Override - public ListenableFuture> findByFrom(EntityId from) { - log.trace("Executing findByFrom [{}]", from); + public ListenableFuture> findByFrom(EntityId from, RelationTypeGroup typeGroup) { + log.trace("Executing findByFrom [{}][{}]", from, typeGroup); validate(from); - return relationDao.findAllByFrom(from); + validateTypeGroup(typeGroup); + return relationDao.findAllByFrom(from, typeGroup); } @Override - public ListenableFuture> findInfoByFrom(EntityId from) { - log.trace("Executing findInfoByFrom [{}]", from); + public ListenableFuture> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup) { + log.trace("Executing findInfoByFrom [{}][{}]", from, typeGroup); validate(from); - ListenableFuture> relations = relationDao.findAllByFrom(from); + validateTypeGroup(typeGroup); + ListenableFuture> relations = relationDao.findAllByFrom(from, typeGroup); ListenableFuture> relationsInfo = Futures.transform(relations, (AsyncFunction, List>) relations1 -> { List> futures = new ArrayList<>(); @@ -143,26 +151,29 @@ public class BaseRelationService implements RelationService { } @Override - public ListenableFuture> findByFromAndType(EntityId from, String relationType) { - log.trace("Executing findByFromAndType [{}][{}]", from, relationType); + public ListenableFuture> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { + log.trace("Executing findByFromAndType [{}][{}][{}]", from, relationType, typeGroup); validate(from); validateType(relationType); - return relationDao.findAllByFromAndType(from, relationType); + validateTypeGroup(typeGroup); + return relationDao.findAllByFromAndType(from, relationType, typeGroup); } @Override - public ListenableFuture> findByTo(EntityId to) { - log.trace("Executing findByTo [{}]", to); + public ListenableFuture> findByTo(EntityId to, RelationTypeGroup typeGroup) { + log.trace("Executing findByTo [{}][{}]", to, typeGroup); validate(to); - return relationDao.findAllByTo(to); + validateTypeGroup(typeGroup); + return relationDao.findAllByTo(to, typeGroup); } @Override - public ListenableFuture> findByToAndType(EntityId to, String relationType) { - log.trace("Executing findByToAndType [{}][{}]", to, relationType); + public ListenableFuture> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { + log.trace("Executing findByToAndType [{}][{}][{}]", to, relationType, typeGroup); validate(to); validateType(relationType); - return relationDao.findAllByToAndType(to, relationType); + validateTypeGroup(typeGroup); + return relationDao.findAllByToAndType(to, relationType, typeGroup); } @Override @@ -204,11 +215,12 @@ public class BaseRelationService implements RelationService { if (relation == null) { throw new DataValidationException("Relation type should be specified!"); } - validate(relation.getFrom(), relation.getTo(), relation.getType()); + validate(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup()); } - protected void validate(EntityId from, EntityId to, String type) { + protected void validate(EntityId from, EntityId to, String type, RelationTypeGroup typeGroup) { validateType(type); + validateTypeGroup(typeGroup); if (from == null) { throw new DataValidationException("Relation should contain from entity!"); } @@ -223,6 +235,12 @@ public class BaseRelationService implements RelationService { } } + private void validateTypeGroup(RelationTypeGroup typeGroup) { + if (typeGroup == null) { + throw new DataValidationException("Relation type group should be specified!"); + } + } + protected void validate(EntityId entity) { if (entity == null) { throw new DataValidationException("Entity should be specified!"); @@ -294,9 +312,9 @@ public class BaseRelationService implements RelationService { private ListenableFuture> findRelations(final EntityId rootId, final EntitySearchDirection direction) { ListenableFuture> relations; if (direction == EntitySearchDirection.FROM) { - relations = findByFrom(rootId); + relations = findByFrom(rootId, RelationTypeGroup.COMMON); } else { - relations = findByTo(rootId); + relations = findByTo(rootId, RelationTypeGroup.COMMON); } return relations; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java index bec03208ac..3abadb8253 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import java.util.List; @@ -28,24 +29,24 @@ import java.util.List; */ public interface RelationDao { - ListenableFuture> findAllByFrom(EntityId from); + ListenableFuture> findAllByFrom(EntityId from, RelationTypeGroup typeGroup); - ListenableFuture> findAllByFromAndType(EntityId from, String relationType); + ListenableFuture> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup); - ListenableFuture> findAllByTo(EntityId to); + ListenableFuture> findAllByTo(EntityId to, RelationTypeGroup typeGroup); - ListenableFuture> findAllByToAndType(EntityId to, String relationType); + ListenableFuture> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup); - ListenableFuture checkRelation(EntityId from, EntityId to, String relationType); + ListenableFuture checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); ListenableFuture saveRelation(EntityRelation relation); ListenableFuture deleteRelation(EntityRelation relation); - ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType); + ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); ListenableFuture deleteOutboundRelations(EntityId entity); - ListenableFuture> findRelations(EntityId from, String relationType, EntityType toType, TimePageLink pageLink); + ListenableFuture> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType toType, TimePageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java index e89985eea8..868769ffe8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationInfo; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import java.util.List; @@ -27,25 +28,25 @@ import java.util.List; */ public interface RelationService { - ListenableFuture checkRelation(EntityId from, EntityId to, String relationType); + ListenableFuture checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); ListenableFuture saveRelation(EntityRelation relation); ListenableFuture deleteRelation(EntityRelation relation); - ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType); + ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); ListenableFuture deleteEntityRelations(EntityId entity); - ListenableFuture> findByFrom(EntityId from); + ListenableFuture> findByFrom(EntityId from, RelationTypeGroup typeGroup); - ListenableFuture> findInfoByFrom(EntityId from); + ListenableFuture> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup); - ListenableFuture> findByFromAndType(EntityId from, String relationType); + ListenableFuture> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup); - ListenableFuture> findByTo(EntityId to); + ListenableFuture> findByTo(EntityId to, RelationTypeGroup typeGroup); - ListenableFuture> findByToAndType(EntityId to, String relationType); + ListenableFuture> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup); ListenableFuture> findByQuery(EntityRelationsQuery query); diff --git a/dao/src/main/resources/schema.cql b/dao/src/main/resources/schema.cql index b72d2f642f..71de6771af 100644 --- a/dao/src/main/resources/schema.cql +++ b/dao/src/main/resources/schema.cql @@ -307,24 +307,25 @@ CREATE TABLE IF NOT EXISTS thingsboard.relation ( from_type text, to_id timeuuid, to_type text, + relation_type_group text, relation_type text, additional_info text, - PRIMARY KEY ((from_id, from_type), relation_type, to_id, to_type) -) WITH CLUSTERING ORDER BY ( relation_type ASC, to_id ASC, to_type ASC); + PRIMARY KEY ((from_id, from_type), relation_type_group, relation_type, to_id, to_type) +) WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, to_id ASC, to_type ASC); CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.relation_by_type_and_child_type AS SELECT * from thingsboard.relation - WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL - PRIMARY KEY ((from_id, from_type), relation_type, to_type, to_id) - WITH CLUSTERING ORDER BY ( relation_type ASC, to_type ASC, to_id DESC); + WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type_group IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL + PRIMARY KEY ((from_id, from_type), relation_type_group, relation_type, to_type, to_id) + WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, to_type ASC, to_id DESC); CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.reverse_relation AS SELECT * from thingsboard.relation - WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL - PRIMARY KEY ((to_id, to_type), relation_type, from_id, from_type) - WITH CLUSTERING ORDER BY ( relation_type ASC, from_id ASC, from_type ASC); + WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type_group IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL + PRIMARY KEY ((to_id, to_type), relation_type_group, relation_type, from_id, from_type) + WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, from_id ASC, from_type ASC); CREATE TABLE IF NOT EXISTS thingsboard.widgets_bundle ( id timeuuid, diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceImplTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceImplTest.java index 3f5c55affd..f7e47ce526 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceImplTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceImplTest.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.EntityRelationsQuery; import org.thingsboard.server.dao.relation.EntitySearchDirection; @@ -55,13 +56,13 @@ public class RelationServiceImplTest extends AbstractServiceTest { Assert.assertTrue(saveRelation(relation)); - Assert.assertTrue(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, "NOT_EXISTING_TYPE").get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, "NOT_EXISTING_TYPE", RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, parentId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(childId, parentId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, parentId, "NOT_EXISTING_TYPE").get()); + Assert.assertFalse(relationService.checkRelation(childId, parentId, "NOT_EXISTING_TYPE", RelationTypeGroup.COMMON).get()); } @Test @@ -78,11 +79,11 @@ public class RelationServiceImplTest extends AbstractServiceTest { Assert.assertTrue(relationService.deleteRelation(relationA).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertTrue(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertTrue(relationService.deleteRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.deleteRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); } @Test @@ -99,9 +100,9 @@ public class RelationServiceImplTest extends AbstractServiceTest { Assert.assertTrue(relationService.deleteEntityRelations(childId).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); } @Test @@ -123,7 +124,7 @@ public class RelationServiceImplTest extends AbstractServiceTest { saveRelation(relationB1); saveRelation(relationB2); - List relations = relationService.findByFrom(parentA).get(); + List relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(EntityRelation.CONTAINS_TYPE, relation.getType()); @@ -131,13 +132,13 @@ public class RelationServiceImplTest extends AbstractServiceTest { Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); } - relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); - relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByFrom(parentB).get(); + relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(EntityRelation.MANAGES_TYPE, relation.getType()); @@ -145,10 +146,10 @@ public class RelationServiceImplTest extends AbstractServiceTest { Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); } - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); } @@ -178,26 +179,26 @@ public class RelationServiceImplTest extends AbstractServiceTest { // Data propagation to views is async Thread.sleep(3000); - List relations = relationService.findByTo(childA).get(); + List relations = relationService.findByTo(childA, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(childA, relation.getTo()); Assert.assertTrue(parentA.equals(relation.getFrom()) || parentB.equals(relation.getFrom())); } - relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(1, relations.size()); - relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(1, relations.size()); - relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByTo(childB).get(); + relations = relationService.findByTo(childB, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(childB, relation.getTo()); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceTest.java index 376a88dc49..8a082fc1da 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/RelationServiceTest.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.EntityRelationsQuery; import org.thingsboard.server.dao.relation.EntitySearchDirection; @@ -55,13 +56,13 @@ public class RelationServiceTest extends AbstractServiceTest { Assert.assertTrue(saveRelation(relation)); - Assert.assertTrue(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, "NOT_EXISTING_TYPE").get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, "NOT_EXISTING_TYPE", RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, parentId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(childId, parentId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, parentId, "NOT_EXISTING_TYPE").get()); + Assert.assertFalse(relationService.checkRelation(childId, parentId, "NOT_EXISTING_TYPE", RelationTypeGroup.COMMON).get()); } @Test @@ -78,11 +79,11 @@ public class RelationServiceTest extends AbstractServiceTest { Assert.assertTrue(relationService.deleteRelation(relationA).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertTrue(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertTrue(relationService.deleteRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertTrue(relationService.deleteRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); } @Test @@ -99,9 +100,9 @@ public class RelationServiceTest extends AbstractServiceTest { Assert.assertTrue(relationService.deleteEntityRelations(childId).get()); - Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(parentId, childId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); - Assert.assertFalse(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE).get()); + Assert.assertFalse(relationService.checkRelation(childId, subChildId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get()); } @Test @@ -123,7 +124,7 @@ public class RelationServiceTest extends AbstractServiceTest { saveRelation(relationB1); saveRelation(relationB2); - List relations = relationService.findByFrom(parentA).get(); + List relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(EntityRelation.CONTAINS_TYPE, relation.getType()); @@ -131,13 +132,13 @@ public class RelationServiceTest extends AbstractServiceTest { Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); } - relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); - relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByFrom(parentB).get(); + relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(EntityRelation.MANAGES_TYPE, relation.getType()); @@ -145,10 +146,10 @@ public class RelationServiceTest extends AbstractServiceTest { Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); } - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); } @@ -178,26 +179,26 @@ public class RelationServiceTest extends AbstractServiceTest { // Data propagation to views is async Thread.sleep(3000); - List relations = relationService.findByTo(childA).get(); + List relations = relationService.findByTo(childA, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(childA, relation.getTo()); Assert.assertTrue(parentA.equals(relation.getFrom()) || parentB.equals(relation.getFrom())); } - relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE).get(); + relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(1, relations.size()); - relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(1, relations.size()); - relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE).get(); + relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); Assert.assertEquals(0, relations.size()); - relations = relationService.findByTo(childB).get(); + relations = relationService.findByTo(childB, RelationTypeGroup.COMMON).get(); Assert.assertEquals(2, relations.size()); for (EntityRelation relation : relations) { Assert.assertEquals(childB, relation.getTo()); diff --git a/pom.xml b/pom.xml index fe95d9b9d9..9e59137d0b 100755 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 18.0 3.4 1.5.0 - 2.7.3 + 2.8.8.1 2.2.6 2.11 2.4.2 diff --git a/ui/src/app/entity/entity-select.directive.js b/ui/src/app/entity/entity-select.directive.js index 8988aaeccd..705c6b8627 100644 --- a/ui/src/app/entity/entity-select.directive.js +++ b/ui/src/app/entity/entity-select.directive.js @@ -29,7 +29,7 @@ export default function EntitySelect($compile, $templateCache) { element.html(template); scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false; - scope.model = null; + scope.model = {}; scope.updateView = function () { if (!scope.disabled) { @@ -50,11 +50,11 @@ export default function EntitySelect($compile, $templateCache) { ngModelCtrl.$render = function () { if (ngModelCtrl.$viewValue) { var value = ngModelCtrl.$viewValue; - scope.model = {}; scope.model.entityType = value.entityType; scope.model.entityId = value.id; } else { - scope.model = null; + scope.model.entityType = null; + scope.model.entityId = null; } } diff --git a/ui/src/app/entity/entity-select.tpl.html b/ui/src/app/entity/entity-select.tpl.html index a354b1dcf6..ce0a16b483 100644 --- a/ui/src/app/entity/entity-select.tpl.html +++ b/ui/src/app/entity/entity-select.tpl.html @@ -19,7 +19,7 @@ -