Commit 009da885ad9486ffaa29325c7349f627d51fdf86

Authored by VoBa
Committed by GitHub
2 parents b0b6ee06 ae8d8f01

Merge pull request #1043 from ViktorBasanets/master

Entity View
@@ -24,6 +24,7 @@ DROP TABLE IF EXISTS thingsboard.entity_views; @@ -24,6 +24,7 @@ DROP TABLE IF EXISTS thingsboard.entity_views;
24 CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( 24 CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
25 id timeuuid, 25 id timeuuid,
26 entity_id timeuuid, 26 entity_id timeuuid,
  27 + entity_type text,
27 tenant_id timeuuid, 28 tenant_id timeuuid,
28 customer_id timeuuid, 29 customer_id timeuuid,
29 name text, 30 name text,
@@ -33,7 +34,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( @@ -33,7 +34,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
33 search_text text, 34 search_text text,
34 additional_info text, 35 additional_info text,
35 PRIMARY KEY (id, entity_id, tenant_id, customer_id) 36 PRIMARY KEY (id, entity_id, tenant_id, customer_id)
36 - ); 37 +);
37 38
38 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS 39 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS
39 SELECT * 40 SELECT *
@@ -26,17 +26,11 @@ import org.springframework.stereotype.Component; @@ -26,17 +26,11 @@ import org.springframework.stereotype.Component;
26 import org.springframework.web.context.request.async.DeferredResult; 26 import org.springframework.web.context.request.async.DeferredResult;
27 import org.thingsboard.server.common.data.Customer; 27 import org.thingsboard.server.common.data.Customer;
28 import org.thingsboard.server.common.data.Device; 28 import org.thingsboard.server.common.data.Device;
  29 +import org.thingsboard.server.common.data.EntityView;
29 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
30 import org.thingsboard.server.common.data.asset.Asset; 31 import org.thingsboard.server.common.data.asset.Asset;
31 import org.thingsboard.server.common.data.exception.ThingsboardException; 32 import org.thingsboard.server.common.data.exception.ThingsboardException;
32 -import org.thingsboard.server.common.data.id.AssetId;  
33 -import org.thingsboard.server.common.data.id.CustomerId;  
34 -import org.thingsboard.server.common.data.id.DeviceId;  
35 -import org.thingsboard.server.common.data.id.EntityId;  
36 -import org.thingsboard.server.common.data.id.EntityIdFactory;  
37 -import org.thingsboard.server.common.data.id.RuleChainId;  
38 -import org.thingsboard.server.common.data.id.RuleNodeId;  
39 -import org.thingsboard.server.common.data.id.TenantId; 33 +import org.thingsboard.server.common.data.id.*;
40 import org.thingsboard.server.common.data.rule.RuleChain; 34 import org.thingsboard.server.common.data.rule.RuleChain;
41 import org.thingsboard.server.common.data.rule.RuleNode; 35 import org.thingsboard.server.common.data.rule.RuleNode;
42 import org.thingsboard.server.controller.HttpValidationCallback; 36 import org.thingsboard.server.controller.HttpValidationCallback;
@@ -44,6 +38,7 @@ import org.thingsboard.server.dao.alarm.AlarmService; @@ -44,6 +38,7 @@ import org.thingsboard.server.dao.alarm.AlarmService;
44 import org.thingsboard.server.dao.asset.AssetService; 38 import org.thingsboard.server.dao.asset.AssetService;
45 import org.thingsboard.server.dao.customer.CustomerService; 39 import org.thingsboard.server.dao.customer.CustomerService;
46 import org.thingsboard.server.dao.device.DeviceService; 40 import org.thingsboard.server.dao.device.DeviceService;
  41 +import org.thingsboard.server.dao.entityview.EntityViewService;
