Commit b0b6ee06bdeb0d7b6c5f1f6c6825b36540d97123

Authored by VoBa
Committed by GitHub
2 parents 40017c46 8ecd9628

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 }
... ...
... ... @@ -359,7 +359,7 @@ spring:
359 359 password: "${SPRING_DATASOURCE_PASSWORD:}"
360 360
361 361 # PostgreSQL DAO Configuration
362   -#spring:
  362 +# spring:
363 363 # data:
364 364 # sql:
365 365 # repositories:
... ...
  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
... ...
  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 +}
... ...
  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 +}
... ...
  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 +}
... ...
  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
... ...