thingsboard-memoizeit

Changes

pom.xml 2(+1 -1)

Details

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 04f1c3f..1a08d56 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<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException {
+    public List<EntityRelation> 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<EntityRelationInfo> findInfoByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException {
+    public List<EntityRelationInfo> 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<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType
-            , @RequestParam("relationType") String strRelationType) throws ThingsboardException {
+    public List<EntityRelation> 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<EntityRelation> findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException {
+    public List<EntityRelation> 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<EntityRelation> findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType
-            , @RequestParam("relationType") String strRelationType) throws ThingsboardException {
+    public List<EntityRelation> 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/alarm/Alarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java
index 7bf7a08..09695e5 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<AlarmId> 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/Customer.java b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
index f8c1e30..ec535bf 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<CustomerId> 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 c4daf9d..3be3b79 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<DashboardId> 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/relation/EntityRelation.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java
index 39e7d54..8dab589 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 0000000..82798ab
--- /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/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 3a5f6bf..4501759 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<TenantId> 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 0543ef0..1b97e2e 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<UserId> implements HasName {
     }
 
     @Override
+    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
     public String getName() {
         return email;
     }
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 994fe80..1362e6b 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<AlarmEntity> 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<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, EntityType.ALARM, query.getPageLink());
+        ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink());
         return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<Alarm>>) input -> {
             List<ListenableFuture<Alarm>> 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 5b31a51..3981f64 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<EntityId> 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<EntityId> 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 967f4d1..dfad10b 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 0000000..1c0514e
--- /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<RelationTypeGroup> {
+
+    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 1b05866..9fc2382 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<List<EntityRelation>> findAllByFrom(EntityId from) {
-        BoundStatement stmt = getFindAllByFromStmt().bind().setUUID(0, from.getId()).setString(1, from.getEntityType().name());
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType) {
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findAllByTo(EntityId to) {
-        BoundStatement stmt = getFindAllByToStmt().bind().setUUID(0, to.getId()).setString(1, to.getEntityType().name());
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType) {
+    public ListenableFuture<List<EntityRelation>> 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<Boolean> checkRelation(EntityId from, EntityId to, String relationType) {
+    public ListenableFuture<Boolean> 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<Boolean> deleteRelation(EntityRelation relation) {
-        return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType());
+        return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
     }
 
     @Override
-    public ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType) {
+    public ListenableFuture<Boolean> 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<List<EntityRelation>> findRelations(EntityId from, String relationType, EntityType childType, TimePageLink pageLink) {
+    public ListenableFuture<List<EntityRelation>> 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 9b4f906..9559cd3 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> deleteEntityRelations(EntityId entity) {
         log.trace("Executing deleteEntityRelations [{}]", entity);
         validate(entity);
-        ListenableFuture<List<EntityRelation>> inboundRelations = relationDao.findAllByTo(entity);
-        ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<EntityRelation>, List<Boolean>>() {
+        List<ListenableFuture<List<EntityRelation>>> inboundRelationsList = new ArrayList<>();
+        for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
+            inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup));
+        }
+        Futures.allAsList(inboundRelationsList);
+        ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
+        ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<List<EntityRelation>>, List<Boolean>>() {
             @Override
-            public ListenableFuture<List<Boolean>> apply(List<EntityRelation> relations) throws Exception {
+            public ListenableFuture<List<Boolean>> apply(List<List<EntityRelation>> relations) throws Exception {
                 List<ListenableFuture<Boolean>> results = new ArrayList<>();
-                for (EntityRelation relation : relations) {
-                    results.add(relationDao.deleteRelation(relation));
+                for (List<EntityRelation> 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<List<EntityRelation>> findByFrom(EntityId from) {
-        log.trace("Executing findByFrom [{}]", from);
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelationInfo>> findInfoByFrom(EntityId from) {
-        log.trace("Executing findInfoByFrom [{}]", from);
+    public ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup) {
+        log.trace("Executing findInfoByFrom [{}][{}]", from, typeGroup);
         validate(from);
-        ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(from);
+        validateTypeGroup(typeGroup);
+        ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(from, typeGroup);
         ListenableFuture<List<EntityRelationInfo>> relationsInfo = Futures.transform(relations,
                 (AsyncFunction<List<EntityRelation>, List<EntityRelationInfo>>) relations1 -> {
             List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
@@ -143,26 +151,29 @@ public class BaseRelationService implements RelationService {
     }
 
     @Override
-    public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
-        log.trace("Executing findByFromAndType [{}][{}]", from, relationType);
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findByTo(EntityId to) {
-        log.trace("Executing findByTo [{}]", to);
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findByToAndType(EntityId to, String relationType) {
-        log.trace("Executing findByToAndType [{}][{}]", to, relationType);
+    public ListenableFuture<List<EntityRelation>> 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<List<EntityRelation>> findRelations(final EntityId rootId, final EntitySearchDirection direction) {
         ListenableFuture<List<EntityRelation>> 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 bec0320..3abadb8 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<List<EntityRelation>> findAllByFrom(EntityId from);
+    ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType);
+    ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to);
+    ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType);
+    ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
 
-    ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType);
+    ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
 
     ListenableFuture<Boolean> saveRelation(EntityRelation relation);
 
     ListenableFuture<Boolean> deleteRelation(EntityRelation relation);
 
-    ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType);
+    ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
 
     ListenableFuture<Boolean> deleteOutboundRelations(EntityId entity);
 
-    ListenableFuture<List<EntityRelation>> findRelations(EntityId from, String relationType, EntityType toType, TimePageLink pageLink);
+    ListenableFuture<List<EntityRelation>> 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 e89985e..868769f 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<Boolean> checkRelation(EntityId from, EntityId to, String relationType);
+    ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
 
     ListenableFuture<Boolean> saveRelation(EntityRelation relation);
 
     ListenableFuture<Boolean> deleteRelation(EntityRelation relation);
 
-    ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType);
+    ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
 
     ListenableFuture<Boolean> deleteEntityRelations(EntityId entity);
 
-    ListenableFuture<List<EntityRelation>> findByFrom(EntityId from);
+    ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from);
+    ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType);
+    ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findByTo(EntityId to);
+    ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup);
 
-    ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType);
+    ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
 
     ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query);
 
diff --git a/dao/src/main/resources/schema.cql b/dao/src/main/resources/schema.cql
index b72d2f6..71de677 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 3f5c55a..f7e47ce 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<EntityRelation> relations = relationService.findByFrom(parentA).get();
+        List<EntityRelation> 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<EntityRelation> relations = relationService.findByTo(childA).get();
+        List<EntityRelation> 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 376a88d..8a082fc 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<EntityRelation> relations = relationService.findByFrom(parentA).get();
+        List<EntityRelation> 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<EntityRelation> relations = relationService.findByTo(childA).get();
+        List<EntityRelation> 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());

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index fe95d9b..9e59137 100755
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
         <guava.version>18.0</guava.version>
         <commons-lang3.version>3.4</commons-lang3.version>
         <commons-validator.version>1.5.0</commons-validator.version>
-        <jackson.version>2.7.3</jackson.version>
+        <jackson.version>2.8.8.1</jackson.version>
         <json-schema-validator.version>2.2.6</json-schema-validator.version>
         <scala.version>2.11</scala.version>
         <akka.version>2.4.2</akka.version>
diff --git a/ui/src/app/entity/entity-select.directive.js b/ui/src/app/entity/entity-select.directive.js
index 8988aae..705c6b8 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 a354b1d..ce0a16b 100644
--- a/ui/src/app/entity/entity-select.tpl.html
+++ b/ui/src/app/entity/entity-select.tpl.html
@@ -19,7 +19,7 @@
     <tb-entity-type-select style="min-width: 100px;"
                            ng-model="model.entityType">
     </tb-entity-type-select>
-    <tb-entity-autocomplete flex
+    <tb-entity-autocomplete flex ng-if="model.entityType"
                             the-form="theForm"
                             ng-disabled="disabled"
                             tb-required="tbRequired"
diff --git a/ui/src/app/entity/entity-subtype-select.directive.js b/ui/src/app/entity/entity-subtype-select.directive.js
index 4a2d33e..36d9729 100644
--- a/ui/src/app/entity/entity-subtype-select.directive.js
+++ b/ui/src/app/entity/entity-subtype-select.directive.js
@@ -70,7 +70,7 @@ export default function EntitySubtypeSelect($compile, $templateCache, $translate
         };
 
         function loadSubTypes() {
-            scope.entitySubtypes.length = 0;
+            scope.entitySubtypes = [];
             var entitySubtypesPromise;
             if (scope.entityType == types.entityType.asset) {
                 entitySubtypesPromise = assetService.getAssetTypes();