47 import org.thingsboard.server.dao.rule.RuleChainService; 42 import org.thingsboard.server.dao.rule.RuleChainService;
48 import org.thingsboard.server.dao.tenant.TenantService; 43 import org.thingsboard.server.dao.tenant.TenantService;
49 import org.thingsboard.server.dao.user.UserService; 44 import org.thingsboard.server.dao.user.UserService;
@@ -66,6 +61,7 @@ public class AccessValidator { @@ -66,6 +61,7 @@ public class AccessValidator {
66 public static final String CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "Customer user is not allowed to perform this operation!"; 61 public static final String CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "Customer user is not allowed to perform this operation!";
67 public static final String SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "System administrator is not allowed to perform this operation!"; 62 public static final String SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "System administrator is not allowed to perform this operation!";
68 public static final String DEVICE_WITH_REQUESTED_ID_NOT_FOUND = "Device with requested id wasn't found!"; 63 public static final String DEVICE_WITH_REQUESTED_ID_NOT_FOUND = "Device with requested id wasn't found!";
  64 + public static final String ENTITY_VIEW_WITH_REQUESTED_ID_NOT_FOUND = "Entity-view with requested id wasn't found!";
69 65
70 @Autowired 66 @Autowired
71 protected TenantService tenantService; 67 protected TenantService tenantService;
@@ -88,6 +84,9 @@ public class AccessValidator { @@ -88,6 +84,9 @@ public class AccessValidator {
88 @Autowired 84 @Autowired
89 protected RuleChainService ruleChainService; 85 protected RuleChainService ruleChainService;
90 86
  87 + @Autowired
  88 + protected EntityViewService entityViewService;
  89 +
91 private ExecutorService executor; 90 private ExecutorService executor;
92 91
93 @PostConstruct 92 @PostConstruct
@@ -158,6 +157,9 @@ public class AccessValidator { @@ -158,6 +157,9 @@ public class AccessValidator {
158 case TENANT: 157 case TENANT:
159 validateTenant(currentUser, entityId, callback); 158 validateTenant(currentUser, entityId, callback);
160 return; 159 return;
  160 + case ENTITY_VIEW:
  161 + validateEntityView(currentUser, entityId, callback);
  162 + return;
161 default: 163 default:
162 //TODO: add support of other entities 164 //TODO: add support of other entities
163 throw new IllegalStateException("Not Implemented!"); 165 throw new IllegalStateException("Not Implemented!");
@@ -293,6 +295,27 @@ public class AccessValidator { @@ -293,6 +295,27 @@ public class AccessValidator {
293 } 295 }
294 } 296 }
295 297
  298 + private void validateEntityView(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
  299 + if (currentUser.isSystemAdmin()) {
  300 + callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
  301 + } else {
  302 + ListenableFuture<EntityView> entityViewFuture = entityViewService.findEntityViewByIdAsync(new EntityViewId(entityId.getId()));
  303 + Futures.addCallback(entityViewFuture, getCallback(callback, entityView -> {
  304 + if (entityView == null) {
  305 + return ValidationResult.entityNotFound(ENTITY_VIEW_WITH_REQUESTED_ID_NOT_FOUND);
  306 + } else {
  307 + if (!entityView.getTenantId().equals(currentUser.getTenantId())) {
  308 + return ValidationResult.accessDenied("Entity-view doesn't belong to the current Tenant!");
  309 + } else if (currentUser.isCustomerUser() && !entityView.getCustomerId().equals(currentUser.getCustomerId())) {
  310 + return ValidationResult.accessDenied("Entity-view doesn't belong to the current Customer!");
  311 + } else {
  312 + return ValidationResult.ok(entityView);
  313 + }
  314 + }
  315 + }), executor);
  316 + }
  317 + }
  318 +
296 private <T, V> FutureCallback<T> getCallback(FutureCallback<ValidationResult> callback, Function<T, ValidationResult<V>> transformer) { 319 private <T, V> FutureCallback<T> getCallback(FutureCallback<ValidationResult> callback, Function<T, ValidationResult<V>> transformer) {
297 return new FutureCallback<T>() { 320 return new FutureCallback<T>() {
298 @Override 321 @Override
@@ -24,7 +24,7 @@ import java.util.Arrays; @@ -24,7 +24,7 @@ import java.util.Arrays;
24 24
25 @RunWith(ClasspathSuite.class) 25 @RunWith(ClasspathSuite.class)
26 @ClasspathSuite.ClassnameFilters({ 26 @ClasspathSuite.ClassnameFilters({
27 - "org.thingsboard.server.controller.sql.EntityViewControllerSqlTest", 27 + "org.thingsboard.server.controller.sql.*Test",
28 }) 28 })
29 public class ControllerSqlTestSuite { 29 public class ControllerSqlTestSuite {
30 30
@@ -16,9 +16,11 @@ @@ -16,9 +16,11 @@
16 package org.thingsboard.server.controller.nosql; 16 package org.thingsboard.server.controller.nosql;
17 17
18 import org.thingsboard.server.controller.BaseEntityViewControllerTest; 18 import org.thingsboard.server.controller.BaseEntityViewControllerTest;
  19 +import org.thingsboard.server.dao.service.DaoNoSqlTest;
19 20
20 /** 21 /**
21 * Created by Victor Basanets on 8/27/2017. 22 * Created by Victor Basanets on 8/27/2017.
22 */ 23 */
  24 +@DaoNoSqlTest
23 public class EntityViewControllerNoSqlTest extends BaseEntityViewControllerTest { 25 public class EntityViewControllerNoSqlTest extends BaseEntityViewControllerTest {
24 } 26 }
@@ -39,8 +39,8 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> @@ -39,8 +39,8 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId>
39 private CustomerId customerId; 39 private CustomerId customerId;
40 private String name; 40 private String name;
41 private TelemetryEntityView keys; 41 private TelemetryEntityView keys;
42 - private Long tsBegin;  
43 - private Long tsEnd; 42 + private long startTs;
  43 + private long endTs;
44 44
45 public EntityView() { 45 public EntityView() {
46 super(); 46 super();
@@ -44,9 +44,4 @@ public class AttributesEntityView { @@ -44,9 +44,4 @@ public class AttributesEntityView {
44 public AttributesEntityView(AttributesEntityView obj) { 44 public AttributesEntityView(AttributesEntityView obj) {
45 this(obj.getCs(), obj.getSs(), obj.getSh()); 45 this(obj.getCs(), obj.getSs(), obj.getSh());
46 } 46 }
47 -  
48 - @Override  
49 - public String toString() {  
50 - return "{cs=" + cs + ", ss=" + ss + ", sh=" + sh + '}';  
51 - }  
52 } 47 }
@@ -40,9 +40,4 @@ public class TelemetryEntityView { @@ -40,9 +40,4 @@ public class TelemetryEntityView {
40 public TelemetryEntityView(TelemetryEntityView obj) { 40 public TelemetryEntityView(TelemetryEntityView obj) {
41 this(obj.getTimeseries(), obj.getAttributes()); 41 this(obj.getTimeseries(), obj.getAttributes());
42 } 42 }
43 -  
44 - @Override  
45 - public String toString() {  
46 - return "{timeseries=" + timeseries + ", attributes=" + attributes + '}';  
47 - }  
48 } 43 }
  1 +/**
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.entityview;
  17 +
  18 +import com.datastax.driver.core.Statement;
  19 +import com.datastax.driver.core.querybuilder.Select;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.stereotype.Component;
  22 +import org.thingsboard.server.common.data.EntitySubtype;
  23 +import org.thingsboard.server.common.data.EntityType;
  24 +import org.thingsboard.server.common.data.EntityView;
  25 +import org.thingsboard.server.common.data.page.TextPageLink;
  26 +import org.thingsboard.server.dao.DaoUtil;
  27 +import org.thingsboard.server.dao.model.EntitySubtypeEntity;
  28 +import org.thingsboard.server.dao.model.nosql.EntityViewEntity;
  29 +import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
  30 +import org.thingsboard.server.dao.util.NoSqlDao;
  31 +
  32 +import java.util.*;
  33 +
  34 +import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
  35 +import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
  36 +import static org.thingsboard.server.dao.model.ModelConstants.*;
  37 +
  38 +/**
  39 + * Created by Victor Basanets on 9/06/2017.
  40 + */
  41 +@Component
  42 +@Slf4j
  43 +@NoSqlDao
  44 +public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<EntityViewEntity, EntityView> implements EntityViewDao {
  45 +
  46 + @Override
  47 + protected Class<EntityViewEntity> getColumnFamilyClass() {
  48 + return EntityViewEntity.class;
  49 + }
  50 +
  51 + @Override
  52 + protected String getColumnFamilyName() {
  53 + return ENTITY_VIEW_TABLE_FAMILY_NAME;
  54 + }
  55 +
  56 + @Override
  57 + public EntityView save(EntityView domain) {
  58 + EntityView savedEntityView = super.save(domain);
  59 + EntitySubtype entitySubtype = new EntitySubtype(savedEntityView.getTenantId(), EntityType.ENTITY_VIEW,
  60 + savedEntityView.getId().getEntityType().toString());
  61 + EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
  62 + Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
  63 + executeWrite(saveStatement);
  64 + return savedEntityView;
  65 + }
  66 +
  67 + @Override
  68 + public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) {
  69 + log.debug("Try to find entity-views by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
  70 + List<EntityViewEntity> entityViewEntities =
  71 + findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  72 + Collections.singletonList(eq(ENTITY_VIEW_TENANT_ID_PROPERTY, tenantId)), pageLink);
  73 +
  74 + log.trace("Found entity-views [{}] by tenantId [{}] and pageLink [{}]", entityViewEntities, tenantId, pageLink);
  75 + return DaoUtil.convertDataList(entityViewEntities);
  76 + }
  77 +
  78 + @Override
  79 + public Optional<EntityView> findEntityViewByTenantIdAndName(UUID tenantId, String entityViewName) {
  80 + return Optional.ofNullable(DaoUtil.getData(
  81 + findOneByStatement(select().from(ENTITY_VIEW_TENANT_AND_NAME_VIEW_NAME).where()
  82 + .and(eq(ENTITY_VIEW_TENANT_ID_PROPERTY, tenantId))
  83 + .and(eq(ENTITY_VIEW_NAME_PROPERTY, entityViewName))))
  84 + );
  85 + }
  86 +
  87 + @Override
  88 + public List<EntityView> findEntityViewByTenantIdAndEntityId(UUID tenantId, UUID entityId, TextPageLink pageLink) {
  89 + log.debug("Try to find entity-views by tenantId [{}], entityId[{}] and pageLink [{}]", tenantId, entityId, pageLink);
  90 + List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  91 + Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, entityId),
  92 + eq(DEVICE_TENANT_ID_PROPERTY, tenantId)),
  93 + pageLink);
  94 +
  95 + log.trace("Found entity-views [{}] by tenantId [{}], entityId [{}] and pageLink [{}]", entityViewEntities, tenantId, entityId, pageLink);
  96 + return DaoUtil.convertDataList(entityViewEntities);
  97 + }
  98 +
  99 + @Override
  100 + public List<EntityView> findEntityViewsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
  101 + return null;
  102 + }
  103 +
  104 + @Override
  105 + public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(UUID tenantId, UUID customerId, UUID entityId, TextPageLink pageLink) {
  106 + return null;
  107 + }
  108 +}
@@ -30,6 +30,14 @@ import java.util.UUID; @@ -30,6 +30,14 @@ import java.util.UUID;
30 public interface EntityViewDao extends Dao<EntityView> { 30 public interface EntityViewDao extends Dao<EntityView> {
31 31
32 /** 32 /**
  33 + * Save or update device object
  34 + *
  35 + * @param entityView the entity-view object
  36 + * @return saved entity-view object
  37 + */
  38 + EntityView save(EntityView entityView);
  39 +
  40 + /**
33 * Find entity views by tenantId and page link. 41 * Find entity views by tenantId and page link.
34 * 42 *
35 * @param tenantId the tenantId 43 * @param tenantId the tenantId
@@ -15,12 +15,10 @@ @@ -15,12 +15,10 @@
15 */ 15 */
16 package org.thingsboard.server.dao.entityview; 16 package org.thingsboard.server.dao.entityview;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 import org.thingsboard.server.common.data.EntityType; 19 import org.thingsboard.server.common.data.EntityType;
19 import org.thingsboard.server.common.data.EntityView; 20 import org.thingsboard.server.common.data.EntityView;
20 -import org.thingsboard.server.common.data.id.CustomerId;  
21 -import org.thingsboard.server.common.data.id.EntityId;  
22 -import org.thingsboard.server.common.data.id.EntityViewId;  
23 -import org.thingsboard.server.common.data.id.TenantId; 21 +import org.thingsboard.server.common.data.id.*;
24 import org.thingsboard.server.common.data.page.TextPageData; 22 import org.thingsboard.server.common.data.page.TextPageData;
25 import org.thingsboard.server.common.data.page.TextPageLink; 23 import org.thingsboard.server.common.data.page.TextPageLink;
26 24
@@ -57,4 +55,6 @@ public interface EntityViewService { @@ -57,4 +55,6 @@ public interface EntityViewService {
57 TextPageLink pageLink); 55 TextPageLink pageLink);
58 56
59 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); 57 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
  58 +
  59 + ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
60 } 60 }
@@ -15,11 +15,14 @@ @@ -15,11 +15,14 @@
15 */ 15 */
16 package org.thingsboard.server.dao.entityview; 16 package org.thingsboard.server.dao.entityview;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
19 import org.apache.commons.lang3.StringUtils; 20 import org.apache.commons.lang3.StringUtils;
20 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.cache.Cache; 22 import org.springframework.cache.Cache;
22 import org.springframework.cache.CacheManager; 23 import org.springframework.cache.CacheManager;
  24 +import org.springframework.cache.annotation.CacheEvict;
  25 +import org.springframework.cache.annotation.Cacheable;
23 import org.springframework.stereotype.Service; 26 import org.springframework.stereotype.Service;
24 import org.thingsboard.server.common.data.Customer; 27 import org.thingsboard.server.common.data.Customer;
25 import org.thingsboard.server.common.data.EntityView; 28 import org.thingsboard.server.common.data.EntityView;
@@ -40,6 +43,8 @@ import org.thingsboard.server.dao.tenant.TenantDao; @@ -40,6 +43,8 @@ import org.thingsboard.server.dao.tenant.TenantDao;
40 import java.util.ArrayList; 43 import java.util.ArrayList;
41 import java.util.List; 44 import java.util.List;
42 45
  46 +import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE;
  47 +import static org.thingsboard.server.common.data.CacheConstants.ENTITY_VIEW_CACHE;
43 import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; 48 import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
44 import static org.thingsboard.server.dao.service.Validator.validateId; 49 import static org.thingsboard.server.dao.service.Validator.validateId;
45 import static org.thingsboard.server.dao.service.Validator.validatePageLink; 50 import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@@ -67,6 +72,10 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -67,6 +72,10 @@ public class EntityViewServiceImpl extends AbstractEntityService
67 @Autowired 72 @Autowired
68 private CustomerDao customerDao; 73 private CustomerDao customerDao;
69 74
  75 + @Autowired
  76 + private CacheManager cacheManager;
  77 +
  78 + @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
70 @Override 79 @Override
71 public EntityView findEntityViewById(EntityViewId entityViewId) { 80 public EntityView findEntityViewById(EntityViewId entityViewId) {
72 log.trace("Executing findEntityViewById [{}]", entityViewId); 81 log.trace("Executing findEntityViewById [{}]", entityViewId);
@@ -82,6 +91,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -82,6 +91,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
82 .orElse(null); 91 .orElse(null);
83 } 92 }
84 93
  94 + @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.id}")
85 @Override 95 @Override
86 public EntityView saveEntityView(EntityView entityView) { 96 public EntityView saveEntityView(EntityView entityView) {
87 log.trace("Executing save entity view [{}]", entityView); 97 log.trace("Executing save entity view [{}]", entityView);
@@ -106,12 +116,14 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -106,12 +116,14 @@ public class EntityViewServiceImpl extends AbstractEntityService
106 @Override 116 @Override
107 public void deleteEntityView(EntityViewId entityViewId) { 117 public void deleteEntityView(EntityViewId entityViewId) {
108 log.trace("Executing deleteEntityView [{}]", entityViewId); 118 log.trace("Executing deleteEntityView [{}]", entityViewId);
  119 + Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE);
109 validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); 120 validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
110 deleteEntityRelations(entityViewId); 121 deleteEntityRelations(entityViewId);
111 EntityView entityView = entityViewDao.findById(entityViewId.getId()); 122 EntityView entityView = entityViewDao.findById(entityViewId.getId());
112 List<Object> list = new ArrayList<>(); 123 List<Object> list = new ArrayList<>();
113 list.add(entityView.getTenantId()); 124 list.add(entityView.getTenantId());
114 list.add(entityView.getName()); 125 list.add(entityView.getName());
  126 + cache.evict(list);
115 entityViewDao.removeById(entityViewId.getId()); 127 entityViewDao.removeById(entityViewId.getId());
116 } 128 }
117 129
@@ -124,6 +136,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -124,6 +136,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
124 return new TextPageData<>(entityViews, pageLink); 136 return new TextPageData<>(entityViews, pageLink);
125 } 137 }
126 138
  139 + @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #entityId, #pageLink}")
127 @Override 140 @Override
128 public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, 141 public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId,
129 TextPageLink pageLink) { 142 TextPageLink pageLink) {
@@ -163,6 +176,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -163,6 +176,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
163 return new TextPageData<>(entityViews, pageLink); 176 return new TextPageData<>(entityViews, pageLink);
164 } 177 }
165 178
  179 + @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #customerId, #entityId, #pageLink}")
166 @Override 180 @Override
167 public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId, 181 public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId,
168 CustomerId customerId, 182 CustomerId customerId,
@@ -190,6 +204,13 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -190,6 +204,13 @@ public class EntityViewServiceImpl extends AbstractEntityService
190 new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId); 204 new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId);
191 } 205 }
192 206
  207 + @Override
  208 + public ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
  209 + log.trace("Executing findEntityViewById [{}]", entityViewId);
  210 + validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
  211 + return entityViewDao.findByIdAsync(entityViewId.getId());
  212 + }
  213 +
