Commit 009da885ad9486ffaa29325c7349f627d51fdf86
Committed by
GitHub
Merge pull request #1043 from ViktorBasanets/master
Entity View
Showing
16 changed files
with
292 additions
and
55 deletions
@@ -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 |
application/src/test/java/org/thingsboard/server/controller/nosql/EntityViewControllerNoSqlTest.java
@@ -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, |