Commit b0b6ee06bdeb0d7b6c5f1f6c6825b36540d97123
Committed by
GitHub
Merge pull request #1053 from ViktorBasanets/master
Entity View server side
Showing
30 changed files
with
1674 additions
and
4 deletions
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 | + | |
17 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_views_by_tenant_and_name; | |
18 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_views_by_tenant_and_entity; | |
19 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_views_by_tenant_and_customer; | |
20 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_views_by_tenant_and_customer_and_entity; | |
21 | + | |
22 | +DROP TABLE IF EXISTS thingsboard.entity_views; | |
23 | + | |
24 | +CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( | |
25 | + id timeuuid, | |
26 | + entity_id timeuuid, | |
27 | + tenant_id timeuuid, | |
28 | + customer_id timeuuid, | |
29 | + name text, | |
30 | + keys text, | |
31 | + ts_begin bigint, | |
32 | + ts_end bigint, | |
33 | + search_text text, | |
34 | + additional_info text, | |
35 | + PRIMARY KEY (id, entity_id, tenant_id, customer_id) | |
36 | + ); | |
37 | + | |
38 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS | |
39 | + SELECT * | |
40 | + from thingsboard.entity_views | |
41 | + WHERE entity_id IS NOT NULL | |
42 | + AND tenant_id IS NOT NULL | |
43 | + AND customer_id IS NOT NULL | |
44 | + AND keys IS NOT NULL | |
45 | + AND ts_begin IS NOT NULL | |
46 | + AND ts_end IS NOT NULL | |
47 | + AND name IS NOT NULL | |
48 | + AND id IS NOT NULL | |
49 | + PRIMARY KEY (tenant_id, name, id, entity_id, customer_id) | |
50 | + WITH CLUSTERING ORDER BY (name ASC, id DESC, entity_id DESC, customer_id DESC); | |
51 | + | |
52 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_entity AS | |
53 | + SELECT * | |
54 | + from thingsboard.entity_views | |
55 | + WHERE entity_id IS NOT NULL | |
56 | + AND tenant_id IS NOT NULL | |
57 | + AND customer_id IS NOT NULL | |
58 | + AND keys IS NOT NULL | |
59 | + AND ts_begin IS NOT NULL | |
60 | + AND ts_end IS NOT NULL | |
61 | + AND name IS NOT NULL | |
62 | + AND id IS NOT NULL | |
63 | + PRIMARY KEY (tenant_id, entity_id, id, customer_id, name) | |
64 | + WITH CLUSTERING ORDER BY (entity_id ASC, customer_id ASC, id DESC, name DESC); | |
65 | + | |
66 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_customer AS | |
67 | + SELECT * | |
68 | + from thingsboard.entity_views | |
69 | + WHERE entity_id IS NOT NULL | |
70 | + AND tenant_id IS NOT NULL | |
71 | + AND customer_id IS NOT NULL | |
72 | + AND keys IS NOT NULL | |
73 | + AND ts_begin IS NOT NULL | |
74 | + AND ts_end IS NOT NULL | |
75 | + AND name IS NOT NULL | |
76 | + AND id IS NOT NULL | |
77 | + PRIMARY KEY (tenant_id, customer_id, id, entity_id, name) | |
78 | + WITH CLUSTERING ORDER BY (customer_id ASC, id DESC, entity_id DESC, name DESC); | |
79 | + | |
80 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_customer_and_entity AS | |
81 | + SELECT * | |
82 | + from thingsboard.entity_views | |
83 | + WHERE entity_id IS NOT NULL | |
84 | + AND tenant_id IS NOT NULL | |
85 | + AND customer_id IS NOT NULL | |
86 | + AND keys IS NOT NULL | |
87 | + AND ts_begin IS NOT NULL | |
88 | + AND ts_end IS NOT NULL | |
89 | + AND name IS NOT NULL | |
90 | + AND id IS NOT NULL | |
91 | + PRIMARY KEY (tenant_id, customer_id, entity_id, id, name) | |
92 | + WITH CLUSTERING ORDER BY (customer_id ASC, entity_id DESC, id DESC, name DESC); | ... | ... |
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 | + | |
17 | +DROP TABLE IF EXISTS entity_views; | |
18 | + | |
19 | +CREATE TABLE IF NOT EXISTS entity_views ( | |
20 | + id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, | |
21 | + entity_id varchar(31), | |
22 | + entity_type varchar(255), | |
23 | + tenant_id varchar(31), | |
24 | + customer_id varchar(31), | |
25 | + name varchar(255), | |
26 | + keys varchar(255), | |
27 | + ts_begin varchar(255), | |
28 | + ts_end varchar(255), | |
29 | + search_text varchar(255), | |
30 | + additional_info varchar | |
31 | +); | ... | ... |
... | ... | @@ -56,6 +56,7 @@ import org.thingsboard.server.dao.customer.CustomerService; |
56 | 56 | import org.thingsboard.server.dao.dashboard.DashboardService; |
57 | 57 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
58 | 58 | import org.thingsboard.server.dao.device.DeviceService; |
59 | +import org.thingsboard.server.dao.entityview.EntityViewService; | |
59 | 60 | import org.thingsboard.server.dao.exception.DataValidationException; |
60 | 61 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
61 | 62 | import org.thingsboard.server.dao.model.ModelConstants; |
... | ... | @@ -139,6 +140,9 @@ public abstract class BaseController { |
139 | 140 | @Autowired |
140 | 141 | protected DeviceStateService deviceStateService; |
141 | 142 | |
143 | + @Autowired | |
144 | + protected EntityViewService entityViewService; | |
145 | + | |
142 | 146 | @ExceptionHandler(ThingsboardException.class) |
143 | 147 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { |
144 | 148 | errorResponseHandler.handle(ex, response); |
... | ... | @@ -313,6 +317,9 @@ public abstract class BaseController { |
313 | 317 | case USER: |
314 | 318 | checkUserId(new UserId(entityId.getId())); |
315 | 319 | return; |
320 | + case ENTITY_VIEW: | |
321 | + checkEntityView(entityViewService.findEntityViewById(new EntityViewId(entityId.getId()))); | |
322 | + return; | |
316 | 323 | default: |
317 | 324 | throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); |
318 | 325 | } |
... | ... | @@ -340,6 +347,25 @@ public abstract class BaseController { |
340 | 347 | } |
341 | 348 | } |
342 | 349 | |
350 | + protected EntityView checkEntityViewId(EntityViewId entityViewId) throws ThingsboardException { | |
351 | + try { | |
352 | + validateId(entityViewId, "Incorrect entityViewId " + entityViewId); | |
353 | + EntityView entityView = entityViewService.findEntityViewById(entityViewId); | |
354 | + checkEntityView(entityView); | |
355 | + return entityView; | |
356 | + } catch (Exception e) { | |
357 | + throw handleException(e, false); | |
358 | + } | |
359 | + } | |
360 | + | |
361 | + protected void checkEntityView(EntityView entityView) throws ThingsboardException { | |
362 | + checkNotNull(entityView); | |
363 | + checkTenantId(entityView.getTenantId()); | |
364 | + if (entityView.getCustomerId() != null && !entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { | |
365 | + checkCustomerId(entityView.getCustomerId()); | |
366 | + } | |
367 | + } | |
368 | + | |
343 | 369 | Asset checkAssetId(AssetId assetId) throws ThingsboardException { |
344 | 370 | try { |
345 | 371 | validateId(assetId, "Incorrect assetId " + assetId); | ... | ... |
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.controller; | |
17 | + | |
18 | +import com.google.common.util.concurrent.ListenableFuture; | |
19 | +import org.springframework.http.HttpStatus; | |
20 | +import org.springframework.security.access.prepost.PreAuthorize; | |
21 | +import org.springframework.web.bind.annotation.*; | |
22 | +import org.thingsboard.server.common.data.EntityType; | |
23 | +import org.thingsboard.server.common.data.EntityView; | |
24 | +import org.thingsboard.server.common.data.audit.ActionType; | |
25 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
26 | +import org.thingsboard.server.common.data.id.CustomerId; | |
27 | +import org.thingsboard.server.common.data.id.EntityViewId; | |
28 | +import org.thingsboard.server.common.data.id.TenantId; | |
29 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
30 | + | |
31 | +import java.util.ArrayList; | |
32 | +import java.util.List; | |
33 | + | |
34 | +/** | |
35 | + * Created by Victor Basanets on 8/28/2017. | |
36 | + */ | |
37 | +@RestController | |
38 | +@RequestMapping("/api") | |
39 | +public class EntityViewController extends BaseController { | |
40 | + | |
41 | + public static final String ENTITY_VIEW_ID = "entityViewId"; | |
42 | + | |
43 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | |
44 | + @RequestMapping(value = "/entity-view/{entityViewId}", method = RequestMethod.GET) | |
45 | + @ResponseBody | |
46 | + public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) | |
47 | + throws ThingsboardException { | |
48 | + | |
49 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | |
50 | + try { | |
51 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | |
52 | + return checkEntityViewId(entityViewId); | |
53 | + } catch (Exception e) { | |
54 | + throw handleException(e); | |
55 | + } | |
56 | + } | |
57 | + | |
58 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | |
59 | + @RequestMapping(value = "/entity-view", method = RequestMethod.POST) | |
60 | + @ResponseBody | |
61 | + public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { | |
62 | + try { | |
63 | + entityView.setTenantId(getCurrentUser().getTenantId()); | |
64 | + EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); | |
65 | + logEntityAction(savedEntityView.getId(), savedEntityView, null, | |
66 | + entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); | |
67 | + | |
68 | + return savedEntityView; | |
69 | + | |
70 | + } catch (Exception e) { | |
71 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, | |
72 | + entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); | |
73 | + | |
74 | + throw handleException(e); | |
75 | + } | |
76 | + } | |
77 | + | |
78 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | |
79 | + @RequestMapping(value = "/entity-view/{entityViewId}", method = RequestMethod.DELETE) | |
80 | + @ResponseStatus(value = HttpStatus.OK) | |
81 | + public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | |
82 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | |
83 | + try { | |
84 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | |
85 | + EntityView entityView = checkEntityViewId(entityViewId); | |
86 | + entityViewService.deleteEntityView(entityViewId); | |
87 | + | |
88 | + logEntityAction(entityViewId, entityView, entityView.getCustomerId(), | |
89 | + ActionType.DELETED,null, strEntityViewId); | |
90 | + } catch (Exception e) { | |
91 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), | |
92 | + null, | |
93 | + null, | |
94 | + ActionType.DELETED, e, strEntityViewId); | |
95 | + throw handleException(e); | |
96 | + } | |
97 | + } | |
98 | +} | ... | ... |
... | ... | @@ -88,6 +88,13 @@ public class ThingsboardInstallService { |
88 | 88 | |
89 | 89 | dataUpdateService.updateData("1.4.0"); |
90 | 90 | |
91 | + case "2.0.0": | |
92 | + log.info("Upgrading ThingsBoard from version 2.0.0 to 2.1.1 ..."); | |
93 | + | |
94 | + databaseUpgradeService.upgradeDatabase("2.0.0"); | |
95 | + | |
96 | + dataUpdateService.updateData("2.0.0"); | |
97 | + | |
91 | 98 | log.info("Updating system data..."); |
92 | 99 | |
93 | 100 | systemDataLoaderService.deleteSystemWidgetBundle("charts"); | ... | ... |
... | ... | @@ -49,6 +49,10 @@ public class DefaultDataUpdateService implements DataUpdateService { |
49 | 49 | log.info("Updating data from version 1.4.0 to 2.0.0 ..."); |
50 | 50 | tenantsDefaultRuleChainUpdater.updateEntities(null); |
51 | 51 | break; |
52 | + case "2.0.0": | |
53 | + log.info("Updating data from version 2.0.0 to 2.1.1 ..."); | |
54 | + tenantsDefaultRuleChainUpdater.updateEntities(null); | |
55 | + break; | |
52 | 56 | default: |
53 | 57 | throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); |
54 | 58 | } | ... | ... |
... | ... | @@ -107,6 +107,15 @@ public class SqlDatabaseUpgradeService implements DatabaseUpgradeService { |
107 | 107 | log.info("Schema updated."); |
108 | 108 | } |
109 | 109 | break; |
110 | + case "2.0.0": | |
111 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | |
112 | + log.info("Updating schema ..."); | |
113 | + schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.1.1", SCHEMA_UPDATE_SQL); | |
114 | + loadSql(schemaUpdateFile, conn); | |
115 | + log.info("Schema updated."); | |
116 | + } | |
117 | + break; | |
118 | + | |
110 | 119 | default: |
111 | 120 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
112 | 121 | } | ... | ... |
application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
0 → 100644
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.controller; | |
17 | + | |
18 | +import org.junit.After; | |
19 | +import org.junit.Assert; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.Device; | |
23 | +import org.thingsboard.server.common.data.EntityView; | |
24 | +import org.thingsboard.server.common.data.Tenant; | |
25 | +import org.thingsboard.server.common.data.User; | |
26 | +import org.thingsboard.server.common.data.objects.AttributesEntityView; | |
27 | +import org.thingsboard.server.common.data.objects.TelemetryEntityView; | |
28 | +import org.thingsboard.server.common.data.security.Authority; | |
29 | + | |
30 | +import java.util.Arrays; | |
31 | + | |
32 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
33 | +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; | |
34 | + | |
35 | +public abstract class BaseEntityViewControllerTest extends AbstractControllerTest { | |
36 | + | |
37 | + private Tenant savedTenant; | |
38 | + private User tenantAdmin; | |
39 | + private Device testDevice; | |
40 | + private TelemetryEntityView obj; | |
41 | + | |
42 | + @Before | |
43 | + public void beforeTest() throws Exception { | |
44 | + loginSysAdmin(); | |
45 | + | |
46 | + Tenant tenant = new Tenant(); | |
47 | + tenant.setTitle("My tenant"); | |
48 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); | |
49 | + | |
50 | + Assert.assertNotNull(savedTenant); | |
51 | + | |
52 | + tenantAdmin = new User(); | |
53 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | |
54 | + tenantAdmin.setTenantId(savedTenant.getId()); | |
55 | + tenantAdmin.setEmail("tenant2@thingsboard.org"); | |
56 | + tenantAdmin.setFirstName("Joe"); | |
57 | + tenantAdmin.setLastName("Downs"); | |
58 | + | |
59 | + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | |
60 | + | |
61 | + Device device = new Device(); | |
62 | + device.setName("Test device"); | |
63 | + device.setType("default"); | |
64 | + testDevice = doPost("/api/device", device, Device.class); | |
65 | + | |
66 | + obj = new TelemetryEntityView( | |
67 | + Arrays.asList("109L", "209L"), | |
68 | + new AttributesEntityView( | |
69 | + Arrays.asList("caKey1", "caKey2", "caKey3"), | |
70 | + Arrays.asList("saKey1", "saKey2", "saKey3", "saKey4"), | |
71 | + Arrays.asList("shKey1", "shKey2", "shKey3", "shKey4", "shKey5"))); | |
72 | + } | |
73 | + | |
74 | + @After | |
75 | + public void afterTest() throws Exception { | |
76 | + loginSysAdmin(); | |
77 | + | |
78 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | |
79 | + .andExpect(status().isOk()); | |
80 | + } | |
81 | + | |
82 | + @Test | |
83 | + public void testFindEntityViewById() throws Exception { | |
84 | + EntityView view = new EntityView(); | |
85 | + view.setName("Test entity view"); | |
86 | + view.setEntityId(testDevice.getId()); | |
87 | + view.setKeys(new TelemetryEntityView(obj)); | |
88 | + EntityView savedView = doPost("/api/entity-view", view, EntityView.class); | |
89 | + EntityView foundView = doGet("/api/entity-view/" + savedView.getId().getId().toString(), EntityView.class); | |
90 | + Assert.assertNotNull(foundView); | |
91 | + Assert.assertEquals(savedView, foundView); | |
92 | + } | |
93 | + | |
94 | + @Test | |
95 | + public void testSaveEntityViewWithIdOfDevice() throws Exception { | |
96 | + EntityView view = new EntityView(); | |
97 | + view.setEntityId(testDevice.getId()); | |
98 | + view.setName("Test entity view"); | |
99 | + view.setTenantId(savedTenant.getId()); | |
100 | + view.setKeys(new TelemetryEntityView(obj)); | |
101 | + EntityView savedView = doPost("/api/entity-view", view, EntityView.class); | |
102 | + | |
103 | + Assert.assertNotNull(savedView); | |
104 | + Assert.assertNotNull(savedView.getId()); | |
105 | + Assert.assertTrue(savedView.getCreatedTime() > 0); | |
106 | + Assert.assertEquals(savedTenant.getId(), savedView.getTenantId()); | |
107 | + Assert.assertNotNull(savedView.getCustomerId()); | |
108 | + Assert.assertEquals(NULL_UUID, savedView.getCustomerId().getId()); | |
109 | + Assert.assertEquals(savedView.getName(), savedView.getName()); | |
110 | + | |
111 | + savedView.setName("New test entity view"); | |
112 | + doPost("/api/entity-view", savedView, EntityView.class); | |
113 | + | |
114 | + EntityView foundEntityView = doGet("/api/entity-view/" | |
115 | + + savedView.getId().getId().toString(), EntityView.class); | |
116 | + | |
117 | + Assert.assertEquals(foundEntityView.getName(), savedView.getName()); | |
118 | + } | |
119 | + | |
120 | + @Test | |
121 | + public void testDeleteEntityView() throws Exception { | |
122 | + EntityView view = new EntityView(); | |
123 | + view.setName("Test entity view"); | |
124 | + view.setEntityId(testDevice.getId()); | |
125 | + view.setKeys(new TelemetryEntityView((TelemetryEntityView) obj)); | |
126 | + EntityView savedView = doPost("/api/entity-view", view, EntityView.class); | |
127 | + | |
128 | + doDelete("/api/entity-view/" + savedView.getId().getId().toString()) | |
129 | + .andExpect(status().isOk()); | |
130 | + | |
131 | + doGet("/api/entity-view/" + savedView.getId().getId().toString()) | |
132 | + .andExpect(status().isNotFound()); | |
133 | + } | |
134 | +} | ... | ... |
... | ... | @@ -24,7 +24,7 @@ import java.util.Arrays; |
24 | 24 | |
25 | 25 | @RunWith(ClasspathSuite.class) |
26 | 26 | @ClasspathSuite.ClassnameFilters({ |
27 | - "org.thingsboard.server.controller.sql.*SqlTest", | |
27 | + "org.thingsboard.server.controller.sql.EntityViewControllerSqlTest", | |
28 | 28 | }) |
29 | 29 | public class ControllerSqlTestSuite { |
30 | 30 | ... | ... |
application/src/test/java/org/thingsboard/server/controller/nosql/EntityViewControllerNoSqlTest.java
0 → 100644
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.controller.nosql; | |
17 | + | |
18 | +import org.thingsboard.server.controller.BaseEntityViewControllerTest; | |
19 | + | |
20 | +/** | |
21 | + * Created by Victor Basanets on 8/27/2017. | |
22 | + */ | |
23 | +public class EntityViewControllerNoSqlTest extends BaseEntityViewControllerTest { | |
24 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/controller/sql/EntityViewControllerSqlTest.java
0 → 100644
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.controller.sql; | |
17 | + | |
18 | +import org.junit.Assert; | |
19 | +import org.junit.Test; | |
20 | +import org.thingsboard.server.common.data.EntityView; | |
21 | +import org.thingsboard.server.controller.BaseEntityViewControllerTest; | |
22 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
23 | + | |
24 | +import java.util.Arrays; | |
25 | + | |
26 | +/** | |
27 | + * Created by Victor Basanets on 8/27/2017. | |
28 | + */ | |
29 | +@DaoSqlTest | |
30 | +public class EntityViewControllerSqlTest extends BaseEntityViewControllerTest { | |
31 | +} | ... | ... |
... | ... | @@ -20,4 +20,5 @@ public class CacheConstants { |
20 | 20 | public static final String RELATIONS_CACHE = "relations"; |
21 | 21 | public static final String DEVICE_CACHE = "devices"; |
22 | 22 | public static final String ASSET_CACHE = "assets"; |
23 | + public static final String ENTITY_VIEW_CACHE = "entityViews"; | |
23 | 24 | } | ... | ... |
... | ... | @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; |
19 | 19 | * @author Andrew Shvayka |
20 | 20 | */ |
21 | 21 | public enum EntityType { |
22 | - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE; | |
22 | + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW | |
23 | 23 | } | ... | ... |
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.common.data; | |
17 | + | |
18 | +import lombok.*; | |
19 | +import org.thingsboard.server.common.data.id.CustomerId; | |
20 | +import org.thingsboard.server.common.data.id.EntityId; | |
21 | +import org.thingsboard.server.common.data.id.EntityViewId; | |
22 | +import org.thingsboard.server.common.data.id.TenantId; | |
23 | +import org.thingsboard.server.common.data.objects.TelemetryEntityView; | |
24 | + | |
25 | +/** | |
26 | + * Created by Victor Basanets on 8/27/2017. | |
27 | + */ | |
28 | + | |
29 | +@Data | |
30 | +@AllArgsConstructor | |
31 | +@EqualsAndHashCode(callSuper = true) | |
32 | +public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> | |
33 | + implements HasName, HasTenantId, HasCustomerId { | |
34 | + | |
35 | + private static final long serialVersionUID = 5582010124562018986L; | |
36 | + | |
37 | + private EntityId entityId; | |
38 | + private TenantId tenantId; | |
39 | + private CustomerId customerId; | |
40 | + private String name; | |
41 | + private TelemetryEntityView keys; | |
42 | + private Long tsBegin; | |
43 | + private Long tsEnd; | |
44 | + | |
45 | + public EntityView() { | |
46 | + super(); | |
47 | + } | |
48 | + | |
49 | + public EntityView(EntityViewId id) { | |
50 | + super(id); | |
51 | + } | |
52 | + | |
53 | + public EntityView(EntityView entityView) { | |
54 | + super(entityView); | |
55 | + } | |
56 | + | |
57 | + @Override | |
58 | + public String getSearchText() { | |
59 | + return getName() /*What the ...*/; | |
60 | + } | |
61 | + | |
62 | + @Override | |
63 | + public CustomerId getCustomerId() { | |
64 | + return customerId; | |
65 | + } | |
66 | + | |
67 | + @Override | |
68 | + public String getName() { | |
69 | + return name; | |
70 | + } | |
71 | + | |
72 | + @Override | |
73 | + public TenantId getTenantId() { | |
74 | + return tenantId; | |
75 | + } | |
76 | +} | ... | ... |
... | ... | @@ -57,6 +57,8 @@ public class EntityIdFactory { |
57 | 57 | return new RuleChainId(uuid); |
58 | 58 | case RULE_NODE: |
59 | 59 | return new RuleNodeId(uuid); |
60 | + case ENTITY_VIEW: | |
61 | + return new EntityViewId(uuid); | |
60 | 62 | } |
61 | 63 | throw new IllegalArgumentException("EntityType " + type + " is not supported!"); |
62 | 64 | } | ... | ... |
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.common.data.id; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonCreator; | |
19 | +import com.fasterxml.jackson.annotation.JsonProperty; | |
20 | +import org.thingsboard.server.common.data.EntityType; | |
21 | + | |
22 | +import java.util.UUID; | |
23 | + | |
24 | +/** | |
25 | + * Created by Victor Basanets on 8/27/2017. | |
26 | + */ | |
27 | +public class EntityViewId extends UUIDBased implements EntityId { | |
28 | + | |
29 | + private static final long serialVersionUID = 1L; | |
30 | + | |
31 | + @JsonCreator | |
32 | + public EntityViewId(@JsonProperty("id") UUID id) { | |
33 | + super(id); | |
34 | + } | |
35 | + | |
36 | + public static EntityViewId fromString(String entityViewID) { | |
37 | + return new EntityViewId(UUID.fromString(entityViewID)); | |
38 | + } | |
39 | + | |
40 | + @Override | |
41 | + public EntityType getEntityType() { | |
42 | + return EntityType.ENTITY_VIEW; | |
43 | + } | |
44 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/objects/AttributesEntityView.java
0 → 100644
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.common.data.objects; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import lombok.NoArgsConstructor; | |
20 | + | |
21 | +import java.util.ArrayList; | |
22 | +import java.util.List; | |
23 | + | |
24 | +/** | |
25 | + * Created by Victor Basanets on 9/05/2017. | |
26 | + */ | |
27 | +@Data | |
28 | +@NoArgsConstructor | |
29 | +public class AttributesEntityView { | |
30 | + | |
31 | + private List<String> cs = new ArrayList<>(); | |
32 | + private List<String> ss = new ArrayList<>(); | |
33 | + private List<String> sh = new ArrayList<>(); | |
34 | + | |
35 | + public AttributesEntityView(List<String> cs, | |
36 | + List<String> ss, | |
37 | + List<String> sh) { | |
38 | + | |
39 | + this.cs = new ArrayList<>(cs); | |
40 | + this.ss = new ArrayList<>(ss); | |
41 | + this.sh = new ArrayList<>(sh); | |
42 | + } | |
43 | + | |
44 | + public AttributesEntityView(AttributesEntityView obj) { | |
45 | + this(obj.getCs(), obj.getSs(), obj.getSh()); | |
46 | + } | |
47 | + | |
48 | + @Override | |
49 | + public String toString() { | |
50 | + return "{cs=" + cs + ", ss=" + ss + ", sh=" + sh + '}'; | |
51 | + } | |
52 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/objects/TelemetryEntityView.java
0 → 100644
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.common.data.objects; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import lombok.NoArgsConstructor; | |
20 | + | |
21 | +import java.util.ArrayList; | |
22 | +import java.util.List; | |
23 | + | |
24 | +/** | |
25 | + * Created by Victor Basanets on 9/05/2017. | |
26 | + */ | |
27 | +@Data | |
28 | +@NoArgsConstructor | |
29 | +public class TelemetryEntityView { | |
30 | + | |
31 | + private List<String> timeseries; | |
32 | + private AttributesEntityView attributes; | |
33 | + | |
34 | + public TelemetryEntityView(List<String> timeseries, AttributesEntityView attributes) { | |
35 | + | |
36 | + this.timeseries = new ArrayList<>(timeseries); | |
37 | + this.attributes = attributes; | |
38 | + } | |
39 | + | |
40 | + public TelemetryEntityView(TelemetryEntityView obj) { | |
41 | + this(obj.getTimeseries(), obj.getAttributes()); | |
42 | + } | |
43 | + | |
44 | + @Override | |
45 | + public String toString() { | |
46 | + return "{timeseries=" + timeseries + ", attributes=" + attributes + '}'; | |
47 | + } | |
48 | +} | ... | ... |
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 org.thingsboard.server.common.data.EntityView; | |
19 | +import org.thingsboard.server.common.data.id.EntityId; | |
20 | +import org.thingsboard.server.common.data.page.TextPageLink; | |
21 | +import org.thingsboard.server.dao.Dao; | |
22 | + | |
23 | +import java.util.List; | |
24 | +import java.util.Optional; | |
25 | +import java.util.UUID; | |
26 | + | |
27 | +/** | |
28 | + * Created by Victor Basanets on 8/28/2017. | |
29 | + */ | |
30 | +public interface EntityViewDao extends Dao<EntityView> { | |
31 | + | |
32 | + /** | |
33 | + * Find entity views by tenantId and page link. | |
34 | + * | |
35 | + * @param tenantId the tenantId | |
36 | + * @param pageLink the page link | |
37 | + * @return the list of entity view objects | |
38 | + */ | |
39 | + List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink); | |
40 | + | |
41 | + /** | |
42 | + * Find entity views by tenantId and entity view name. | |
43 | + * | |
44 | + * @param tenantId the tenantId | |
45 | + * @param name the entity view name | |
46 | + * @return the optional entity view object | |
47 | + */ | |
48 | + Optional<EntityView> findEntityViewByTenantIdAndName(UUID tenantId, String name); | |
49 | + | |
50 | + /** | |
51 | + * Find entity views by tenantId, entityId and page link. | |
52 | + * | |
53 | + * @param tenantId the tenantId | |
54 | + * @param entityId the entityId | |
55 | + * @param pageLink the page link | |
56 | + * @return the list of entity view objects | |
57 | + */ | |
58 | + List<EntityView> findEntityViewByTenantIdAndEntityId(UUID tenantId, | |
59 | + UUID entityId, | |
60 | + TextPageLink pageLink); | |
61 | + | |
62 | + /** | |
63 | + * Find entity views by tenantId, customerId and page link. | |
64 | + * | |
65 | + * @param tenantId the tenantId | |
66 | + * @param customerId the customerId | |
67 | + * @param pageLink the page link | |
68 | + * @return the list of entity view objects | |
69 | + */ | |
70 | + List<EntityView> findEntityViewsByTenantIdAndCustomerId(UUID tenantId, | |
71 | + UUID customerId, | |
72 | + TextPageLink pageLink); | |
73 | + | |
74 | + /** | |
75 | + * Find entity views by tenantId, customerId, entityId and page link. | |
76 | + * | |
77 | + * @param tenantId the tenantId | |
78 | + * @param customerId the customerId | |
79 | + * @param entityId the entityId | |
80 | + * @param pageLink the page link | |
81 | + * @return the list of entity view objects | |
82 | + */ | |
83 | + List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(UUID tenantId, | |
84 | + UUID customerId, | |
85 | + UUID entityId, | |
86 | + TextPageLink pageLink); | |
87 | + | |
88 | +} | ... | ... |
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 org.thingsboard.server.common.data.EntityType; | |
19 | +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; | |
24 | +import org.thingsboard.server.common.data.page.TextPageData; | |
25 | +import org.thingsboard.server.common.data.page.TextPageLink; | |
26 | + | |
27 | +/** | |
28 | + * Created by Victor Basanets on 8/27/2017. | |
29 | + */ | |
30 | +public interface EntityViewService { | |
31 | + | |
32 | + EntityView findEntityViewById(EntityViewId entityViewId); | |
33 | + | |
34 | + EntityView findEntityViewByTenantIdAndName(TenantId tenantId, String name); | |
35 | + | |
36 | + EntityView saveEntityView(EntityView entityView); | |
37 | + | |
38 | + EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId); | |
39 | + | |
40 | + EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId); | |
41 | + | |
42 | + void deleteEntityView(EntityViewId entityViewId); | |
43 | + | |
44 | + TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink); | |
45 | + | |
46 | + TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, | |
47 | + TextPageLink pageLink); | |
48 | + | |
49 | + void deleteEntityViewByTenantId(TenantId tenantId); | |
50 | + | |
51 | + TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, | |
52 | + TextPageLink pageLink); | |
53 | + | |
54 | + TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId, | |
55 | + CustomerId customerId, | |
56 | + EntityId entityId, | |
57 | + TextPageLink pageLink); | |
58 | + | |
59 | + void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); | |
60 | +} | ... | ... |
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 lombok.extern.slf4j.Slf4j; | |
19 | +import org.apache.commons.lang3.StringUtils; | |
20 | +import org.springframework.beans.factory.annotation.Autowired; | |
21 | +import org.springframework.cache.Cache; | |
22 | +import org.springframework.cache.CacheManager; | |
23 | +import org.springframework.stereotype.Service; | |
24 | +import org.thingsboard.server.common.data.Customer; | |
25 | +import org.thingsboard.server.common.data.EntityView; | |
26 | +import org.thingsboard.server.common.data.Tenant; | |
27 | +import org.thingsboard.server.common.data.id.CustomerId; | |
28 | +import org.thingsboard.server.common.data.id.EntityId; | |
29 | +import org.thingsboard.server.common.data.id.EntityViewId; | |
30 | +import org.thingsboard.server.common.data.id.TenantId; | |
31 | +import org.thingsboard.server.common.data.page.TextPageData; | |
32 | +import org.thingsboard.server.common.data.page.TextPageLink; | |
33 | +import org.thingsboard.server.dao.customer.CustomerDao; | |
34 | +import org.thingsboard.server.dao.entity.AbstractEntityService; | |
35 | +import org.thingsboard.server.dao.exception.DataValidationException; | |
36 | +import org.thingsboard.server.dao.service.DataValidator; | |
37 | +import org.thingsboard.server.dao.service.PaginatedRemover; | |
38 | +import org.thingsboard.server.dao.tenant.TenantDao; | |
39 | + | |
40 | +import java.util.ArrayList; | |
41 | +import java.util.List; | |
42 | + | |
43 | +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; | |
44 | +import static org.thingsboard.server.dao.service.Validator.validateId; | |
45 | +import static org.thingsboard.server.dao.service.Validator.validatePageLink; | |
46 | +import static org.thingsboard.server.dao.service.Validator.validateString; | |
47 | + | |
48 | +/** | |
49 | + * Created by Victor Basanets on 8/28/2017. | |
50 | + */ | |
51 | +@Service | |
52 | +@Slf4j | |
53 | +public class EntityViewServiceImpl extends AbstractEntityService | |
54 | + implements EntityViewService { | |
55 | + | |
56 | + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | |
57 | + public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; | |
58 | + public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; | |
59 | + public static final String INCORRECT_ENTITY_VIEW_ID = "Incorrect entityViewId "; | |
60 | + | |
61 | + @Autowired | |
62 | + private EntityViewDao entityViewDao; | |
63 | + | |
64 | + @Autowired | |
65 | + private TenantDao tenantDao; | |
66 | + | |
67 | + @Autowired | |
68 | + private CustomerDao customerDao; | |
69 | + | |
70 | + @Override | |
71 | + public EntityView findEntityViewById(EntityViewId entityViewId) { | |
72 | + log.trace("Executing findEntityViewById [{}]", entityViewId); | |
73 | + validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); | |
74 | + return entityViewDao.findById(entityViewId.getId()); | |
75 | + } | |
76 | + | |
77 | + @Override | |
78 | + public EntityView findEntityViewByTenantIdAndName(TenantId tenantId, String name) { | |
79 | + log.trace("Executing findEntityViewByTenantIdAndName [{}][{}]", tenantId, name); | |
80 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
81 | + return entityViewDao.findEntityViewByTenantIdAndName(tenantId.getId(), name) | |
82 | + .orElse(null); | |
83 | + } | |
84 | + | |
85 | + @Override | |
86 | + public EntityView saveEntityView(EntityView entityView) { | |
87 | + log.trace("Executing save entity view [{}]", entityView); | |
88 | + entityViewValidator.validate(entityView); | |
89 | + return entityViewDao.save(entityView); | |
90 | + } | |
91 | + | |
92 | + @Override | |
93 | + public EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId) { | |
94 | + EntityView entityView = findEntityViewById(entityViewId); | |
95 | + entityView.setCustomerId(customerId); | |
96 | + return saveEntityView(entityView); | |
97 | + } | |
98 | + | |
99 | + @Override | |
100 | + public EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId) { | |
101 | + EntityView entityView = findEntityViewById(entityViewId); | |
102 | + entityView.setCustomerId(null); | |
103 | + return saveEntityView(entityView); | |
104 | + } | |
105 | + | |
106 | + @Override | |
107 | + public void deleteEntityView(EntityViewId entityViewId) { | |
108 | + log.trace("Executing deleteEntityView [{}]", entityViewId); | |
109 | + validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); | |
110 | + deleteEntityRelations(entityViewId); | |
111 | + EntityView entityView = entityViewDao.findById(entityViewId.getId()); | |
112 | + List<Object> list = new ArrayList<>(); | |
113 | + list.add(entityView.getTenantId()); | |
114 | + list.add(entityView.getName()); | |
115 | + entityViewDao.removeById(entityViewId.getId()); | |
116 | + } | |
117 | + | |
118 | + @Override | |
119 | + public TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink) { | |
120 | + log.trace("Executing findEntityViewByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); | |
121 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
122 | + validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); | |
123 | + List<EntityView> entityViews = entityViewDao.findEntityViewByTenantId(tenantId.getId(), pageLink); | |
124 | + return new TextPageData<>(entityViews, pageLink); | |
125 | + } | |
126 | + | |
127 | + @Override | |
128 | + public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, | |
129 | + TextPageLink pageLink) { | |
130 | + | |
131 | + log.trace("Executing findEntityViewByTenantIdAndType, tenantId [{}], entityId [{}], pageLink [{}]", | |
132 | + tenantId, entityId, pageLink); | |
133 | + | |
134 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
135 | + validateString(entityId.toString(), "Incorrect entityId " + entityId.toString()); | |
136 | + validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); | |
137 | + List<EntityView> entityViews = entityViewDao.findEntityViewByTenantIdAndEntityId(tenantId.getId(), | |
138 | + entityId.getId(), pageLink); | |
139 | + | |
140 | + return new TextPageData<>(entityViews, pageLink); | |
141 | + } | |
142 | + | |
143 | + @Override | |
144 | + public void deleteEntityViewByTenantId(TenantId tenantId) { | |
145 | + log.trace("Executing deleteEntityViewByTenantId, tenantId [{}]", tenantId); | |
146 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
147 | + tenantEntityViewRemover.removeEntities(tenantId); | |
148 | + } | |
149 | + | |
150 | + @Override | |
151 | + public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, | |
152 | + TextPageLink pageLink) { | |
153 | + | |
154 | + log.trace("Executing findEntityViewByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," + | |
155 | + " pageLink [{}]", tenantId, customerId, pageLink); | |
156 | + | |
157 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
158 | + validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); | |
159 | + validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); | |
160 | + List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), | |
161 | + customerId.getId(), pageLink); | |
162 | + | |
163 | + return new TextPageData<>(entityViews, pageLink); | |
164 | + } | |
165 | + | |
166 | + @Override | |
167 | + public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId, | |
168 | + CustomerId customerId, | |
169 | + EntityId entityId, | |
170 | + TextPageLink pageLink) { | |
171 | + | |
172 | + log.trace("Executing findEntityViewsByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}]," + | |
173 | + " entityId [{}], pageLink [{}]", tenantId, customerId, entityId, pageLink); | |
174 | + | |
175 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
176 | + validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); | |
177 | + validateString(entityId.toString(), "Incorrect entityId " + entityId.toString()); | |
178 | + validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); | |
179 | + List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerIdAndEntityId( | |
180 | + tenantId.getId(), customerId.getId(), entityId.getId(), pageLink); | |
181 | + | |
182 | + return new TextPageData<>(entityViews, pageLink); | |
183 | + } | |
184 | + | |
185 | + @Override | |
186 | + public void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId) { | |
187 | + log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId); | |
188 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
189 | + validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); | |
190 | + new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId); | |
191 | + } | |
192 | + | |
193 | + private DataValidator<EntityView> entityViewValidator = | |
194 | + new DataValidator<EntityView>() { | |
195 | + | |
196 | + @Override | |
197 | + protected void validateCreate(EntityView entityView) { | |
198 | + entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName()) | |
199 | + .ifPresent( e -> { | |
200 | + throw new DataValidationException("Entity view with such name already exists!"); | |
201 | + }); | |
202 | + } | |
203 | + | |
204 | + @Override | |
205 | + protected void validateUpdate(EntityView entityView) { | |
206 | + entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName()) | |
207 | + .ifPresent( e -> { | |
208 | + if (!e.getUuidId().equals(entityView.getUuidId())) { | |
209 | + throw new DataValidationException("Entity view with such name already exists!"); | |
210 | + } | |
211 | + }); | |
212 | + } | |
213 | + | |
214 | + @Override | |
215 | + protected void validateDataImpl(EntityView entityView) { | |
216 | + if (StringUtils.isEmpty(entityView.getKeys().toString())) { | |
217 | + throw new DataValidationException("Entity view type should be specified!"); | |
218 | + } | |
219 | + if (StringUtils.isEmpty(entityView.getName())) { | |
220 | + throw new DataValidationException("Entity view name should be specified!"); | |
221 | + } | |
222 | + if (entityView.getTenantId() == null) { | |
223 | + throw new DataValidationException("Entity view should be assigned to tenant!"); | |
224 | + } else { | |
225 | + Tenant tenant = tenantDao.findById(entityView.getTenantId().getId()); | |
226 | + if (tenant == null) { | |
227 | + throw new DataValidationException("Entity view is referencing to non-existent tenant!"); | |
228 | + } | |
229 | + } | |
230 | + if (entityView.getCustomerId() == null) { | |
231 | + entityView.setCustomerId(new CustomerId(NULL_UUID)); | |
232 | + } else if (!entityView.getCustomerId().getId().equals(NULL_UUID)) { | |
233 | + Customer customer = customerDao.findById(entityView.getCustomerId().getId()); | |
234 | + if (customer == null) { | |
235 | + throw new DataValidationException("Can't assign entity view to non-existent customer!"); | |
236 | + } | |
237 | + if (!customer.getTenantId().getId().equals(entityView.getTenantId().getId())) { | |
238 | + throw new DataValidationException("Can't assign entity view to customer from different tenant!"); | |
239 | + } | |
240 | + } | |
241 | + } | |
242 | + }; | |
243 | + | |
244 | + private PaginatedRemover<TenantId, EntityView> tenantEntityViewRemover = | |
245 | + new PaginatedRemover<TenantId, EntityView>() { | |
246 | + | |
247 | + @Override | |
248 | + protected List<EntityView> findEntities(TenantId id, TextPageLink pageLink) { | |
249 | + return entityViewDao.findEntityViewByTenantId(id.getId(), pageLink); | |
250 | + } | |
251 | + | |
252 | + @Override | |
253 | + protected void removeEntity(EntityView entity) { | |
254 | + deleteEntityView(new EntityViewId(entity.getUuidId())); | |
255 | + } | |
256 | + }; | |
257 | + | |
258 | + private class CustomerEntityViewsUnAssigner extends PaginatedRemover<CustomerId, EntityView> { | |
259 | + | |
260 | + private TenantId tenantId; | |
261 | + | |
262 | + CustomerEntityViewsUnAssigner(TenantId tenantId) { | |
263 | + this.tenantId = tenantId; | |
264 | + } | |
265 | + | |
266 | + @Override | |
267 | + protected List<EntityView> findEntities(CustomerId id, TextPageLink pageLink) { | |
268 | + return entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink); | |
269 | + } | |
270 | + | |
271 | + @Override | |
272 | + protected void removeEntity(EntityView entity) { | |
273 | + unassignEntityViewFromCustomer(new EntityViewId(entity.getUuidId())); | |
274 | + } | |
275 | + } | |
276 | +} | ... | ... |
... | ... | @@ -45,6 +45,7 @@ public class ModelConstants { |
45 | 45 | public static final String SEARCH_TEXT_PROPERTY = "search_text"; |
46 | 46 | public static final String ADDITIONAL_INFO_PROPERTY = "additional_info"; |
47 | 47 | public static final String ENTITY_TYPE_PROPERTY = "entity_type"; |
48 | + /*public static final String ENTITY_VIEW_ID_PROPERTY = "entity_view_id";*/ | |
48 | 49 | |
49 | 50 | public static final String ENTITY_TYPE_COLUMN = ENTITY_TYPE_PROPERTY; |
50 | 51 | public static final String ENTITY_ID_COLUMN = "entity_id"; |
... | ... | @@ -144,6 +145,20 @@ public class ModelConstants { |
144 | 145 | public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant"; |
145 | 146 | |
146 | 147 | /** |
148 | + * Cassandra entityView constants. | |
149 | + */ | |
150 | + public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_views"; | |
151 | + public static final String ENTITY_VIEW_ENTITY_ID_PROPERTY = ENTITY_ID_COLUMN; | |
152 | + 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; | |
154 | + public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY; | |
155 | + public static final String ENTITY_VIEW_TYPE_PROPERTY = "type_entity"; | |
156 | + public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys"; | |
157 | + public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin"; | |
158 | + public static final String ENTITY_VIEW_TS_END_PROPERTY = "ts_end"; | |
159 | + public static final String ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; | |
160 | + | |
161 | + /** | |
147 | 162 | * Cassandra audit log constants. |
148 | 163 | */ |
149 | 164 | public static final String AUDIT_LOG_COLUMN_FAMILY_NAME = "audit_log"; | ... | ... |
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.model.nosql; | |
17 | + | |
18 | +import com.datastax.driver.core.utils.UUIDs; | |
19 | +import com.datastax.driver.mapping.annotations.PartitionKey; | |
20 | +import com.datastax.driver.mapping.annotations.Table; | |
21 | +import com.fasterxml.jackson.databind.JsonNode; | |
22 | +import lombok.Data; | |
23 | +import lombok.EqualsAndHashCode; | |
24 | +import lombok.ToString; | |
25 | +import org.hibernate.annotations.Type; | |
26 | +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; | |
31 | +import org.thingsboard.server.common.data.objects.TelemetryEntityView; | |
32 | +import org.thingsboard.server.dao.model.ModelConstants; | |
33 | +import org.thingsboard.server.dao.model.SearchTextEntity; | |
34 | + | |
35 | +import javax.persistence.Column; | |
36 | + | |
37 | +import java.io.IOException; | |
38 | +import java.util.UUID; | |
39 | + | |
40 | +import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME; | |
41 | +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; | |
42 | + | |
43 | +/** | |
44 | + * Created by Victor Basanets on 8/31/2017. | |
45 | + */ | |
46 | +@Data | |
47 | +@Table(name = ENTITY_VIEW_TABLE_FAMILY_NAME) | |
48 | +@EqualsAndHashCode | |
49 | +@ToString | |
50 | +public class EntityViewEntity implements SearchTextEntity<EntityView> { | |
51 | + | |
52 | + @PartitionKey(value = 0) | |
53 | + @Column(name = ID_PROPERTY) | |
54 | + private UUID id; | |
55 | + | |
56 | + @PartitionKey(value = 1) | |
57 | + @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY) | |
58 | + private UUID entityId; | |
59 | + | |
60 | + @PartitionKey(value = 2) | |
61 | + @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY) | |
62 | + private UUID tenantId; | |
63 | + | |
64 | + @PartitionKey(value = 3) | |
65 | + @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY) | |
66 | + private UUID customerId; | |
67 | + | |
68 | + @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY) | |
69 | + private String name; | |
70 | + | |
71 | + @Type(type = "json") | |
72 | + @Column(name = ModelConstants.ENTITY_VIEW_KEYS_PROPERTY) | |
73 | + private JsonNode keys; | |
74 | + | |
75 | + @Column(name = ModelConstants.ENTITY_VIEW_TS_BEGIN_PROPERTY) | |
76 | + private String tsBegin; | |
77 | + | |
78 | + @Column(name = ModelConstants.ENTITY_VIEW_TS_END_PROPERTY) | |
79 | + private String tsEnd; | |
80 | + | |
81 | + @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) | |
82 | + private String searchText; | |
83 | + | |
84 | + @Type(type = "json") | |
85 | + @Column(name = ModelConstants.ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY) | |
86 | + private JsonNode additionalInfo; | |
87 | + | |
88 | + public EntityViewEntity() { | |
89 | + super(); | |
90 | + } | |
91 | + | |
92 | + public EntityViewEntity(EntityView entityView) { | |
93 | + if (entityView.getId() != null) { | |
94 | + this.id = entityView.getId().getId(); | |
95 | + } | |
96 | + if (entityView.getEntityId() != null) { | |
97 | + this.entityId = entityView.getEntityId().getId(); | |
98 | + } | |
99 | + if (entityView.getTenantId() != null) { | |
100 | + this.tenantId = entityView.getTenantId().getId(); | |
101 | + } | |
102 | + if (entityView.getCustomerId() != null) { | |
103 | + this.customerId = entityView.getCustomerId().getId(); | |
104 | + } | |
105 | + 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"; | |
113 | + this.searchText = entityView.getSearchText(); | |
114 | + this.additionalInfo = entityView.getAdditionalInfo(); | |
115 | + } | |
116 | + | |
117 | + @Override | |
118 | + public String getSearchTextSource() { | |
119 | + return name; | |
120 | + } | |
121 | + | |
122 | + @Override | |
123 | + public EntityView toData() { | |
124 | + EntityView entityView = new EntityView(new EntityViewId(id)); | |
125 | + entityView.setCreatedTime(UUIDs.unixTimestamp(id)); | |
126 | + if (entityId != null) { | |
127 | + entityView.setEntityId(new DeviceId(entityId)); | |
128 | + } | |
129 | + if (tenantId != null) { | |
130 | + entityView.setTenantId(new TenantId(tenantId)); | |
131 | + } | |
132 | + if (customerId != null) { | |
133 | + entityView.setCustomerId(new CustomerId(customerId)); | |
134 | + } | |
135 | + 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)); | |
143 | + entityView.setAdditionalInfo(additionalInfo); | |
144 | + return entityView; | |
145 | + } | |
146 | +} | ... | ... |
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.model.sql; | |
17 | + | |
18 | +import com.datastax.driver.core.utils.UUIDs; | |
19 | +import com.fasterxml.jackson.databind.JsonNode; | |
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
21 | +import lombok.Data; | |
22 | +import lombok.EqualsAndHashCode; | |
23 | +import org.hibernate.annotations.Type; | |
24 | +import org.hibernate.annotations.TypeDef; | |
25 | +import org.thingsboard.server.common.data.EntityType; | |
26 | +import org.thingsboard.server.common.data.EntityView; | |
27 | +import org.thingsboard.server.common.data.id.*; | |
28 | +import org.thingsboard.server.common.data.objects.TelemetryEntityView; | |
29 | +import org.thingsboard.server.dao.model.BaseSqlEntity; | |
30 | +import org.thingsboard.server.dao.model.ModelConstants; | |
31 | +import org.thingsboard.server.dao.model.SearchTextEntity; | |
32 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | |
33 | + | |
34 | +import javax.persistence.*; | |
35 | +import java.io.IOException; | |
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; | |
39 | + | |
40 | +/** | |
41 | + * Created by Victor Basanets on 8/30/2017. | |
42 | + */ | |
43 | + | |
44 | +@Data | |
45 | +@EqualsAndHashCode(callSuper = true) | |
46 | +@Entity | |
47 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | |
48 | +@Table(name = ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME) | |
49 | +public class EntityViewEntity extends BaseSqlEntity<EntityView> implements SearchTextEntity<EntityView> { | |
50 | + | |
51 | + @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY) | |
52 | + private String entityId; | |
53 | + | |
54 | + @Enumerated(EnumType.STRING) | |
55 | + @Column(name = ENTITY_TYPE_PROPERTY) | |
56 | + private EntityType entityType; | |
57 | + | |
58 | + @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY) | |
59 | + private String tenantId; | |
60 | + | |
61 | + @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY) | |
62 | + private String customerId; | |
63 | + | |
64 | + @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY) | |
65 | + private String name; | |
66 | + | |
67 | + @Column(name = ModelConstants.ENTITY_VIEW_KEYS_PROPERTY) | |
68 | + private String keys; | |
69 | + | |
70 | + @Column(name = ModelConstants.ENTITY_VIEW_TS_BEGIN_PROPERTY) | |
71 | + private String tsBegin; | |
72 | + | |
73 | + @Column(name = ModelConstants.ENTITY_VIEW_TS_END_PROPERTY) | |
74 | + private String tsEnd; | |
75 | + | |
76 | + @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) | |
77 | + private String searchText; | |
78 | + | |
79 | + @Type(type = "json") | |
80 | + @Column(name = ModelConstants.ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY) | |
81 | + private JsonNode additionalInfo; | |
82 | + | |
83 | + private static final ObjectMapper mapper = new ObjectMapper(); | |
84 | + | |
85 | + public EntityViewEntity() { | |
86 | + super(); | |
87 | + } | |
88 | + | |
89 | + public EntityViewEntity(EntityView entityView) { | |
90 | + if (entityView.getId() != null) { | |
91 | + this.setId(entityView.getId().getId()); | |
92 | + } | |
93 | + if (entityView.getEntityId() != null) { | |
94 | + this.entityId = toString(entityView.getEntityId().getId()); | |
95 | + this.entityType = entityView.getEntityId().getEntityType(); | |
96 | + } | |
97 | + if (entityView.getTenantId() != null) { | |
98 | + this.tenantId = toString(entityView.getTenantId().getId()); | |
99 | + } | |
100 | + if (entityView.getCustomerId() != null) { | |
101 | + this.customerId = toString(entityView.getCustomerId().getId()); | |
102 | + } | |
103 | + this.name = entityView.getName(); | |
104 | + try { | |
105 | + this.keys = mapper.writeValueAsString(entityView.getKeys()); | |
106 | + } catch (IOException e) { | |
107 | + e.printStackTrace(); | |
108 | + } | |
109 | + this.tsBegin = entityView.getTsBegin() != null ? String.valueOf(entityView.getTsBegin()) : "0"; | |
110 | + this.tsEnd = entityView.getTsEnd() != null ? String.valueOf(entityView.getTsEnd()) : "0"; | |
111 | + this.searchText = entityView.getSearchText(); | |
112 | + this.additionalInfo = entityView.getAdditionalInfo(); | |
113 | + } | |
114 | + | |
115 | + @Override | |
116 | + public String getSearchTextSource() { | |
117 | + return name; | |
118 | + } | |
119 | + | |
120 | + @Override | |
121 | + public void setSearchText(String searchText) { | |
122 | + this.searchText = searchText; | |
123 | + } | |
124 | + | |
125 | + @Override | |
126 | + public EntityView toData() { | |
127 | + EntityView entityView = new EntityView(new EntityViewId(getId())); | |
128 | + entityView.setCreatedTime(UUIDs.unixTimestamp(getId())); | |
129 | + | |
130 | + if (entityId != null) { | |
131 | + entityView.setEntityId(EntityIdFactory.getByTypeAndId(entityType.name(), toUUID(entityId).toString())); | |
132 | + } | |
133 | + if (tenantId != null) { | |
134 | + entityView.setTenantId(new TenantId(toUUID(tenantId))); | |
135 | + } | |
136 | + if (customerId != null) { | |
137 | + entityView.setCustomerId(new CustomerId(toUUID(customerId))); | |
138 | + } | |
139 | + entityView.setName(name); | |
140 | + try { | |
141 | + entityView.setKeys(mapper.readValue(keys, TelemetryEntityView.class)); | |
142 | + } catch (IOException e) { | |
143 | + e.printStackTrace(); | |
144 | + } | |
145 | + entityView.setTsBegin(Long.parseLong(tsBegin)); | |
146 | + entityView.setTsEnd(Long.parseLong(tsEnd)); | |
147 | + entityView.setAdditionalInfo(additionalInfo); | |
148 | + return entityView; | |
149 | + } | |
150 | +} | ... | ... |
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.sql.entityview; | |
17 | + | |
18 | +import org.springframework.data.domain.Pageable; | |
19 | +import org.springframework.data.jpa.repository.Query; | |
20 | +import org.springframework.data.repository.CrudRepository; | |
21 | +import org.springframework.data.repository.query.Param; | |
22 | +import org.thingsboard.server.common.data.id.EntityId; | |
23 | +import org.thingsboard.server.dao.model.sql.EntityViewEntity; | |
24 | +import org.thingsboard.server.dao.util.SqlDao; | |
25 | + | |
26 | +import java.util.List; | |
27 | + | |
28 | +/** | |
29 | + * Created by Victor Basanets on 8/31/2017. | |
30 | + */ | |
31 | +@SqlDao | |
32 | +public interface EntityViewRepository extends CrudRepository<EntityViewEntity, String> { | |
33 | + | |
34 | + @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + | |
35 | + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " + | |
36 | + "AND e.id > :idOffset ORDER BY e.id") | |
37 | + List<EntityViewEntity> findByTenantId(@Param("tenantId") String tenantId, | |
38 | + @Param("textSearch") String textSearch, | |
39 | + @Param("idOffset") String idOffset, | |
40 | + Pageable pageable); | |
41 | + | |
42 | + @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + | |
43 | + "AND e.entityId = :entityId " + | |
44 | + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " + | |
45 | + "AND e.id > :idOffset ORDER BY e.id") | |
46 | + List<EntityViewEntity> findByTenantIdAndEntityId(@Param("tenantId") String tenantId, | |
47 | + @Param("entityId") String entityId, | |
48 | + @Param("textSearch") String textSearch, | |
49 | + @Param("idOffset") String idOffset, | |
50 | + Pageable pageable); | |
51 | + | |
52 | + @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + | |
53 | + "AND e.customerId = :customerId " + | |
54 | + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " + | |
55 | + "AND e.id > :idOffset ORDER BY e.id") | |
56 | + List<EntityViewEntity> findByTenantIdAndCustomerId(@Param("tenantId") String tenantId, | |
57 | + @Param("customerId") String customerId, | |
58 | + @Param("searchText") String searchText, | |
59 | + @Param("idOffset") String idOffset, | |
60 | + Pageable pageable); | |
61 | + | |
62 | + @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + | |
63 | + "AND e.customerId = :customerId " + | |
64 | + "AND e.entityId = :entityId " + | |
65 | + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " + | |
66 | + "AND e.id > :idOffset ORDER BY e.id") | |
67 | + List<EntityViewEntity> findByTenantIdAndCustomerIdAndEntityId(@Param("tenantId") String tenantId, | |
68 | + @Param("customerId") String customerId, | |
69 | + @Param("entityId") String entityId, | |
70 | + @Param("textSearch") String textSearch, | |
71 | + @Param("idOffset") String idOffset, | |
72 | + Pageable pageable); | |
73 | + | |
74 | + EntityViewEntity findByTenantIdAndName(String tenantId, String name); | |
75 | + | |
76 | + List<EntityViewEntity> findAllByTenantIdAndCustomerIdAndIdIn(String tenantId, | |
77 | + String customerId, | |
78 | + List<String> entityViewsIds); | |
79 | + | |
80 | + List<EntityViewEntity> findAllByTenantIdAndIdIn(String tenantId, List<String> entityViewsIds); | |
81 | +} | ... | ... |
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.sql.entityview; | |
17 | + | |
18 | +import org.springframework.beans.factory.annotation.Autowired; | |
19 | +import org.springframework.data.domain.PageRequest; | |
20 | +import org.springframework.data.repository.CrudRepository; | |
21 | +import org.springframework.stereotype.Component; | |
22 | +import org.thingsboard.server.common.data.EntityView; | |
23 | +import org.thingsboard.server.common.data.id.EntityId; | |
24 | +import org.thingsboard.server.common.data.page.TextPageLink; | |
25 | +import org.thingsboard.server.dao.DaoUtil; | |
26 | +import org.thingsboard.server.dao.entityview.EntityViewDao; | |
27 | +import org.thingsboard.server.dao.model.sql.EntityViewEntity; | |
28 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | |
29 | +import org.thingsboard.server.dao.util.SqlDao; | |
30 | + | |
31 | +import java.util.List; | |
32 | +import java.util.Objects; | |
33 | +import java.util.Optional; | |
34 | +import java.util.UUID; | |
35 | + | |
36 | +import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; | |
37 | +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR; | |
38 | + | |
39 | +/** | |
40 | + * Created by Victor Basanets on 8/31/2017. | |
41 | + */ | |
42 | +@Component | |
43 | +@SqlDao | |
44 | +public class JpaEntityViewDao extends JpaAbstractSearchTextDao<EntityViewEntity, EntityView> | |
45 | + implements EntityViewDao { | |
46 | + | |
47 | + @Autowired | |
48 | + EntityViewRepository entityViewRepository; | |
49 | + | |
50 | + @Override | |
51 | + protected Class<EntityViewEntity> getEntityClass() { | |
52 | + return EntityViewEntity.class; | |
53 | + } | |
54 | + | |
55 | + @Override | |
56 | + protected CrudRepository<EntityViewEntity, String> getCrudRepository() { | |
57 | + return entityViewRepository; | |
58 | + } | |
59 | + | |
60 | + @Override | |
61 | + public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) { | |
62 | + return DaoUtil.convertDataList( | |
63 | + entityViewRepository.findByTenantId( | |
64 | + fromTimeUUID(tenantId), | |
65 | + Objects.toString(pageLink.getTextSearch(), ""), | |
66 | + pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()), | |
67 | + new PageRequest(0, pageLink.getLimit()))); | |
68 | + } | |
69 | + | |
70 | + @Override | |
71 | + public Optional<EntityView> findEntityViewByTenantIdAndName(UUID tenantId, String name) { | |
72 | + return Optional.ofNullable( | |
73 | + DaoUtil.getData(entityViewRepository.findByTenantIdAndName(fromTimeUUID(tenantId), name))); | |
74 | + } | |
75 | + | |
76 | + @Override | |
77 | + public List<EntityView> findEntityViewByTenantIdAndEntityId(UUID tenantId, | |
78 | + UUID entityId, | |
79 | + TextPageLink pageLink) { | |
80 | + return DaoUtil.convertDataList( | |
81 | + entityViewRepository.findByTenantIdAndEntityId( | |
82 | + fromTimeUUID(tenantId), | |
83 | + fromTimeUUID(entityId), | |
84 | + Objects.toString(pageLink.getTextSearch(), ""), | |
85 | + pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()), | |
86 | + new PageRequest(0, pageLink.getLimit()))); | |
87 | + } | |
88 | + | |
89 | + @Override | |
90 | + public List<EntityView> findEntityViewsByTenantIdAndCustomerId(UUID tenantId, | |
91 | + UUID customerId, | |
92 | + TextPageLink pageLink) { | |
93 | + return DaoUtil.convertDataList( | |
94 | + entityViewRepository.findByTenantIdAndCustomerId( | |
95 | + fromTimeUUID(tenantId), | |
96 | + fromTimeUUID(customerId), | |
97 | + Objects.toString(pageLink, ""), | |
98 | + pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()), | |
99 | + new PageRequest(0, pageLink.getLimit()) | |
100 | + )); | |
101 | + } | |
102 | + | |
103 | + @Override | |
104 | + public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(UUID tenantId, | |
105 | + UUID customerId, | |
106 | + UUID entityId, | |
107 | + TextPageLink pageLink) { | |
108 | + return DaoUtil.convertDataList( | |
109 | + entityViewRepository.findByTenantIdAndCustomerIdAndEntityId( | |
110 | + fromTimeUUID(tenantId), | |
111 | + fromTimeUUID(customerId), | |
112 | + fromTimeUUID(entityId), | |
113 | + Objects.toString(pageLink, ""), | |
114 | + pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()), | |
115 | + new PageRequest(0, pageLink.getLimit()) | |
116 | + )); | |
117 | + } | |
118 | +} | ... | ... |
... | ... | @@ -638,3 +638,45 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( |
638 | 638 | additional_info text, |
639 | 639 | PRIMARY KEY (id) |
640 | 640 | ); |
641 | + | |
642 | +CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( | |
643 | + id timeuuid, | |
644 | + entity_id timeuuid, | |
645 | + tenant_id timeuuid, | |
646 | + customer_id timeuuid, | |
647 | + name text, | |
648 | + keys text, | |
649 | + ts_begin bigint, | |
650 | + ts_end bigint, | |
651 | + search_text text, | |
652 | + additional_info text, | |
653 | + PRIMARY KEY (id, entity_id, tenant_id, customer_id) | |
654 | +); | |
655 | + | |
656 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS | |
657 | + SELECT * | |
658 | + from thingsboard.entity_views | |
659 | + WHERE entity_id IS NOT NULL AND tenant_id IS NOT NULL AND customer_id IS NOT NULL AND keys IS NOT NULL AND ts_begin IS NOT NULL AND ts_end IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | |
660 | + PRIMARY KEY (tenant_id, name, id, entity_id, customer_id) | |
661 | + WITH CLUSTERING ORDER BY (name ASC, id DESC, entity_id DESC, customer_id DESC); | |
662 | + | |
663 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_entity AS | |
664 | + SELECT * | |
665 | + from thingsboard.entity_views | |
666 | + WHERE entity_id IS NOT NULL AND tenant_id IS NOT NULL AND customer_id IS NOT NULL AND keys IS NOT NULL AND ts_begin IS NOT NULL AND ts_end IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | |
667 | + PRIMARY KEY (tenant_id, entity_id, id, customer_id, name) | |
668 | + WITH CLUSTERING ORDER BY (entity_id ASC, customer_id ASC, id DESC, name DESC); | |
669 | + | |
670 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_customer AS | |
671 | + SELECT * | |
672 | + from thingsboard.entity_views | |
673 | + WHERE entity_id IS NOT NULL AND tenant_id IS NOT NULL AND customer_id IS NOT NULL AND keys IS NOT NULL AND ts_begin IS NOT NULL AND ts_end IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | |
674 | + PRIMARY KEY (tenant_id, customer_id, id, entity_id, name) | |
675 | + WITH CLUSTERING ORDER BY (customer_id ASC, id DESC, entity_id DESC, name DESC); | |
676 | + | |
677 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_customer_and_entity AS | |
678 | + SELECT * | |
679 | + from thingsboard.entity_views | |
680 | + WHERE entity_id IS NOT NULL AND tenant_id IS NOT NULL AND customer_id IS NOT NULL AND keys IS NOT NULL AND ts_begin IS NOT NULL AND ts_end IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | |
681 | + PRIMARY KEY (tenant_id, customer_id, entity_id, id, name) | |
682 | + WITH CLUSTERING ORDER BY (customer_id ASC, entity_id DESC, id DESC, name DESC); | ... | ... |
... | ... | @@ -251,3 +251,17 @@ CREATE TABLE IF NOT EXISTS rule_node ( |
251 | 251 | debug_mode boolean, |
252 | 252 | search_text varchar(255) |
253 | 253 | ); |
254 | + | |
255 | +CREATE TABLE IF NOT EXISTS entity_views ( | |
256 | + id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, | |
257 | + entity_id varchar(31), | |
258 | + entity_type varchar(255), | |
259 | + tenant_id varchar(31), | |
260 | + customer_id varchar(31), | |
261 | + name varchar(255), | |
262 | + keys varchar(255), | |
263 | + ts_begin varchar(255), | |
264 | + ts_end varchar(255), | |
265 | + search_text varchar(255), | |
266 | + additional_info varchar | |
267 | +); | ... | ... |
... | ... | @@ -18,4 +18,5 @@ DROP TABLE IF EXISTS user_credentials; |
18 | 18 | DROP TABLE IF EXISTS widget_type; |
19 | 19 | DROP TABLE IF EXISTS widgets_bundle; |
20 | 20 | DROP TABLE IF EXISTS rule_node; |
21 | -DROP TABLE IF EXISTS rule_chain; | |
\ No newline at end of file | ||
21 | +DROP TABLE IF EXISTS rule_chain; | |
22 | +DROP TABLE IF EXISTS entity_views; | |
\ No newline at end of file | ... | ... |