193 private DataValidator<EntityView> entityViewValidator = 214 private DataValidator<EntityView> entityViewValidator =
194 new DataValidator<EntityView>() { 215 new DataValidator<EntityView>() {
195 216
@@ -136,7 +136,6 @@ public class ModelConstants { @@ -136,7 +136,6 @@ public class ModelConstants {
136 public static final String DEVICE_NAME_PROPERTY = "name"; 136 public static final String DEVICE_NAME_PROPERTY = "name";
137 public static final String DEVICE_TYPE_PROPERTY = "type"; 137 public static final String DEVICE_TYPE_PROPERTY = "type";
138 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 138 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
139 -  
140 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; 139 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text";
141 public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; 140 public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text";
142 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; 141 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text";
@@ -152,11 +151,12 @@ public class ModelConstants { @@ -152,11 +151,12 @@ public class ModelConstants {
152 public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; 151 public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
153 public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; 152 public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
154 public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY; 153 public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY;
155 - public static final String ENTITY_VIEW_TYPE_PROPERTY = "type_entity"; 154 + public static final String ENTITY_VIEW_TENANT_AND_NAME_VIEW_NAME = "entity_view_by_tenant_and_name";
156 public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys"; 155 public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys";
157 public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin"; 156 public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin";
158 public static final String ENTITY_VIEW_TS_END_PROPERTY = "ts_end"; 157 public static final String ENTITY_VIEW_TS_END_PROPERTY = "ts_end";
159 public static final String ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 158 public static final String ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
  159 + public static final String ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "entity_view_by_tenant_and_search_text";
160 160
161 /** 161 /**
162 * Cassandra audit log constants. 162 * Cassandra audit log constants.
@@ -19,24 +19,26 @@ import com.datastax.driver.core.utils.UUIDs; @@ -19,24 +19,26 @@ import com.datastax.driver.core.utils.UUIDs;
19 import com.datastax.driver.mapping.annotations.PartitionKey; 19 import com.datastax.driver.mapping.annotations.PartitionKey;
20 import com.datastax.driver.mapping.annotations.Table; 20 import com.datastax.driver.mapping.annotations.Table;
21 import com.fasterxml.jackson.databind.JsonNode; 21 import com.fasterxml.jackson.databind.JsonNode;
  22 +import com.fasterxml.jackson.databind.ObjectMapper;
22 import lombok.Data; 23 import lombok.Data;
23 import lombok.EqualsAndHashCode; 24 import lombok.EqualsAndHashCode;
24 import lombok.ToString; 25 import lombok.ToString;
25 import org.hibernate.annotations.Type; 26 import org.hibernate.annotations.Type;
  27 +import org.thingsboard.server.common.data.EntityType;
26 import org.thingsboard.server.common.data.EntityView; 28 import org.thingsboard.server.common.data.EntityView;
27 -import org.thingsboard.server.common.data.id.CustomerId;  
28 -import org.thingsboard.server.common.data.id.DeviceId;  
29 -import org.thingsboard.server.common.data.id.EntityViewId;  
30 -import org.thingsboard.server.common.data.id.TenantId; 29 +import org.thingsboard.server.common.data.id.*;
31 import org.thingsboard.server.common.data.objects.TelemetryEntityView; 30 import org.thingsboard.server.common.data.objects.TelemetryEntityView;
32 import org.thingsboard.server.dao.model.ModelConstants; 31 import org.thingsboard.server.dao.model.ModelConstants;
33 import org.thingsboard.server.dao.model.SearchTextEntity; 32 import org.thingsboard.server.dao.model.SearchTextEntity;
34 33
35 import javax.persistence.Column; 34 import javax.persistence.Column;
  35 +import javax.persistence.EnumType;
  36 +import javax.persistence.Enumerated;
36 37
37 import java.io.IOException; 38 import java.io.IOException;
38 import java.util.UUID; 39 import java.util.UUID;
39 40
  41 +import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_TYPE_PROPERTY;
40 import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME; 42 import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME;
41 import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; 43 import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
42 44
@@ -57,6 +59,10 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -57,6 +59,10 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
57 @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY) 59 @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY)
58 private UUID entityId; 60 private UUID entityId;
59 61
  62 + @Enumerated(EnumType.STRING)
  63 + @Column(name = ENTITY_TYPE_PROPERTY)
  64 + private EntityType entityType;
  65 +
60 @PartitionKey(value = 2) 66 @PartitionKey(value = 2)
61 @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY) 67 @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY)
62 private UUID tenantId; 68 private UUID tenantId;
@@ -68,9 +74,8 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -68,9 +74,8 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
68 @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY) 74 @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY)
69 private String name; 75 private String name;
70 76
71 - @Type(type = "json")  
72 @Column(name = ModelConstants.ENTITY_VIEW_KEYS_PROPERTY) 77 @Column(name = ModelConstants.ENTITY_VIEW_KEYS_PROPERTY)
73 - private JsonNode keys; 78 + private String keys;
74 79
75 @Column(name = ModelConstants.ENTITY_VIEW_TS_BEGIN_PROPERTY) 80 @Column(name = ModelConstants.ENTITY_VIEW_TS_BEGIN_PROPERTY)
76 private String tsBegin; 81 private String tsBegin;
@@ -85,6 +90,8 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -85,6 +90,8 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
85 @Column(name = ModelConstants.ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY) 90 @Column(name = ModelConstants.ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY)
86 private JsonNode additionalInfo; 91 private JsonNode additionalInfo;
87 92
  93 + private static final ObjectMapper mapper = new ObjectMapper();
  94 +
88 public EntityViewEntity() { 95 public EntityViewEntity() {
89 super(); 96 super();
90 } 97 }
@@ -95,6 +102,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -95,6 +102,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
95 } 102 }
96 if (entityView.getEntityId() != null) { 103 if (entityView.getEntityId() != null) {
97 this.entityId = entityView.getEntityId().getId(); 104 this.entityId = entityView.getEntityId().getId();
  105 + this.entityType = entityView.getEntityId().getEntityType();
98 } 106 }
99 if (entityView.getTenantId() != null) { 107 if (entityView.getTenantId() != null) {
100 this.tenantId = entityView.getTenantId().getId(); 108 this.tenantId = entityView.getTenantId().getId();
@@ -103,13 +111,13 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -103,13 +111,13 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
103 this.customerId = entityView.getCustomerId().getId(); 111 this.customerId = entityView.getCustomerId().getId();
104 } 112 }
105 this.name = entityView.getName(); 113 this.name = entityView.getName();
106 -// try {  
107 -// this.keys = entityView.getKeys();  
108 -// } catch (IOException e) {  
109 -// e.printStackTrace();  
110 -// }  
111 - this.tsBegin = entityView.getTsBegin() != null ? String.valueOf(entityView.getTsBegin()) : "0";  
112 - this.tsEnd = entityView.getTsEnd() != null ? String.valueOf(entityView.getTsEnd()) : "0"; 114 + try {
  115 + this.keys = mapper.writeValueAsString(entityView.getKeys());
  116 + } catch (IOException e) {
  117 + e.printStackTrace();
  118 + }
  119 + this.tsBegin = entityView.getStartTs() != 0L ? String.valueOf(entityView.getStartTs()) : "0";
  120 + this.tsEnd = entityView.getEndTs() != 0L ? String.valueOf(entityView.getEndTs()) : "0";
113 this.searchText = entityView.getSearchText(); 121 this.searchText = entityView.getSearchText();
114 this.additionalInfo = entityView.getAdditionalInfo(); 122 this.additionalInfo = entityView.getAdditionalInfo();
115 } 123 }
@@ -124,7 +132,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -124,7 +132,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
124 EntityView entityView = new EntityView(new EntityViewId(id)); 132 EntityView entityView = new EntityView(new EntityViewId(id));
125 entityView.setCreatedTime(UUIDs.unixTimestamp(id)); 133 entityView.setCreatedTime(UUIDs.unixTimestamp(id));
126 if (entityId != null) { 134 if (entityId != null) {
127 - entityView.setEntityId(new DeviceId(entityId)); 135 + entityView.setEntityId(EntityIdFactory.getByTypeAndId(entityType.name(), entityId.toString()));
128 } 136 }
129 if (tenantId != null) { 137 if (tenantId != null) {
130 entityView.setTenantId(new TenantId(tenantId)); 138 entityView.setTenantId(new TenantId(tenantId));
@@ -133,13 +141,13 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -133,13 +141,13 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
133 entityView.setCustomerId(new CustomerId(customerId)); 141 entityView.setCustomerId(new CustomerId(customerId));
134 } 142 }
135 entityView.setName(name); 143 entityView.setName(name);
136 -// try {  
137 -// entityView.setKeys((TelemetryEntityView) entityView.getKeys().toObject(keys));  
138 -// } catch (IOException e) {  
139 -// e.printStackTrace();  
140 -// }  
141 - entityView.setTsBegin(Long.parseLong(tsBegin));  
142 - entityView.setTsEnd(Long.parseLong(tsEnd)); 144 + try {
  145 + entityView.setKeys(mapper.readValue(keys, TelemetryEntityView.class));
  146 + } catch (IOException e) {
  147 + e.printStackTrace();
  148 + }
  149 + entityView.setStartTs(Long.parseLong(tsBegin));
  150 + entityView.setEndTs(Long.parseLong(tsEnd));
143 entityView.setAdditionalInfo(additionalInfo); 151 entityView.setAdditionalInfo(additionalInfo);
144 return entityView; 152 return entityView;
145 } 153 }
@@ -34,7 +34,6 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; @@ -34,7 +34,6 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
34 import javax.persistence.*; 34 import javax.persistence.*;
35 import java.io.IOException; 35 import java.io.IOException;
36 36
37 -import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_ENTITY_TYPE_PROPERTY;  
38 import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_TYPE_PROPERTY; 37 import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_TYPE_PROPERTY;
39 38
40 /** 39 /**
@@ -106,8 +105,8 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc @@ -106,8 +105,8 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc
106 } catch (IOException e) { 105 } catch (IOException e) {
107 e.printStackTrace(); 106 e.printStackTrace();
108 } 107 }
109 - this.tsBegin = entityView.getTsBegin() != null ? String.valueOf(entityView.getTsBegin()) : "0";  
110 - this.tsEnd = entityView.getTsEnd() != null ? String.valueOf(entityView.getTsEnd()) : "0"; 108 + this.tsBegin = entityView.getStartTs() != 0L ? String.valueOf(entityView.getStartTs()) : "0";
  109 + this.tsEnd = entityView.getEndTs() != 0L ? String.valueOf(entityView.getEndTs()) : "0";
111 this.searchText = entityView.getSearchText(); 110 this.searchText = entityView.getSearchText();
112 this.additionalInfo = entityView.getAdditionalInfo(); 111 this.additionalInfo = entityView.getAdditionalInfo();
113 } 112 }
@@ -142,8 +141,8 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc @@ -142,8 +141,8 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc
142 } catch (IOException e) { 141 } catch (IOException e) {
143 e.printStackTrace(); 142 e.printStackTrace();
144 } 143 }
145 - entityView.setTsBegin(Long.parseLong(tsBegin));  
146 - entityView.setTsEnd(Long.parseLong(tsEnd)); 144 + entityView.setStartTs(Long.parseLong(tsBegin));
  145 + entityView.setEndTs(Long.parseLong(tsEnd));
147 entityView.setAdditionalInfo(additionalInfo); 146 entityView.setAdditionalInfo(additionalInfo);
148 return entityView; 147 return entityView;
149 } 148 }
@@ -21,12 +21,18 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -21,12 +21,18 @@ import com.google.common.util.concurrent.ListenableFuture;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
  24 +import org.thingsboard.server.common.data.EntityType;
  25 +import org.thingsboard.server.common.data.EntityView;
24 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
  27 +import org.thingsboard.server.common.data.id.EntityViewId;
  28 +import org.thingsboard.server.common.data.kv.BaseTsKvQuery;
25 import org.thingsboard.server.common.data.kv.TsKvEntry; 29 import org.thingsboard.server.common.data.kv.TsKvEntry;
26 import org.thingsboard.server.common.data.kv.TsKvQuery; 30 import org.thingsboard.server.common.data.kv.TsKvQuery;
  31 +import org.thingsboard.server.dao.entityview.EntityViewService;
27 import org.thingsboard.server.dao.exception.IncorrectParameterException; 32 import org.thingsboard.server.dao.exception.IncorrectParameterException;
28 import org.thingsboard.server.dao.service.Validator; 33 import org.thingsboard.server.dao.service.Validator;
29 34
  35 +import java.util.ArrayList;
30 import java.util.Collection; 36 import java.util.Collection;
31 import java.util.List; 37 import java.util.List;
32 38
@@ -44,10 +50,17 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -44,10 +50,17 @@ public class BaseTimeseriesService implements TimeseriesService {
44 @Autowired 50 @Autowired
45 private TimeseriesDao timeseriesDao; 51 private TimeseriesDao timeseriesDao;
46 52
  53 + @Autowired
  54 + private EntityViewService entityViewService;
  55 +
47 @Override 56 @Override
48 public ListenableFuture<List<TsKvEntry>> findAll(EntityId entityId, List<TsKvQuery> queries) { 57 public ListenableFuture<List<TsKvEntry>> findAll(EntityId entityId, List<TsKvQuery> queries) {
49 validate(entityId); 58 validate(entityId);
50 queries.forEach(query -> validate(query)); 59 queries.forEach(query -> validate(query));
  60 + if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
  61 + EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
  62 + return timeseriesDao.findAllAsync(entityView.getEntityId(), updateQueriesForEntityView(entityView, queries));
  63 + }
51 return timeseriesDao.findAllAsync(entityId, queries); 64 return timeseriesDao.findAllAsync(entityId, queries);
52 } 65 }
53 66
@@ -56,7 +69,13 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -56,7 +69,13 @@ public class BaseTimeseriesService implements TimeseriesService {
56 validate(entityId); 69 validate(entityId);
57 List<ListenableFuture<TsKvEntry>> futures = Lists.newArrayListWithExpectedSize(keys.size()); 70 List<ListenableFuture<TsKvEntry>> futures = Lists.newArrayListWithExpectedSize(keys.size());
58 keys.forEach(key -> Validator.validateString(key, "Incorrect key " + key)); 71 keys.forEach(key -> Validator.validateString(key, "Incorrect key " + key));
59 - keys.forEach(key -> futures.add(timeseriesDao.findLatest(entityId, key))); 72 + if (false/*entityId.getEntityType().equals(EntityType.ENTITY_VIEW)*/) {
  73 + EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
  74 + Collection<String> newKeys = chooseKeysForEntityView(entityView, keys);
  75 + newKeys.forEach(newKey -> futures.add(timeseriesDao.findLatest(entityView.getEntityId(), newKey)));
  76 + } else {
  77 + keys.forEach(key -> futures.add(timeseriesDao.findLatest(entityId, key)));
  78 + }
60 return Futures.allAsList(futures); 79 return Futures.allAsList(futures);
61 } 80 }
62 81
@@ -69,6 +88,11 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -69,6 +88,11 @@ public class BaseTimeseriesService implements TimeseriesService {
69 @Override 88 @Override
70 public ListenableFuture<List<Void>> save(EntityId entityId, TsKvEntry tsKvEntry) { 89 public ListenableFuture<List<Void>> save(EntityId entityId, TsKvEntry tsKvEntry) {
71 validate(entityId); 90 validate(entityId);
  91 + try {
  92 + checkForNonEntityView(entityId);
  93 + } catch (Exception e) {
  94 + e.printStackTrace();
  95 + }
72 if (tsKvEntry == null) { 96 if (tsKvEntry == null) {
73 throw new IncorrectParameterException("Key value entry can't be null"); 97 throw new IncorrectParameterException("Key value entry can't be null");
74 } 98 }
@@ -79,6 +103,11 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -79,6 +103,11 @@ public class BaseTimeseriesService implements TimeseriesService {
79 103
80 @Override 104 @Override
81 public ListenableFuture<List<Void>> save(EntityId entityId, List<TsKvEntry> tsKvEntries, long ttl) { 105 public ListenableFuture<List<Void>> save(EntityId entityId, List<TsKvEntry> tsKvEntries, long ttl) {
  106 + try {
  107 + checkForNonEntityView(entityId);
  108 + } catch (Exception e) {
  109 + e.printStackTrace();
  110 + }
82 List<ListenableFuture<Void>> futures = Lists.newArrayListWithExpectedSize(tsKvEntries.size() * INSERTS_PER_ENTRY); 111 List<ListenableFuture<Void>> futures = Lists.newArrayListWithExpectedSize(tsKvEntries.size() * INSERTS_PER_ENTRY);
83 for (TsKvEntry tsKvEntry : tsKvEntries) { 112 for (TsKvEntry tsKvEntry : tsKvEntries) {
84 if (tsKvEntry == null) { 113 if (tsKvEntry == null) {
@@ -90,11 +119,47 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -90,11 +119,47 @@ public class BaseTimeseriesService implements TimeseriesService {
90 } 119 }
91 120
92 private void saveAndRegisterFutures(List<ListenableFuture<Void>> futures, EntityId entityId, TsKvEntry tsKvEntry, long ttl) { 121 private void saveAndRegisterFutures(List<ListenableFuture<Void>> futures, EntityId entityId, TsKvEntry tsKvEntry, long ttl) {
  122 + try {
  123 + checkForNonEntityView(entityId);
  124 + } catch (Exception e) {
  125 + e.printStackTrace();
  126 + }
93 futures.add(timeseriesDao.savePartition(entityId, tsKvEntry.getTs(), tsKvEntry.getKey(), ttl)); 127 futures.add(timeseriesDao.savePartition(entityId, tsKvEntry.getTs(), tsKvEntry.getKey(), ttl));
94 futures.add(timeseriesDao.saveLatest(entityId, tsKvEntry)); 128 futures.add(timeseriesDao.saveLatest(entityId, tsKvEntry));
95 futures.add(timeseriesDao.save(entityId, tsKvEntry, ttl)); 129 futures.add(timeseriesDao.save(entityId, tsKvEntry, ttl));
96 } 130 }
97 131
  132 + private List<TsKvQuery> updateQueriesForEntityView(EntityView entityView, List<TsKvQuery> queries) {
  133 + List<TsKvQuery> newQueries = new ArrayList<>();
  134 + entityView.getKeys().getTimeseries()
  135 + .forEach(viewKey -> queries
  136 + .forEach(query -> {
  137 + if (query.getKey().equals(viewKey)) {
  138 + if (entityView.getStartTs() == 0 && entityView.getEndTs() == 0) {
  139 + newQueries.add(updateQuery(query.getStartTs(), query.getEndTs(), viewKey, query));
  140 + } else if (entityView.getStartTs() == 0 && entityView.getEndTs() != 0) {
  141 + newQueries.add(updateQuery(query.getStartTs(), entityView.getEndTs(), viewKey, query));
  142 + } else if (entityView.getStartTs() != 0 && entityView.getEndTs() == 0) {
  143 + newQueries.add(updateQuery(entityView.getStartTs(), query.getEndTs(), viewKey, query));
  144 + } else {
  145 + newQueries.add(updateQuery(entityView.getStartTs(), entityView.getEndTs(), viewKey, query));
  146 + }
  147 + }}));
  148 + return newQueries;
  149 + }
  150 +
  151 + @Deprecated /*Will be a modified*/
  152 + private Collection<String> chooseKeysForEntityView(EntityView entityView, Collection<String> keys) {
  153 + Collection<String> newKeys = new ArrayList<>();
  154 + entityView.getKeys().getTimeseries()
  155 + .forEach(viewKey -> keys
  156 + .forEach(key -> {
  157 + if (key.equals(viewKey)) {
  158 + newKeys.add(key);
  159 + }}));
  160 + return newKeys;
  161 + }
  162 +
98 private static void validate(EntityId entityId) { 163 private static void validate(EntityId entityId) {
99 Validator.validateEntityId(entityId, "Incorrect entityId " + entityId); 164 Validator.validateEntityId(entityId, "Incorrect entityId " + entityId);
100 } 165 }
@@ -108,4 +173,15 @@ public class BaseTimeseriesService implements TimeseriesService { @@ -108,4 +173,15 @@ public class BaseTimeseriesService implements TimeseriesService {
108 throw new IncorrectParameterException("Incorrect TsKvQuery. Aggregation can't be empty"); 173 throw new IncorrectParameterException("Incorrect TsKvQuery. Aggregation can't be empty");
109 } 174 }
110 } 175 }
  176 +
  177 + private static TsKvQuery updateQuery(Long startTs, Long endTs, String viewKey, TsKvQuery query) {
  178 + return startTs <= query.getStartTs() && endTs >= query.getEndTs() ? query :
  179 + new BaseTsKvQuery(viewKey, startTs, endTs, query.getInterval(), query.getLimit(), query.getAggregation());
  180 + }
  181 +
  182 + private static void checkForNonEntityView(EntityId entityId) throws Exception {
  183 + if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
  184 + throw new Exception("Entity-views were read only");
  185 + }
  186 + }
111 } 187 }
@@ -642,6 +642,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( @@ -642,6 +642,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node (
642 CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( 642 CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
643 id timeuuid, 643 id timeuuid,
644 entity_id timeuuid, 644 entity_id timeuuid,
  645 + entity_type text,
645 tenant_id timeuuid, 646 tenant_id timeuuid,
646 customer_id timeuuid, 647 customer_id timeuuid,
647 name text, 648 name text,