Commit bdc048c54833351ae5d7d0529947cb2fd16b5cae

Authored by volodymyr-babak
2 parents e5d664b4 e3976b31

Merge remote-tracking branch 'upstream/master' into feature/mqtt-plugin

Showing 64 changed files with 3225 additions and 253 deletions

Too many changes to show.

To preserve performance only 64 of 169 files are displayed.

@@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; @@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.asset.Asset; 23 import org.thingsboard.server.common.data.asset.Asset;
  24 +import org.thingsboard.server.common.data.asset.TenantAssetType;
24 import org.thingsboard.server.common.data.id.AssetId; 25 import org.thingsboard.server.common.data.id.AssetId;
25 import org.thingsboard.server.common.data.id.CustomerId; 26 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
@@ -136,13 +137,18 @@ public class AssetController extends BaseController { @@ -136,13 +137,18 @@ public class AssetController extends BaseController {
136 @ResponseBody 137 @ResponseBody
137 public TextPageData<Asset> getTenantAssets( 138 public TextPageData<Asset> getTenantAssets(
138 @RequestParam int limit, 139 @RequestParam int limit,
  140 + @RequestParam(required = false) String type,
139 @RequestParam(required = false) String textSearch, 141 @RequestParam(required = false) String textSearch,
140 @RequestParam(required = false) String idOffset, 142 @RequestParam(required = false) String idOffset,
141 @RequestParam(required = false) String textOffset) throws ThingsboardException { 143 @RequestParam(required = false) String textOffset) throws ThingsboardException {
142 try { 144 try {
143 TenantId tenantId = getCurrentUser().getTenantId(); 145 TenantId tenantId = getCurrentUser().getTenantId();
144 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); 146 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
145 - return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink)); 147 + if (type != null && type.trim().length()>0) {
  148 + return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink));
  149 + } else {
  150 + return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink));
  151 + }
146 } catch (Exception e) { 152 } catch (Exception e) {
147 throw handleException(e); 153 throw handleException(e);
148 } 154 }
@@ -167,6 +173,7 @@ public class AssetController extends BaseController { @@ -167,6 +173,7 @@ public class AssetController extends BaseController {
167 public TextPageData<Asset> getCustomerAssets( 173 public TextPageData<Asset> getCustomerAssets(
168 @PathVariable("customerId") String strCustomerId, 174 @PathVariable("customerId") String strCustomerId,
169 @RequestParam int limit, 175 @RequestParam int limit,
  176 + @RequestParam(required = false) String type,
170 @RequestParam(required = false) String textSearch, 177 @RequestParam(required = false) String textSearch,
171 @RequestParam(required = false) String idOffset, 178 @RequestParam(required = false) String idOffset,
172 @RequestParam(required = false) String textOffset) throws ThingsboardException { 179 @RequestParam(required = false) String textOffset) throws ThingsboardException {
@@ -176,7 +183,11 @@ public class AssetController extends BaseController { @@ -176,7 +183,11 @@ public class AssetController extends BaseController {
176 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 183 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
177 checkCustomerId(customerId); 184 checkCustomerId(customerId);
178 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); 185 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
179 - return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); 186 + if (type != null && type.trim().length()>0) {
  187 + return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
  188 + } else {
  189 + return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
  190 + }
180 } catch (Exception e) { 191 } catch (Exception e) {
181 throw handleException(e); 192 throw handleException(e);
182 } 193 }
@@ -231,4 +242,18 @@ public class AssetController extends BaseController { @@ -231,4 +242,18 @@ public class AssetController extends BaseController {
231 throw handleException(e); 242 throw handleException(e);
232 } 243 }
233 } 244 }
  245 +
  246 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  247 + @RequestMapping(value = "/asset/types", method = RequestMethod.GET)
  248 + @ResponseBody
  249 + public List<TenantAssetType> getAssetTypes() throws ThingsboardException {
  250 + try {
  251 + SecurityUser user = getCurrentUser();
  252 + TenantId tenantId = user.getTenantId();
  253 + ListenableFuture<List<TenantAssetType>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
  254 + return checkNotNull(assetTypes.get());
  255 + } catch (Exception e) {
  256 + throw handleException(e);
  257 + }
  258 + }
234 } 259 }
@@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; @@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
  24 +import org.thingsboard.server.common.data.TenantDeviceType;
24 import org.thingsboard.server.common.data.id.CustomerId; 25 import org.thingsboard.server.common.data.id.CustomerId;
25 import org.thingsboard.server.common.data.id.DeviceId; 26 import org.thingsboard.server.common.data.id.DeviceId;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
@@ -166,13 +167,18 @@ public class DeviceController extends BaseController { @@ -166,13 +167,18 @@ public class DeviceController extends BaseController {
166 @ResponseBody 167 @ResponseBody
167 public TextPageData<Device> getTenantDevices( 168 public TextPageData<Device> getTenantDevices(
168 @RequestParam int limit, 169 @RequestParam int limit,
  170 + @RequestParam(required = false) String type,
169 @RequestParam(required = false) String textSearch, 171 @RequestParam(required = false) String textSearch,
170 @RequestParam(required = false) String idOffset, 172 @RequestParam(required = false) String idOffset,
171 @RequestParam(required = false) String textOffset) throws ThingsboardException { 173 @RequestParam(required = false) String textOffset) throws ThingsboardException {
172 try { 174 try {
173 TenantId tenantId = getCurrentUser().getTenantId(); 175 TenantId tenantId = getCurrentUser().getTenantId();
174 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); 176 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
175 - return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink)); 177 + if (type != null && type.trim().length()>0) {
  178 + return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink));
  179 + } else {
  180 + return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink));
  181 + }
176 } catch (Exception e) { 182 } catch (Exception e) {
177 throw handleException(e); 183 throw handleException(e);
178 } 184 }
@@ -197,6 +203,7 @@ public class DeviceController extends BaseController { @@ -197,6 +203,7 @@ public class DeviceController extends BaseController {
197 public TextPageData<Device> getCustomerDevices( 203 public TextPageData<Device> getCustomerDevices(
198 @PathVariable("customerId") String strCustomerId, 204 @PathVariable("customerId") String strCustomerId,
199 @RequestParam int limit, 205 @RequestParam int limit,
  206 + @RequestParam(required = false) String type,
200 @RequestParam(required = false) String textSearch, 207 @RequestParam(required = false) String textSearch,
201 @RequestParam(required = false) String idOffset, 208 @RequestParam(required = false) String idOffset,
202 @RequestParam(required = false) String textOffset) throws ThingsboardException { 209 @RequestParam(required = false) String textOffset) throws ThingsboardException {
@@ -206,7 +213,11 @@ public class DeviceController extends BaseController { @@ -206,7 +213,11 @@ public class DeviceController extends BaseController {
206 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 213 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
207 checkCustomerId(customerId); 214 checkCustomerId(customerId);
208 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); 215 TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
209 - return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink)); 216 + if (type != null && type.trim().length()>0) {
  217 + return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
  218 + } else {
  219 + return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink));
  220 + }
210 } catch (Exception e) { 221 } catch (Exception e) {
211 throw handleException(e); 222 throw handleException(e);
212 } 223 }
@@ -261,4 +272,19 @@ public class DeviceController extends BaseController { @@ -261,4 +272,19 @@ public class DeviceController extends BaseController {
261 throw handleException(e); 272 throw handleException(e);
262 } 273 }
263 } 274 }
  275 +
  276 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  277 + @RequestMapping(value = "/device/types", method = RequestMethod.GET)
  278 + @ResponseBody
  279 + public List<TenantDeviceType> getDeviceTypes() throws ThingsboardException {
  280 + try {
  281 + SecurityUser user = getCurrentUser();
  282 + TenantId tenantId = user.getTenantId();
  283 + ListenableFuture<List<TenantDeviceType>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
  284 + return checkNotNull(deviceTypes.get());
  285 + } catch (Exception e) {
  286 + throw handleException(e);
  287 + }
  288 + }
  289 +
264 } 290 }
@@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*; @@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
21 import org.thingsboard.server.common.data.id.EntityId; 21 import org.thingsboard.server.common.data.id.EntityId;
22 import org.thingsboard.server.common.data.id.EntityIdFactory; 22 import org.thingsboard.server.common.data.id.EntityIdFactory;
23 import org.thingsboard.server.common.data.relation.EntityRelation; 23 import org.thingsboard.server.common.data.relation.EntityRelation;
  24 +import org.thingsboard.server.common.data.relation.EntityRelationInfo;
24 import org.thingsboard.server.dao.relation.EntityRelationsQuery; 25 import org.thingsboard.server.dao.relation.EntityRelationsQuery;
25 import org.thingsboard.server.exception.ThingsboardErrorCode; 26 import org.thingsboard.server.exception.ThingsboardErrorCode;
26 import org.thingsboard.server.exception.ThingsboardException; 27 import org.thingsboard.server.exception.ThingsboardException;
@@ -128,6 +129,21 @@ public class EntityRelationController extends BaseController { @@ -128,6 +129,21 @@ public class EntityRelationController extends BaseController {
128 } 129 }
129 130
130 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 131 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  132 + @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {"fromId", "fromType"})
  133 + @ResponseBody
  134 + public List<EntityRelationInfo> findInfoByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException {
  135 + checkParameter("fromId", strFromId);
  136 + checkParameter("fromType", strFromType);
  137 + EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
  138 + checkEntityId(entityId);
  139 + try {
  140 + return checkNotNull(relationService.findInfoByFrom(entityId).get());
  141 + } catch (Exception e) {
  142 + throw handleException(e);
  143 + }
  144 + }
  145 +
  146 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
131 @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType"}) 147 @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType"})
132 @ResponseBody 148 @ResponseBody
133 public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType 149 public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType
@@ -19,12 +19,18 @@ server: @@ -19,12 +19,18 @@ server:
19 address: "${HTTP_BIND_ADDRESS:0.0.0.0}" 19 address: "${HTTP_BIND_ADDRESS:0.0.0.0}"
20 # Server bind port 20 # Server bind port
21 port: "${HTTP_BIND_PORT:8080}" 21 port: "${HTTP_BIND_PORT:8080}"
22 -# Uncomment the following section to enable ssl  
23 -# ssl:  
24 -# key-store: classpath:keystore/keystore.p12  
25 -# key-store-password: thingsboard  
26 -# keyStoreType: PKCS12  
27 -# keyAlias: tomcat 22 + # Server SSL configuration
  23 + ssl:
  24 + # Enable/disable SSL support
  25 + enabled: "${SSL_ENABLED:false}"
  26 + # Path to the key store that holds the SSL certificate
  27 + key-store: "${SSL_KEY_STORE:classpath:keystore/keystore.p12}"
  28 + # Password used to access the key store
  29 + key-store-password: "${SSL_KEY_STORE_PASSWORD:thingsboard}"
  30 + # Type of the key store
  31 + key-store-type: "${SSL_KEY_STORE_TYPE:PKCS12}"
  32 + # Alias that identifies the key in the key store
  33 + key-alias: "${SSL_KEY_ALIAS:tomcat}"
28 34
29 # Zookeeper connection parameters. Used for service discovery. 35 # Zookeeper connection parameters. Used for service discovery.
30 zk: 36 zk:
@@ -79,12 +85,18 @@ mqtt: @@ -79,12 +85,18 @@ mqtt:
79 leak_detector_level: "${NETTY_LEASK_DETECTOR_LVL:DISABLED}" 85 leak_detector_level: "${NETTY_LEASK_DETECTOR_LVL:DISABLED}"
80 boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}" 86 boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}"
81 worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}" 87 worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}"
82 -# Uncomment the following lines to enable ssl for MQTT  
83 -# ssl:  
84 -# key_store: mqttserver.jks  
85 -# key_store_password: server_ks_password  
86 -# key_password: server_key_password  
87 -# key_store_type: JKS 88 + # MQTT SSL configuration
  89 + ssl:
  90 + # Enable/disable SSL support
  91 + enabled: "${MQTT_SSL_ENABLED:false}"
  92 + # Path to the key store that holds the SSL certificate
  93 + key_store: "${MQTT_SSL_KEY_STORE:mqttserver.jks}"
  94 + # Password used to access the key store
  95 + key_store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}"
  96 + # Password used to access the key
  97 + key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"
  98 + # Type of the key store
  99 + key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}"
88 100
89 # CoAP server parameters 101 # CoAP server parameters
90 coap: 102 coap:
@@ -98,13 +98,15 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC @@ -98,13 +98,15 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC
98 @IntegrationTest("server.port:0") 98 @IntegrationTest("server.port:0")
99 public abstract class AbstractControllerTest { 99 public abstract class AbstractControllerTest {
100 100
  101 + protected static final String TEST_TENANT_NAME = "TEST TENANT";
  102 +
101 protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; 103 protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org";
102 private static final String SYS_ADMIN_PASSWORD = "sysadmin"; 104 private static final String SYS_ADMIN_PASSWORD = "sysadmin";
103 105
104 - protected static final String TENANT_ADMIN_EMAIL = "tenant@thingsboard.org"; 106 + protected static final String TENANT_ADMIN_EMAIL = "testtenant@thingsboard.org";
105 private static final String TENANT_ADMIN_PASSWORD = "tenant"; 107 private static final String TENANT_ADMIN_PASSWORD = "tenant";
106 108
107 - protected static final String CUSTOMER_USER_EMAIL = "customer@thingsboard.org"; 109 + protected static final String CUSTOMER_USER_EMAIL = "testcustomer@thingsboard.org";
108 private static final String CUSTOMER_USER_PASSWORD = "customer"; 110 private static final String CUSTOMER_USER_PASSWORD = "customer";
109 111
110 protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), 112 protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
@@ -147,7 +149,7 @@ public abstract class AbstractControllerTest { @@ -147,7 +149,7 @@ public abstract class AbstractControllerTest {
147 loginSysAdmin(); 149 loginSysAdmin();
148 150
149 Tenant tenant = new Tenant(); 151 Tenant tenant = new Tenant();
150 - tenant.setTitle("Tenant"); 152 + tenant.setTitle(TEST_TENANT_NAME);
151 Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); 153 Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class);
152 Assert.assertNotNull(savedTenant); 154 Assert.assertNotNull(savedTenant);
153 tenantId = savedTenant.getId(); 155 tenantId = savedTenant.getId();
  1 +/**
  2 + * Copyright © 2016-2017 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 static org.hamcrest.Matchers.containsString;
  19 +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
  20 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  21 +
  22 +import java.util.ArrayList;
  23 +import java.util.Collections;
  24 +import java.util.List;
  25 +
  26 +import org.apache.commons.lang3.RandomStringUtils;
  27 +import org.thingsboard.server.common.data.*;
  28 +import org.thingsboard.server.common.data.asset.Asset;
  29 +import org.thingsboard.server.common.data.asset.TenantAssetType;
  30 +import org.thingsboard.server.common.data.id.CustomerId;
  31 +import org.thingsboard.server.common.data.id.AssetId;
  32 +import org.thingsboard.server.common.data.page.TextPageData;
  33 +import org.thingsboard.server.common.data.page.TextPageLink;
  34 +import org.thingsboard.server.common.data.security.Authority;
  35 +import org.thingsboard.server.dao.model.ModelConstants;
  36 +import org.junit.After;
  37 +import org.junit.Assert;
  38 +import org.junit.Before;
  39 +import org.junit.Test;
  40 +
  41 +import com.datastax.driver.core.utils.UUIDs;
  42 +import com.fasterxml.jackson.core.type.TypeReference;
  43 +
  44 +public class AssetControllerTest extends AbstractControllerTest {
  45 +
  46 + private IdComparator<Asset> idComparator = new IdComparator<>();
  47 +
  48 + private Tenant savedTenant;
  49 + private User tenantAdmin;
  50 +
  51 + @Before
  52 + public void beforeTest() throws Exception {
  53 + loginSysAdmin();
  54 +
  55 + Tenant tenant = new Tenant();
  56 + tenant.setTitle("My tenant");
  57 + savedTenant = doPost("/api/tenant", tenant, Tenant.class);
  58 + Assert.assertNotNull(savedTenant);
  59 +
  60 + tenantAdmin = new User();
  61 + tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
  62 + tenantAdmin.setTenantId(savedTenant.getId());
  63 + tenantAdmin.setEmail("tenant2@thingsboard.org");
  64 + tenantAdmin.setFirstName("Joe");
  65 + tenantAdmin.setLastName("Downs");
  66 +
  67 + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
  68 + }
  69 +
  70 + @After
  71 + public void afterTest() throws Exception {
  72 + loginSysAdmin();
  73 +
  74 + doDelete("/api/tenant/"+savedTenant.getId().getId().toString())
  75 + .andExpect(status().isOk());
  76 + }
  77 +
  78 + @Test
  79 + public void testSaveAsset() throws Exception {
  80 + Asset asset = new Asset();
  81 + asset.setName("My asset");
  82 + asset.setType("default");
  83 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  84 +
  85 + Assert.assertNotNull(savedAsset);
  86 + Assert.assertNotNull(savedAsset.getId());
  87 + Assert.assertTrue(savedAsset.getCreatedTime() > 0);
  88 + Assert.assertEquals(savedTenant.getId(), savedAsset.getTenantId());
  89 + Assert.assertNotNull(savedAsset.getCustomerId());
  90 + Assert.assertEquals(NULL_UUID, savedAsset.getCustomerId().getId());
  91 + Assert.assertEquals(asset.getName(), savedAsset.getName());
  92 +
  93 + savedAsset.setName("My new asset");
  94 + doPost("/api/asset", savedAsset, Asset.class);
  95 +
  96 + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  97 + Assert.assertEquals(foundAsset.getName(), savedAsset.getName());
  98 + }
  99 +
  100 + @Test
  101 + public void testFindAssetById() throws Exception {
  102 + Asset asset = new Asset();
  103 + asset.setName("My asset");
  104 + asset.setType("default");
  105 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  106 + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  107 + Assert.assertNotNull(foundAsset);
  108 + Assert.assertEquals(savedAsset, foundAsset);
  109 + }
  110 +
  111 + @Test
  112 + public void testFindAssetTypesByTenantId() throws Exception {
  113 + List<Asset> assets = new ArrayList<>();
  114 + for (int i=0;i<3;i++) {
  115 + Asset asset = new Asset();
  116 + asset.setName("My asset B"+i);
  117 + asset.setType("typeB");
  118 + assets.add(doPost("/api/asset", asset, Asset.class));
  119 + }
  120 + for (int i=0;i<7;i++) {
  121 + Asset asset = new Asset();
  122 + asset.setName("My asset C"+i);
  123 + asset.setType("typeC");
  124 + assets.add(doPost("/api/asset", asset, Asset.class));
  125 + }
  126 + for (int i=0;i<9;i++) {
  127 + Asset asset = new Asset();
  128 + asset.setName("My asset A"+i);
  129 + asset.setType("typeA");
  130 + assets.add(doPost("/api/asset", asset, Asset.class));
  131 + }
  132 + List<TenantAssetType> assetTypes = doGetTyped("/api/asset/types",
  133 + new TypeReference<List<TenantAssetType>>(){});
  134 +
  135 + Assert.assertNotNull(assetTypes);
  136 + Assert.assertEquals(3, assetTypes.size());
  137 + Assert.assertEquals("typeA", assetTypes.get(0).getType());
  138 + Assert.assertEquals("typeB", assetTypes.get(1).getType());
  139 + Assert.assertEquals("typeC", assetTypes.get(2).getType());
  140 + }
  141 +
  142 + @Test
  143 + public void testDeleteAsset() throws Exception {
  144 + Asset asset = new Asset();
  145 + asset.setName("My asset");
  146 + asset.setType("default");
  147 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  148 +
  149 + doDelete("/api/asset/"+savedAsset.getId().getId().toString())
  150 + .andExpect(status().isOk());
  151 +
  152 + doGet("/api/asset/"+savedAsset.getId().getId().toString())
  153 + .andExpect(status().isNotFound());
  154 + }
  155 +
  156 + @Test
  157 + public void testSaveAssetWithEmptyType() throws Exception {
  158 + Asset asset = new Asset();
  159 + asset.setName("My asset");
  160 + doPost("/api/asset", asset)
  161 + .andExpect(status().isBadRequest())
  162 + .andExpect(statusReason(containsString("Asset type should be specified")));
  163 + }
  164 +
  165 + @Test
  166 + public void testSaveAssetWithEmptyName() throws Exception {
  167 + Asset asset = new Asset();
  168 + asset.setType("default");
  169 + doPost("/api/asset", asset)
  170 + .andExpect(status().isBadRequest())
  171 + .andExpect(statusReason(containsString("Asset name should be specified")));
  172 + }
  173 +
  174 + @Test
  175 + public void testAssignUnassignAssetToCustomer() throws Exception {
  176 + Asset asset = new Asset();
  177 + asset.setName("My asset");
  178 + asset.setType("default");
  179 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  180 +
  181 + Customer customer = new Customer();
  182 + customer.setTitle("My customer");
  183 + Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
  184 +
  185 + Asset assignedAsset = doPost("/api/customer/" + savedCustomer.getId().getId().toString()
  186 + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  187 + Assert.assertEquals(savedCustomer.getId(), assignedAsset.getCustomerId());
  188 +
  189 + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  190 + Assert.assertEquals(savedCustomer.getId(), foundAsset.getCustomerId());
  191 +
  192 + Asset unassignedAsset =
  193 + doDelete("/api/customer/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  194 + Assert.assertEquals(ModelConstants.NULL_UUID, unassignedAsset.getCustomerId().getId());
  195 +
  196 + foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  197 + Assert.assertEquals(ModelConstants.NULL_UUID, foundAsset.getCustomerId().getId());
  198 + }
  199 +
  200 + @Test
  201 + public void testAssignAssetToNonExistentCustomer() throws Exception {
  202 + Asset asset = new Asset();
  203 + asset.setName("My asset");
  204 + asset.setType("default");
  205 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  206 +
  207 + doPost("/api/customer/" + UUIDs.timeBased().toString()
  208 + + "/asset/" + savedAsset.getId().getId().toString())
  209 + .andExpect(status().isNotFound());
  210 + }
  211 +
  212 + @Test
  213 + public void testAssignAssetToCustomerFromDifferentTenant() throws Exception {
  214 + loginSysAdmin();
  215 +
  216 + Tenant tenant2 = new Tenant();
  217 + tenant2.setTitle("Different tenant");
  218 + Tenant savedTenant2 = doPost("/api/tenant", tenant2, Tenant.class);
  219 + Assert.assertNotNull(savedTenant2);
  220 +
  221 + User tenantAdmin2 = new User();
  222 + tenantAdmin2.setAuthority(Authority.TENANT_ADMIN);
  223 + tenantAdmin2.setTenantId(savedTenant2.getId());
  224 + tenantAdmin2.setEmail("tenant3@thingsboard.org");
  225 + tenantAdmin2.setFirstName("Joe");
  226 + tenantAdmin2.setLastName("Downs");
  227 +
  228 + tenantAdmin2 = createUserAndLogin(tenantAdmin2, "testPassword1");
  229 +
  230 + Customer customer = new Customer();
  231 + customer.setTitle("Different customer");
  232 + Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
  233 +
  234 + login(tenantAdmin.getEmail(), "testPassword1");
  235 +
  236 + Asset asset = new Asset();
  237 + asset.setName("My asset");
  238 + asset.setType("default");
  239 + Asset savedAsset = doPost("/api/asset", asset, Asset.class);
  240 +
  241 + doPost("/api/customer/" + savedCustomer.getId().getId().toString()
  242 + + "/asset/" + savedAsset.getId().getId().toString())
  243 + .andExpect(status().isForbidden());
  244 +
  245 + loginSysAdmin();
  246 +
  247 + doDelete("/api/tenant/"+savedTenant2.getId().getId().toString())
  248 + .andExpect(status().isOk());
  249 + }
  250 +
  251 + @Test
  252 + public void testFindTenantAssets() throws Exception {
  253 + List<Asset> assets = new ArrayList<>();
  254 + for (int i=0;i<178;i++) {
  255 + Asset asset = new Asset();
  256 + asset.setName("Asset"+i);
  257 + asset.setType("default");
  258 + assets.add(doPost("/api/asset", asset, Asset.class));
  259 + }
  260 + List<Asset> loadedAssets = new ArrayList<>();
  261 + TextPageLink pageLink = new TextPageLink(23);
  262 + TextPageData<Asset> pageData = null;
  263 + do {
  264 + pageData = doGetTypedWithPageLink("/api/tenant/assets?",
  265 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  266 + loadedAssets.addAll(pageData.getData());
  267 + if (pageData.hasNext()) {
  268 + pageLink = pageData.getNextPageLink();
  269 + }
  270 + } while (pageData.hasNext());
  271 +
  272 + Collections.sort(assets, idComparator);
  273 + Collections.sort(loadedAssets, idComparator);
  274 +
  275 + Assert.assertEquals(assets, loadedAssets);
  276 + }
  277 +
  278 + @Test
  279 + public void testFindTenantAssetsByName() throws Exception {
  280 + String title1 = "Asset title 1";
  281 + List<Asset> assetsTitle1 = new ArrayList<>();
  282 + for (int i=0;i<143;i++) {
  283 + Asset asset = new Asset();
  284 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  285 + String name = title1+suffix;
  286 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  287 + asset.setName(name);
  288 + asset.setType("default");
  289 + assetsTitle1.add(doPost("/api/asset", asset, Asset.class));
  290 + }
  291 + String title2 = "Asset title 2";
  292 + List<Asset> assetsTitle2 = new ArrayList<>();
  293 + for (int i=0;i<75;i++) {
  294 + Asset asset = new Asset();
  295 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  296 + String name = title2+suffix;
  297 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  298 + asset.setName(name);
  299 + asset.setType("default");
  300 + assetsTitle2.add(doPost("/api/asset", asset, Asset.class));
  301 + }
  302 +
  303 + List<Asset> loadedAssetsTitle1 = new ArrayList<>();
  304 + TextPageLink pageLink = new TextPageLink(15, title1);
  305 + TextPageData<Asset> pageData = null;
  306 + do {
  307 + pageData = doGetTypedWithPageLink("/api/tenant/assets?",
  308 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  309 + loadedAssetsTitle1.addAll(pageData.getData());
  310 + if (pageData.hasNext()) {
  311 + pageLink = pageData.getNextPageLink();
  312 + }
  313 + } while (pageData.hasNext());
  314 +
  315 + Collections.sort(assetsTitle1, idComparator);
  316 + Collections.sort(loadedAssetsTitle1, idComparator);
  317 +
  318 + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
  319 +
  320 + List<Asset> loadedAssetsTitle2 = new ArrayList<>();
  321 + pageLink = new TextPageLink(4, title2);
  322 + do {
  323 + pageData = doGetTypedWithPageLink("/api/tenant/assets?",
  324 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  325 + loadedAssetsTitle2.addAll(pageData.getData());
  326 + if (pageData.hasNext()) {
  327 + pageLink = pageData.getNextPageLink();
  328 + }
  329 + } while (pageData.hasNext());
  330 +
  331 + Collections.sort(assetsTitle2, idComparator);
  332 + Collections.sort(loadedAssetsTitle2, idComparator);
  333 +
  334 + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
  335 +
  336 + for (Asset asset : loadedAssetsTitle1) {
  337 + doDelete("/api/asset/"+asset.getId().getId().toString())
  338 + .andExpect(status().isOk());
  339 + }
  340 +
  341 + pageLink = new TextPageLink(4, title1);
  342 + pageData = doGetTypedWithPageLink("/api/tenant/assets?",
  343 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  344 + Assert.assertFalse(pageData.hasNext());
  345 + Assert.assertEquals(0, pageData.getData().size());
  346 +
  347 + for (Asset asset : loadedAssetsTitle2) {
  348 + doDelete("/api/asset/"+asset.getId().getId().toString())
  349 + .andExpect(status().isOk());
  350 + }
  351 +
  352 + pageLink = new TextPageLink(4, title2);
  353 + pageData = doGetTypedWithPageLink("/api/tenant/assets?",
  354 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  355 + Assert.assertFalse(pageData.hasNext());
  356 + Assert.assertEquals(0, pageData.getData().size());
  357 + }
  358 +
  359 + @Test
  360 + public void testFindTenantAssetsByType() throws Exception {
  361 + String title1 = "Asset title 1";
  362 + String type1 = "typeA";
  363 + List<Asset> assetsType1 = new ArrayList<>();
  364 + for (int i=0;i<143;i++) {
  365 + Asset asset = new Asset();
  366 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  367 + String name = title1+suffix;
  368 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  369 + asset.setName(name);
  370 + asset.setType(type1);
  371 + assetsType1.add(doPost("/api/asset", asset, Asset.class));
  372 + }
  373 + String title2 = "Asset title 2";
  374 + String type2 = "typeB";
  375 + List<Asset> assetsType2 = new ArrayList<>();
  376 + for (int i=0;i<75;i++) {
  377 + Asset asset = new Asset();
  378 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  379 + String name = title2+suffix;
  380 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  381 + asset.setName(name);
  382 + asset.setType(type2);
  383 + assetsType2.add(doPost("/api/asset", asset, Asset.class));
  384 + }
  385 +
  386 + List<Asset> loadedAssetsType1 = new ArrayList<>();
  387 + TextPageLink pageLink = new TextPageLink(15);
  388 + TextPageData<Asset> pageData = null;
  389 + do {
  390 + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&",
  391 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1);
  392 + loadedAssetsType1.addAll(pageData.getData());
  393 + if (pageData.hasNext()) {
  394 + pageLink = pageData.getNextPageLink();
  395 + }
  396 + } while (pageData.hasNext());
  397 +
  398 + Collections.sort(assetsType1, idComparator);
  399 + Collections.sort(loadedAssetsType1, idComparator);
  400 +
  401 + Assert.assertEquals(assetsType1, loadedAssetsType1);
  402 +
  403 + List<Asset> loadedAssetsType2 = new ArrayList<>();
  404 + pageLink = new TextPageLink(4);
  405 + do {
  406 + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&",
  407 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2);
  408 + loadedAssetsType2.addAll(pageData.getData());
  409 + if (pageData.hasNext()) {
  410 + pageLink = pageData.getNextPageLink();
  411 + }
  412 + } while (pageData.hasNext());
  413 +
  414 + Collections.sort(assetsType2, idComparator);
  415 + Collections.sort(loadedAssetsType2, idComparator);
  416 +
  417 + Assert.assertEquals(assetsType2, loadedAssetsType2);
  418 +
  419 + for (Asset asset : loadedAssetsType1) {
  420 + doDelete("/api/asset/"+asset.getId().getId().toString())
  421 + .andExpect(status().isOk());
  422 + }
  423 +
  424 + pageLink = new TextPageLink(4);
  425 + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&",
  426 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1);
  427 + Assert.assertFalse(pageData.hasNext());
  428 + Assert.assertEquals(0, pageData.getData().size());
  429 +
  430 + for (Asset asset : loadedAssetsType2) {
  431 + doDelete("/api/asset/"+asset.getId().getId().toString())
  432 + .andExpect(status().isOk());
  433 + }
  434 +
  435 + pageLink = new TextPageLink(4);
  436 + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&",
  437 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2);
  438 + Assert.assertFalse(pageData.hasNext());
  439 + Assert.assertEquals(0, pageData.getData().size());
  440 + }
  441 +
  442 + @Test
  443 + public void testFindCustomerAssets() throws Exception {
  444 + Customer customer = new Customer();
  445 + customer.setTitle("Test customer");
  446 + customer = doPost("/api/customer", customer, Customer.class);
  447 + CustomerId customerId = customer.getId();
  448 +
  449 + List<Asset> assets = new ArrayList<>();
  450 + for (int i=0;i<128;i++) {
  451 + Asset asset = new Asset();
  452 + asset.setName("Asset"+i);
  453 + asset.setType("default");
  454 + asset = doPost("/api/asset", asset, Asset.class);
  455 + assets.add(doPost("/api/customer/" + customerId.getId().toString()
  456 + + "/asset/" + asset.getId().getId().toString(), Asset.class));
  457 + }
  458 +
  459 + List<Asset> loadedAssets = new ArrayList<>();
  460 + TextPageLink pageLink = new TextPageLink(23);
  461 + TextPageData<Asset> pageData = null;
  462 + do {
  463 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?",
  464 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  465 + loadedAssets.addAll(pageData.getData());
  466 + if (pageData.hasNext()) {
  467 + pageLink = pageData.getNextPageLink();
  468 + }
  469 + } while (pageData.hasNext());
  470 +
  471 + Collections.sort(assets, idComparator);
  472 + Collections.sort(loadedAssets, idComparator);
  473 +
  474 + Assert.assertEquals(assets, loadedAssets);
  475 + }
  476 +
  477 + @Test
  478 + public void testFindCustomerAssetsByName() throws Exception {
  479 + Customer customer = new Customer();
  480 + customer.setTitle("Test customer");
  481 + customer = doPost("/api/customer", customer, Customer.class);
  482 + CustomerId customerId = customer.getId();
  483 +
  484 + String title1 = "Asset title 1";
  485 + List<Asset> assetsTitle1 = new ArrayList<>();
  486 + for (int i=0;i<125;i++) {
  487 + Asset asset = new Asset();
  488 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  489 + String name = title1+suffix;
  490 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  491 + asset.setName(name);
  492 + asset.setType("default");
  493 + asset = doPost("/api/asset", asset, Asset.class);
  494 + assetsTitle1.add(doPost("/api/customer/" + customerId.getId().toString()
  495 + + "/asset/" + asset.getId().getId().toString(), Asset.class));
  496 + }
  497 + String title2 = "Asset title 2";
  498 + List<Asset> assetsTitle2 = new ArrayList<>();
  499 + for (int i=0;i<143;i++) {
  500 + Asset asset = new Asset();
  501 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  502 + String name = title2+suffix;
  503 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  504 + asset.setName(name);
  505 + asset.setType("default");
  506 + asset = doPost("/api/asset", asset, Asset.class);
  507 + assetsTitle2.add(doPost("/api/customer/" + customerId.getId().toString()
  508 + + "/asset/" + asset.getId().getId().toString(), Asset.class));
  509 + }
  510 +
  511 + List<Asset> loadedAssetsTitle1 = new ArrayList<>();
  512 + TextPageLink pageLink = new TextPageLink(15, title1);
  513 + TextPageData<Asset> pageData = null;
  514 + do {
  515 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?",
  516 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  517 + loadedAssetsTitle1.addAll(pageData.getData());
  518 + if (pageData.hasNext()) {
  519 + pageLink = pageData.getNextPageLink();
  520 + }
  521 + } while (pageData.hasNext());
  522 +
  523 + Collections.sort(assetsTitle1, idComparator);
  524 + Collections.sort(loadedAssetsTitle1, idComparator);
  525 +
  526 + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
  527 +
  528 + List<Asset> loadedAssetsTitle2 = new ArrayList<>();
  529 + pageLink = new TextPageLink(4, title2);
  530 + do {
  531 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?",
  532 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  533 + loadedAssetsTitle2.addAll(pageData.getData());
  534 + if (pageData.hasNext()) {
  535 + pageLink = pageData.getNextPageLink();
  536 + }
  537 + } while (pageData.hasNext());
  538 +
  539 + Collections.sort(assetsTitle2, idComparator);
  540 + Collections.sort(loadedAssetsTitle2, idComparator);
  541 +
  542 + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
  543 +
  544 + for (Asset asset : loadedAssetsTitle1) {
  545 + doDelete("/api/customer/asset/" + asset.getId().getId().toString())
  546 + .andExpect(status().isOk());
  547 + }
  548 +
  549 + pageLink = new TextPageLink(4, title1);
  550 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?",
  551 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  552 + Assert.assertFalse(pageData.hasNext());
  553 + Assert.assertEquals(0, pageData.getData().size());
  554 +
  555 + for (Asset asset : loadedAssetsTitle2) {
  556 + doDelete("/api/customer/asset/" + asset.getId().getId().toString())
  557 + .andExpect(status().isOk());
  558 + }
  559 +
  560 + pageLink = new TextPageLink(4, title2);
  561 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?",
  562 + new TypeReference<TextPageData<Asset>>(){}, pageLink);
  563 + Assert.assertFalse(pageData.hasNext());
  564 + Assert.assertEquals(0, pageData.getData().size());
  565 + }
  566 +
  567 + @Test
  568 + public void testFindCustomerAssetsByType() throws Exception {
  569 + Customer customer = new Customer();
  570 + customer.setTitle("Test customer");
  571 + customer = doPost("/api/customer", customer, Customer.class);
  572 + CustomerId customerId = customer.getId();
  573 +
  574 + String title1 = "Asset title 1";
  575 + String type1 = "typeC";
  576 + List<Asset> assetsType1 = new ArrayList<>();
  577 + for (int i=0;i<125;i++) {
  578 + Asset asset = new Asset();
  579 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  580 + String name = title1+suffix;
  581 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  582 + asset.setName(name);
  583 + asset.setType(type1);
  584 + asset = doPost("/api/asset", asset, Asset.class);
  585 + assetsType1.add(doPost("/api/customer/" + customerId.getId().toString()
  586 + + "/asset/" + asset.getId().getId().toString(), Asset.class));
  587 + }
  588 + String title2 = "Asset title 2";
  589 + String type2 = "typeD";
  590 + List<Asset> assetsType2 = new ArrayList<>();
  591 + for (int i=0;i<143;i++) {
  592 + Asset asset = new Asset();
  593 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  594 + String name = title2+suffix;
  595 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  596 + asset.setName(name);
  597 + asset.setType(type2);
  598 + asset = doPost("/api/asset", asset, Asset.class);
  599 + assetsType2.add(doPost("/api/customer/" + customerId.getId().toString()
  600 + + "/asset/" + asset.getId().getId().toString(), Asset.class));
  601 + }
  602 +
  603 + List<Asset> loadedAssetsType1 = new ArrayList<>();
  604 + TextPageLink pageLink = new TextPageLink(15);
  605 + TextPageData<Asset> pageData = null;
  606 + do {
  607 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&",
  608 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1);
  609 + loadedAssetsType1.addAll(pageData.getData());
  610 + if (pageData.hasNext()) {
  611 + pageLink = pageData.getNextPageLink();
  612 + }
  613 + } while (pageData.hasNext());
  614 +
  615 + Collections.sort(assetsType1, idComparator);
  616 + Collections.sort(loadedAssetsType1, idComparator);
  617 +
  618 + Assert.assertEquals(assetsType1, loadedAssetsType1);
  619 +
  620 + List<Asset> loadedAssetsType2 = new ArrayList<>();
  621 + pageLink = new TextPageLink(4);
  622 + do {
  623 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&",
  624 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2);
  625 + loadedAssetsType2.addAll(pageData.getData());
  626 + if (pageData.hasNext()) {
  627 + pageLink = pageData.getNextPageLink();
  628 + }
  629 + } while (pageData.hasNext());
  630 +
  631 + Collections.sort(assetsType2, idComparator);
  632 + Collections.sort(loadedAssetsType2, idComparator);
  633 +
  634 + Assert.assertEquals(assetsType2, loadedAssetsType2);
  635 +
  636 + for (Asset asset : loadedAssetsType1) {
  637 + doDelete("/api/customer/asset/" + asset.getId().getId().toString())
  638 + .andExpect(status().isOk());
  639 + }
  640 +
  641 + pageLink = new TextPageLink(4);
  642 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&",
  643 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1);
  644 + Assert.assertFalse(pageData.hasNext());
  645 + Assert.assertEquals(0, pageData.getData().size());
  646 +
  647 + for (Asset asset : loadedAssetsType2) {
  648 + doDelete("/api/customer/asset/" + asset.getId().getId().toString())
  649 + .andExpect(status().isOk());
  650 + }
  651 +
  652 + pageLink = new TextPageLink(4);
  653 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&",
  654 + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2);
  655 + Assert.assertFalse(pageData.hasNext());
  656 + Assert.assertEquals(0, pageData.getData().size());
  657 + }
  658 +
  659 +}
@@ -24,10 +24,7 @@ import java.util.Collections; @@ -24,10 +24,7 @@ import java.util.Collections;
24 import java.util.List; 24 import java.util.List;
25 25
26 import org.apache.commons.lang3.RandomStringUtils; 26 import org.apache.commons.lang3.RandomStringUtils;
27 -import org.thingsboard.server.common.data.Customer;  
28 -import org.thingsboard.server.common.data.Device;  
29 -import org.thingsboard.server.common.data.Tenant;  
30 -import org.thingsboard.server.common.data.User; 27 +import org.thingsboard.server.common.data.*;
31 import org.thingsboard.server.common.data.id.CustomerId; 28 import org.thingsboard.server.common.data.id.CustomerId;
32 import org.thingsboard.server.common.data.id.DeviceCredentialsId; 29 import org.thingsboard.server.common.data.id.DeviceCredentialsId;
33 import org.thingsboard.server.common.data.id.DeviceId; 30 import org.thingsboard.server.common.data.id.DeviceId;
@@ -83,6 +80,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -83,6 +80,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
83 public void testSaveDevice() throws Exception { 80 public void testSaveDevice() throws Exception {
84 Device device = new Device(); 81 Device device = new Device();
85 device.setName("My device"); 82 device.setName("My device");
  83 + device.setType("default");
86 Device savedDevice = doPost("/api/device", device, Device.class); 84 Device savedDevice = doPost("/api/device", device, Device.class);
87 85
88 Assert.assertNotNull(savedDevice); 86 Assert.assertNotNull(savedDevice);
@@ -114,16 +112,49 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -114,16 +112,49 @@ public class DeviceControllerTest extends AbstractControllerTest {
114 public void testFindDeviceById() throws Exception { 112 public void testFindDeviceById() throws Exception {
115 Device device = new Device(); 113 Device device = new Device();
116 device.setName("My device"); 114 device.setName("My device");
  115 + device.setType("default");
117 Device savedDevice = doPost("/api/device", device, Device.class); 116 Device savedDevice = doPost("/api/device", device, Device.class);
118 Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); 117 Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class);
119 Assert.assertNotNull(foundDevice); 118 Assert.assertNotNull(foundDevice);
120 Assert.assertEquals(savedDevice, foundDevice); 119 Assert.assertEquals(savedDevice, foundDevice);
121 } 120 }
  121 +
  122 + @Test
  123 + public void testFindDeviceTypesByTenantId() throws Exception {
  124 + List<Device> devices = new ArrayList<>();
  125 + for (int i=0;i<3;i++) {
  126 + Device device = new Device();
  127 + device.setName("My device B"+i);
  128 + device.setType("typeB");
  129 + devices.add(doPost("/api/device", device, Device.class));
  130 + }
  131 + for (int i=0;i<7;i++) {
  132 + Device device = new Device();
  133 + device.setName("My device C"+i);
  134 + device.setType("typeC");
  135 + devices.add(doPost("/api/device", device, Device.class));
  136 + }
  137 + for (int i=0;i<9;i++) {
  138 + Device device = new Device();
  139 + device.setName("My device A"+i);
  140 + device.setType("typeA");
  141 + devices.add(doPost("/api/device", device, Device.class));
  142 + }
  143 + List<TenantDeviceType> deviceTypes = doGetTyped("/api/device/types",
  144 + new TypeReference<List<TenantDeviceType>>(){});
  145 +
  146 + Assert.assertNotNull(deviceTypes);
  147 + Assert.assertEquals(3, deviceTypes.size());
  148 + Assert.assertEquals("typeA", deviceTypes.get(0).getType());
  149 + Assert.assertEquals("typeB", deviceTypes.get(1).getType());
  150 + Assert.assertEquals("typeC", deviceTypes.get(2).getType());
  151 + }
122 152
123 @Test 153 @Test
124 public void testDeleteDevice() throws Exception { 154 public void testDeleteDevice() throws Exception {
125 Device device = new Device(); 155 Device device = new Device();
126 device.setName("My device"); 156 device.setName("My device");
  157 + device.setType("default");
127 Device savedDevice = doPost("/api/device", device, Device.class); 158 Device savedDevice = doPost("/api/device", device, Device.class);
128 159
129 doDelete("/api/device/"+savedDevice.getId().getId().toString()) 160 doDelete("/api/device/"+savedDevice.getId().getId().toString())
@@ -132,10 +163,20 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -132,10 +163,20 @@ public class DeviceControllerTest extends AbstractControllerTest {
132 doGet("/api/device/"+savedDevice.getId().getId().toString()) 163 doGet("/api/device/"+savedDevice.getId().getId().toString())
133 .andExpect(status().isNotFound()); 164 .andExpect(status().isNotFound());
134 } 165 }
135 - 166 +
  167 + @Test
  168 + public void testSaveDeviceWithEmptyType() throws Exception {
  169 + Device device = new Device();
  170 + device.setName("My device");
  171 + doPost("/api/device", device)
  172 + .andExpect(status().isBadRequest())
  173 + .andExpect(statusReason(containsString("Device type should be specified")));
  174 + }
  175 +
136 @Test 176 @Test
137 public void testSaveDeviceWithEmptyName() throws Exception { 177 public void testSaveDeviceWithEmptyName() throws Exception {
138 Device device = new Device(); 178 Device device = new Device();
  179 + device.setType("default");
139 doPost("/api/device", device) 180 doPost("/api/device", device)
140 .andExpect(status().isBadRequest()) 181 .andExpect(status().isBadRequest())
141 .andExpect(statusReason(containsString("Device name should be specified"))); 182 .andExpect(statusReason(containsString("Device name should be specified")));
@@ -145,6 +186,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -145,6 +186,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
145 public void testAssignUnassignDeviceToCustomer() throws Exception { 186 public void testAssignUnassignDeviceToCustomer() throws Exception {
146 Device device = new Device(); 187 Device device = new Device();
147 device.setName("My device"); 188 device.setName("My device");
  189 + device.setType("default");
148 Device savedDevice = doPost("/api/device", device, Device.class); 190 Device savedDevice = doPost("/api/device", device, Device.class);
149 191
150 Customer customer = new Customer(); 192 Customer customer = new Customer();
@@ -170,6 +212,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -170,6 +212,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
170 public void testAssignDeviceToNonExistentCustomer() throws Exception { 212 public void testAssignDeviceToNonExistentCustomer() throws Exception {
171 Device device = new Device(); 213 Device device = new Device();
172 device.setName("My device"); 214 device.setName("My device");
  215 + device.setType("default");
173 Device savedDevice = doPost("/api/device", device, Device.class); 216 Device savedDevice = doPost("/api/device", device, Device.class);
174 217
175 doPost("/api/customer/" + UUIDs.timeBased().toString() 218 doPost("/api/customer/" + UUIDs.timeBased().toString()
@@ -203,6 +246,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -203,6 +246,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
203 246
204 Device device = new Device(); 247 Device device = new Device();
205 device.setName("My device"); 248 device.setName("My device");
  249 + device.setType("default");
206 Device savedDevice = doPost("/api/device", device, Device.class); 250 Device savedDevice = doPost("/api/device", device, Device.class);
207 251
208 doPost("/api/customer/" + savedCustomer.getId().getId().toString() 252 doPost("/api/customer/" + savedCustomer.getId().getId().toString()
@@ -219,6 +263,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -219,6 +263,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
219 public void testFindDeviceCredentialsByDeviceId() throws Exception { 263 public void testFindDeviceCredentialsByDeviceId() throws Exception {
220 Device device = new Device(); 264 Device device = new Device();
221 device.setName("My device"); 265 device.setName("My device");
  266 + device.setType("default");
222 Device savedDevice = doPost("/api/device", device, Device.class); 267 Device savedDevice = doPost("/api/device", device, Device.class);
223 DeviceCredentials deviceCredentials = 268 DeviceCredentials deviceCredentials =
224 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 269 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -229,6 +274,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -229,6 +274,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
229 public void testSaveDeviceCredentials() throws Exception { 274 public void testSaveDeviceCredentials() throws Exception {
230 Device device = new Device(); 275 Device device = new Device();
231 device.setName("My device"); 276 device.setName("My device");
  277 + device.setType("default");
232 Device savedDevice = doPost("/api/device", device, Device.class); 278 Device savedDevice = doPost("/api/device", device, Device.class);
233 DeviceCredentials deviceCredentials = 279 DeviceCredentials deviceCredentials =
234 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 280 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -255,6 +301,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -255,6 +301,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
255 public void testSaveDeviceCredentialsWithEmptyCredentialsType() throws Exception { 301 public void testSaveDeviceCredentialsWithEmptyCredentialsType() throws Exception {
256 Device device = new Device(); 302 Device device = new Device();
257 device.setName("My device"); 303 device.setName("My device");
  304 + device.setType("default");
258 Device savedDevice = doPost("/api/device", device, Device.class); 305 Device savedDevice = doPost("/api/device", device, Device.class);
259 DeviceCredentials deviceCredentials = 306 DeviceCredentials deviceCredentials =
260 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 307 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -268,6 +315,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -268,6 +315,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
268 public void testSaveDeviceCredentialsWithEmptyCredentialsId() throws Exception { 315 public void testSaveDeviceCredentialsWithEmptyCredentialsId() throws Exception {
269 Device device = new Device(); 316 Device device = new Device();
270 device.setName("My device"); 317 device.setName("My device");
  318 + device.setType("default");
271 Device savedDevice = doPost("/api/device", device, Device.class); 319 Device savedDevice = doPost("/api/device", device, Device.class);
272 DeviceCredentials deviceCredentials = 320 DeviceCredentials deviceCredentials =
273 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 321 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -281,6 +329,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -281,6 +329,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
281 public void testSaveNonExistentDeviceCredentials() throws Exception { 329 public void testSaveNonExistentDeviceCredentials() throws Exception {
282 Device device = new Device(); 330 Device device = new Device();
283 device.setName("My device"); 331 device.setName("My device");
  332 + device.setType("default");
284 Device savedDevice = doPost("/api/device", device, Device.class); 333 Device savedDevice = doPost("/api/device", device, Device.class);
285 DeviceCredentials deviceCredentials = 334 DeviceCredentials deviceCredentials =
286 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 335 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -298,6 +347,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -298,6 +347,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
298 public void testSaveDeviceCredentialsWithNonExistentDevice() throws Exception { 347 public void testSaveDeviceCredentialsWithNonExistentDevice() throws Exception {
299 Device device = new Device(); 348 Device device = new Device();
300 device.setName("My device"); 349 device.setName("My device");
  350 + device.setType("default");
301 Device savedDevice = doPost("/api/device", device, Device.class); 351 Device savedDevice = doPost("/api/device", device, Device.class);
302 DeviceCredentials deviceCredentials = 352 DeviceCredentials deviceCredentials =
303 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 353 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -307,9 +357,10 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -307,9 +357,10 @@ public class DeviceControllerTest extends AbstractControllerTest {
307 } 357 }
308 358
309 @Test 359 @Test
310 - public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() throws Exception { 360 + public void testSaveDeviceCredentialsWithInvalidCredentialsIdLength() throws Exception {
311 Device device = new Device(); 361 Device device = new Device();
312 device.setName("My device"); 362 device.setName("My device");
  363 + device.setType("default");
313 Device savedDevice = doPost("/api/device", device, Device.class); 364 Device savedDevice = doPost("/api/device", device, Device.class);
314 DeviceCredentials deviceCredentials = 365 DeviceCredentials deviceCredentials =
315 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); 366 doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class);
@@ -325,6 +376,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -325,6 +376,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
325 for (int i=0;i<178;i++) { 376 for (int i=0;i<178;i++) {
326 Device device = new Device(); 377 Device device = new Device();
327 device.setName("Device"+i); 378 device.setName("Device"+i);
  379 + device.setType("default");
328 devices.add(doPost("/api/device", device, Device.class)); 380 devices.add(doPost("/api/device", device, Device.class));
329 } 381 }
330 List<Device> loadedDevices = new ArrayList<>(); 382 List<Device> loadedDevices = new ArrayList<>();
@@ -355,6 +407,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -355,6 +407,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
355 String name = title1+suffix; 407 String name = title1+suffix;
356 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 408 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
357 device.setName(name); 409 device.setName(name);
  410 + device.setType("default");
358 devicesTitle1.add(doPost("/api/device", device, Device.class)); 411 devicesTitle1.add(doPost("/api/device", device, Device.class));
359 } 412 }
360 String title2 = "Device title 2"; 413 String title2 = "Device title 2";
@@ -365,6 +418,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -365,6 +418,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
365 String name = title2+suffix; 418 String name = title2+suffix;
366 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 419 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
367 device.setName(name); 420 device.setName(name);
  421 + device.setType("default");
368 devicesTitle2.add(doPost("/api/device", device, Device.class)); 422 devicesTitle2.add(doPost("/api/device", device, Device.class));
369 } 423 }
370 424
@@ -423,6 +477,89 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -423,6 +477,89 @@ public class DeviceControllerTest extends AbstractControllerTest {
423 Assert.assertFalse(pageData.hasNext()); 477 Assert.assertFalse(pageData.hasNext());
424 Assert.assertEquals(0, pageData.getData().size()); 478 Assert.assertEquals(0, pageData.getData().size());
425 } 479 }
  480 +
  481 + @Test
  482 + public void testFindTenantDevicesByType() throws Exception {
  483 + String title1 = "Device title 1";
  484 + String type1 = "typeA";
  485 + List<Device> devicesType1 = new ArrayList<>();
  486 + for (int i=0;i<143;i++) {
  487 + Device device = new Device();
  488 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  489 + String name = title1+suffix;
  490 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  491 + device.setName(name);
  492 + device.setType(type1);
  493 + devicesType1.add(doPost("/api/device", device, Device.class));
  494 + }
  495 + String title2 = "Device title 2";
  496 + String type2 = "typeB";
  497 + List<Device> devicesType2 = new ArrayList<>();
  498 + for (int i=0;i<75;i++) {
  499 + Device device = new Device();
  500 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  501 + String name = title2+suffix;
  502 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  503 + device.setName(name);
  504 + device.setType(type2);
  505 + devicesType2.add(doPost("/api/device", device, Device.class));
  506 + }
  507 +
  508 + List<Device> loadedDevicesType1 = new ArrayList<>();
  509 + TextPageLink pageLink = new TextPageLink(15);
  510 + TextPageData<Device> pageData = null;
  511 + do {
  512 + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&",
  513 + new TypeReference<TextPageData<Device>>(){}, pageLink, type1);
  514 + loadedDevicesType1.addAll(pageData.getData());
  515 + if (pageData.hasNext()) {
  516 + pageLink = pageData.getNextPageLink();
  517 + }
  518 + } while (pageData.hasNext());
  519 +
  520 + Collections.sort(devicesType1, idComparator);
  521 + Collections.sort(loadedDevicesType1, idComparator);
  522 +
  523 + Assert.assertEquals(devicesType1, loadedDevicesType1);
  524 +
  525 + List<Device> loadedDevicesType2 = new ArrayList<>();
  526 + pageLink = new TextPageLink(4);
  527 + do {
  528 + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&",
  529 + new TypeReference<TextPageData<Device>>(){}, pageLink, type2);
  530 + loadedDevicesType2.addAll(pageData.getData());
  531 + if (pageData.hasNext()) {
  532 + pageLink = pageData.getNextPageLink();
  533 + }
  534 + } while (pageData.hasNext());
  535 +
  536 + Collections.sort(devicesType2, idComparator);
  537 + Collections.sort(loadedDevicesType2, idComparator);
  538 +
  539 + Assert.assertEquals(devicesType2, loadedDevicesType2);
  540 +
  541 + for (Device device : loadedDevicesType1) {
  542 + doDelete("/api/device/"+device.getId().getId().toString())
  543 + .andExpect(status().isOk());
  544 + }
  545 +
  546 + pageLink = new TextPageLink(4);
  547 + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&",
  548 + new TypeReference<TextPageData<Device>>(){}, pageLink, type1);
  549 + Assert.assertFalse(pageData.hasNext());
  550 + Assert.assertEquals(0, pageData.getData().size());
  551 +
  552 + for (Device device : loadedDevicesType2) {
  553 + doDelete("/api/device/"+device.getId().getId().toString())
  554 + .andExpect(status().isOk());
  555 + }
  556 +
  557 + pageLink = new TextPageLink(4);
  558 + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&",
  559 + new TypeReference<TextPageData<Device>>(){}, pageLink, type2);
  560 + Assert.assertFalse(pageData.hasNext());
  561 + Assert.assertEquals(0, pageData.getData().size());
  562 + }
426 563
427 @Test 564 @Test
428 public void testFindCustomerDevices() throws Exception { 565 public void testFindCustomerDevices() throws Exception {
@@ -435,6 +572,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -435,6 +572,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
435 for (int i=0;i<128;i++) { 572 for (int i=0;i<128;i++) {
436 Device device = new Device(); 573 Device device = new Device();
437 device.setName("Device"+i); 574 device.setName("Device"+i);
  575 + device.setType("default");
438 device = doPost("/api/device", device, Device.class); 576 device = doPost("/api/device", device, Device.class);
439 devices.add(doPost("/api/customer/" + customerId.getId().toString() 577 devices.add(doPost("/api/customer/" + customerId.getId().toString()
440 + "/device/" + device.getId().getId().toString(), Device.class)); 578 + "/device/" + device.getId().getId().toString(), Device.class));
@@ -473,6 +611,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -473,6 +611,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
473 String name = title1+suffix; 611 String name = title1+suffix;
474 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 612 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
475 device.setName(name); 613 device.setName(name);
  614 + device.setType("default");
476 device = doPost("/api/device", device, Device.class); 615 device = doPost("/api/device", device, Device.class);
477 devicesTitle1.add(doPost("/api/customer/" + customerId.getId().toString() 616 devicesTitle1.add(doPost("/api/customer/" + customerId.getId().toString()
478 + "/device/" + device.getId().getId().toString(), Device.class)); 617 + "/device/" + device.getId().getId().toString(), Device.class));
@@ -485,6 +624,7 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -485,6 +624,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
485 String name = title2+suffix; 624 String name = title2+suffix;
486 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 625 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
487 device.setName(name); 626 device.setName(name);
  627 + device.setType("default");
488 device = doPost("/api/device", device, Device.class); 628 device = doPost("/api/device", device, Device.class);
489 devicesTitle2.add(doPost("/api/customer/" + customerId.getId().toString() 629 devicesTitle2.add(doPost("/api/customer/" + customerId.getId().toString()
490 + "/device/" + device.getId().getId().toString(), Device.class)); 630 + "/device/" + device.getId().getId().toString(), Device.class));
@@ -546,4 +686,96 @@ public class DeviceControllerTest extends AbstractControllerTest { @@ -546,4 +686,96 @@ public class DeviceControllerTest extends AbstractControllerTest {
546 Assert.assertEquals(0, pageData.getData().size()); 686 Assert.assertEquals(0, pageData.getData().size());
547 } 687 }
548 688
  689 + @Test
  690 + public void testFindCustomerDevicesByType() throws Exception {
  691 + Customer customer = new Customer();
  692 + customer.setTitle("Test customer");
  693 + customer = doPost("/api/customer", customer, Customer.class);
  694 + CustomerId customerId = customer.getId();
  695 +
  696 + String title1 = "Device title 1";
  697 + String type1 = "typeC";
  698 + List<Device> devicesType1 = new ArrayList<>();
  699 + for (int i=0;i<125;i++) {
  700 + Device device = new Device();
  701 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  702 + String name = title1+suffix;
  703 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  704 + device.setName(name);
  705 + device.setType(type1);
  706 + device = doPost("/api/device", device, Device.class);
  707 + devicesType1.add(doPost("/api/customer/" + customerId.getId().toString()
  708 + + "/device/" + device.getId().getId().toString(), Device.class));
  709 + }
  710 + String title2 = "Device title 2";
  711 + String type2 = "typeD";
  712 + List<Device> devicesType2 = new ArrayList<>();
  713 + for (int i=0;i<143;i++) {
  714 + Device device = new Device();
  715 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  716 + String name = title2+suffix;
  717 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  718 + device.setName(name);
  719 + device.setType(type2);
  720 + device = doPost("/api/device", device, Device.class);
  721 + devicesType2.add(doPost("/api/customer/" + customerId.getId().toString()
  722 + + "/device/" + device.getId().getId().toString(), Device.class));
  723 + }
  724 +
  725 + List<Device> loadedDevicesType1 = new ArrayList<>();
  726 + TextPageLink pageLink = new TextPageLink(15);
  727 + TextPageData<Device> pageData = null;
  728 + do {
  729 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&",
  730 + new TypeReference<TextPageData<Device>>(){}, pageLink, type1);
  731 + loadedDevicesType1.addAll(pageData.getData());
  732 + if (pageData.hasNext()) {
  733 + pageLink = pageData.getNextPageLink();
  734 + }
  735 + } while (pageData.hasNext());
  736 +
  737 + Collections.sort(devicesType1, idComparator);
  738 + Collections.sort(loadedDevicesType1, idComparator);
  739 +
  740 + Assert.assertEquals(devicesType1, loadedDevicesType1);
  741 +
  742 + List<Device> loadedDevicesType2 = new ArrayList<>();
  743 + pageLink = new TextPageLink(4);
  744 + do {
  745 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&",
  746 + new TypeReference<TextPageData<Device>>(){}, pageLink, type2);
  747 + loadedDevicesType2.addAll(pageData.getData());
  748 + if (pageData.hasNext()) {
  749 + pageLink = pageData.getNextPageLink();
  750 + }
  751 + } while (pageData.hasNext());
  752 +
  753 + Collections.sort(devicesType2, idComparator);
  754 + Collections.sort(loadedDevicesType2, idComparator);
  755 +
  756 + Assert.assertEquals(devicesType2, loadedDevicesType2);
  757 +
  758 + for (Device device : loadedDevicesType1) {
  759 + doDelete("/api/customer/device/" + device.getId().getId().toString())
  760 + .andExpect(status().isOk());
  761 + }
  762 +
  763 + pageLink = new TextPageLink(4);
  764 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&",
  765 + new TypeReference<TextPageData<Device>>(){}, pageLink, type1);
  766 + Assert.assertFalse(pageData.hasNext());
  767 + Assert.assertEquals(0, pageData.getData().size());
  768 +
  769 + for (Device device : loadedDevicesType2) {
  770 + doDelete("/api/customer/device/" + device.getId().getId().toString())
  771 + .andExpect(status().isOk());
  772 + }
  773 +
  774 + pageLink = new TextPageLink(4);
  775 + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&",
  776 + new TypeReference<TextPageData<Device>>(){}, pageLink, type2);
  777 + Assert.assertFalse(pageData.hasNext());
  778 + Assert.assertEquals(0, pageData.getData().size());
  779 + }
  780 +
549 } 781 }
@@ -130,7 +130,7 @@ public class TenantControllerTest extends AbstractControllerTest { @@ -130,7 +130,7 @@ public class TenantControllerTest extends AbstractControllerTest {
130 Assert.assertEquals(tenants, loadedTenants); 130 Assert.assertEquals(tenants, loadedTenants);
131 131
132 for (Tenant tenant : loadedTenants) { 132 for (Tenant tenant : loadedTenants) {
133 - if (!tenant.getTitle().equals("Tenant")) { 133 + if (!tenant.getTitle().equals(TEST_TENANT_NAME)) {
134 doDelete("/api/tenant/"+tenant.getId().getId().toString()) 134 doDelete("/api/tenant/"+tenant.getId().getId().toString())
135 .andExpect(status().isOk()); 135 .andExpect(status().isOk());
136 } 136 }
@@ -182,7 +182,7 @@ public class UserControllerTest extends AbstractControllerTest { @@ -182,7 +182,7 @@ public class UserControllerTest extends AbstractControllerTest {
182 Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); 182 Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class);
183 Assert.assertNotNull(savedTenant); 183 Assert.assertNotNull(savedTenant);
184 184
185 - String email = "tenant@thingsboard.org"; 185 + String email = TENANT_ADMIN_EMAIL;
186 User user = new User(); 186 User user = new User();
187 user.setAuthority(Authority.TENANT_ADMIN); 187 user.setAuthority(Authority.TENANT_ADMIN);
188 user.setTenantId(savedTenant.getId()); 188 user.setTenantId(savedTenant.getId());
@@ -47,6 +47,7 @@ public class HttpDeviceApiTest extends AbstractControllerTest { @@ -47,6 +47,7 @@ public class HttpDeviceApiTest extends AbstractControllerTest {
47 loginTenantAdmin(); 47 loginTenantAdmin();
48 device = new Device(); 48 device = new Device();
49 device.setName("My device"); 49 device.setName("My device");
  50 + device.setType("default");
50 device = doPost("/api/device", device, Device.class); 51 device = doPost("/api/device", device, Device.class);
51 52
52 deviceCredentials = 53 deviceCredentials =
@@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.id.TenantId;
20 20
21 import com.fasterxml.jackson.databind.JsonNode; 21 import com.fasterxml.jackson.databind.JsonNode;
22 22
23 -public class Customer extends ContactBased<CustomerId>{ 23 +public class Customer extends ContactBased<CustomerId> implements HasName {
24 24
25 private static final long serialVersionUID = -1599722990298929275L; 25 private static final long serialVersionUID = -1599722990298929275L;
26 26
@@ -59,6 +59,11 @@ public class Customer extends ContactBased<CustomerId>{ @@ -59,6 +59,11 @@ public class Customer extends ContactBased<CustomerId>{
59 this.title = title; 59 this.title = title;
60 } 60 }
61 61
  62 + @Override
  63 + public String getName() {
  64 + return title;
  65 + }
  66 +
62 public JsonNode getAdditionalInfo() { 67 public JsonNode getAdditionalInfo() {
63 return additionalInfo; 68 return additionalInfo;
64 } 69 }
@@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.id.CustomerId; @@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.id.CustomerId;
19 import org.thingsboard.server.common.data.id.DashboardId; 19 import org.thingsboard.server.common.data.id.DashboardId;
20 import org.thingsboard.server.common.data.id.TenantId; 20 import org.thingsboard.server.common.data.id.TenantId;
21 21
22 -public class DashboardInfo extends SearchTextBased<DashboardId> { 22 +public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName {
23 23
24 private TenantId tenantId; 24 private TenantId tenantId;
25 private CustomerId customerId; 25 private CustomerId customerId;
@@ -65,6 +65,11 @@ public class DashboardInfo extends SearchTextBased<DashboardId> { @@ -65,6 +65,11 @@ public class DashboardInfo extends SearchTextBased<DashboardId> {
65 } 65 }
66 66
67 @Override 67 @Override
  68 + public String getName() {
  69 + return title;
  70 + }
  71 +
  72 + @Override
68 public String getSearchText() { 73 public String getSearchText() {
69 return title; 74 return title;
70 } 75 }
@@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.id.TenantId;
21 21
22 import com.fasterxml.jackson.databind.JsonNode; 22 import com.fasterxml.jackson.databind.JsonNode;
23 23
24 -public class Device extends SearchTextBased<DeviceId> { 24 +public class Device extends SearchTextBased<DeviceId> implements HasName {
25 25
26 private static final long serialVersionUID = 2807343040519543363L; 26 private static final long serialVersionUID = 2807343040519543363L;
27 27
@@ -64,6 +64,7 @@ public class Device extends SearchTextBased<DeviceId> { @@ -64,6 +64,7 @@ public class Device extends SearchTextBased<DeviceId> {
64 this.customerId = customerId; 64 this.customerId = customerId;
65 } 65 }
66 66
  67 + @Override
67 public String getName() { 68 public String getName() {
68 return name; 69 return name;
69 } 70 }
@@ -13,34 +13,10 @@ @@ -13,34 +13,10 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
  16 +package org.thingsboard.server.common.data;
16 17
17 -.md-panel {  
18 - &.tb-aliases-device-select-panel {  
19 - position: absolute;  
20 - }  
21 -} 18 +public interface HasName {
22 19
23 -.tb-aliases-device-select-panel {  
24 - max-height: 150px;  
25 - @media (min-height: 350px) {  
26 - max-height: 250px;  
27 - }  
28 - min-width: 300px;  
29 - background: white;  
30 - border-radius: 4px;  
31 - box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2),  
32 - 0 13px 19px 2px rgba(0, 0, 0, 0.14),  
33 - 0 5px 24px 4px rgba(0, 0, 0, 0.12);  
34 - overflow-x: hidden;  
35 - overflow-y: auto;  
36 - md-content {  
37 - background-color: #fff;  
38 - }  
39 -} 20 + String getName();
40 21
41 -.tb-aliases-device-select {  
42 - span {  
43 - pointer-events: all;  
44 - cursor: pointer;  
45 - }  
46 } 22 }
@@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.id.TenantId;
19 19
20 import com.fasterxml.jackson.databind.JsonNode; 20 import com.fasterxml.jackson.databind.JsonNode;
21 21
22 -public class Tenant extends ContactBased<TenantId>{ 22 +public class Tenant extends ContactBased<TenantId> implements HasName {
23 23
24 private static final long serialVersionUID = 8057243243859922101L; 24 private static final long serialVersionUID = 8057243243859922101L;
25 25
@@ -50,6 +50,11 @@ public class Tenant extends ContactBased<TenantId>{ @@ -50,6 +50,11 @@ public class Tenant extends ContactBased<TenantId>{
50 this.title = title; 50 this.title = title;
51 } 51 }
52 52
  53 + @Override
  54 + public String getName() {
  55 + return title;
  56 + }
  57 +
53 public String getRegion() { 58 public String getRegion() {
54 return region; 59 return region;
55 } 60 }
  1 +/**
  2 + * Copyright © 2016-2017 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 org.thingsboard.server.common.data.id.TenantId;
  19 +
  20 +public class TenantDeviceType {
  21 +
  22 + private static final long serialVersionUID = 8057240243859922101L;
  23 +
  24 + private String type;
  25 + private TenantId tenantId;
  26 +
  27 + public TenantDeviceType() {
  28 + super();
  29 + }
  30 +
  31 + public TenantDeviceType(String type, TenantId tenantId) {
  32 + this.type = type;
  33 + this.tenantId = tenantId;
  34 + }
  35 +
  36 + public String getType() {
  37 + return type;
  38 + }
  39 +
  40 + public void setType(String type) {
  41 + this.type = type;
  42 + }
  43 +
  44 + public TenantId getTenantId() {
  45 + return tenantId;
  46 + }
  47 +
  48 + public void setTenantId(TenantId tenantId) {
  49 + this.tenantId = tenantId;
  50 + }
  51 +
  52 + @Override
  53 + public int hashCode() {
  54 + int result = type != null ? type.hashCode() : 0;
  55 + result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
  56 + return result;
  57 + }
  58 +
  59 + @Override
  60 + public boolean equals(Object o) {
  61 + if (this == o) return true;
  62 + if (o == null || getClass() != o.getClass()) return false;
  63 +
  64 + TenantDeviceType that = (TenantDeviceType) o;
  65 +
  66 + if (type != null ? !type.equals(that.type) : that.type != null) return false;
  67 + return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
  68 +
  69 + }
  70 +
  71 + @Override
  72 + public String toString() {
  73 + final StringBuilder sb = new StringBuilder("TenantDeviceType{");
  74 + sb.append("type='").append(type).append('\'');
  75 + sb.append(", tenantId=").append(tenantId);
  76 + sb.append('}');
  77 + return sb.toString();
  78 + }
  79 +}
@@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.security.Authority; @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.security.Authority;
22 22
23 import com.fasterxml.jackson.databind.JsonNode; 23 import com.fasterxml.jackson.databind.JsonNode;
24 24
25 -public class User extends SearchTextBased<UserId> { 25 +public class User extends SearchTextBased<UserId> implements HasName {
26 26
27 private static final long serialVersionUID = 8250339805336035966L; 27 private static final long serialVersionUID = 8250339805336035966L;
28 28
@@ -77,6 +77,11 @@ public class User extends SearchTextBased<UserId> { @@ -77,6 +77,11 @@ public class User extends SearchTextBased<UserId> {
77 this.email = email; 77 this.email = email;
78 } 78 }
79 79
  80 + @Override
  81 + public String getName() {
  82 + return email;
  83 + }
  84 +
80 public Authority getAuthority() { 85 public Authority getAuthority() {
81 return authority; 86 return authority;
82 } 87 }
@@ -18,13 +18,14 @@ package org.thingsboard.server.common.data.alarm; @@ -18,13 +18,14 @@ package org.thingsboard.server.common.data.alarm;
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.Data; 19 import lombok.Data;
20 import org.thingsboard.server.common.data.BaseData; 20 import org.thingsboard.server.common.data.BaseData;
  21 +import org.thingsboard.server.common.data.HasName;
21 import org.thingsboard.server.common.data.id.EntityId; 22 import org.thingsboard.server.common.data.id.EntityId;
22 23
23 /** 24 /**
24 * Created by ashvayka on 11.05.17. 25 * Created by ashvayka on 11.05.17.
25 */ 26 */
26 @Data 27 @Data
27 -public class Alarm extends BaseData<AlarmId> { 28 +public class Alarm extends BaseData<AlarmId> implements HasName {
28 29
29 private long startTs; 30 private long startTs;
30 private long endTs; 31 private long endTs;
@@ -37,4 +38,8 @@ public class Alarm extends BaseData<AlarmId> { @@ -37,4 +38,8 @@ public class Alarm extends BaseData<AlarmId> {
37 private JsonNode details; 38 private JsonNode details;
38 private boolean propagate; 39 private boolean propagate;
39 40
  41 + @Override
  42 + public String getName() {
  43 + return type;
  44 + }
40 } 45 }
@@ -16,12 +16,13 @@ @@ -16,12 +16,13 @@
16 package org.thingsboard.server.common.data.asset; 16 package org.thingsboard.server.common.data.asset;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
  19 +import org.thingsboard.server.common.data.HasName;
19 import org.thingsboard.server.common.data.SearchTextBased; 20 import org.thingsboard.server.common.data.SearchTextBased;
20 import org.thingsboard.server.common.data.id.AssetId; 21 import org.thingsboard.server.common.data.id.AssetId;
21 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
22 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
23 24
24 -public class Asset extends SearchTextBased<AssetId> { 25 +public class Asset extends SearchTextBased<AssetId> implements HasName {
25 26
26 private static final long serialVersionUID = 2807343040519543363L; 27 private static final long serialVersionUID = 2807343040519543363L;
27 28
@@ -64,6 +65,7 @@ public class Asset extends SearchTextBased<AssetId> { @@ -64,6 +65,7 @@ public class Asset extends SearchTextBased<AssetId> {
64 this.customerId = customerId; 65 this.customerId = customerId;
65 } 66 }
66 67
  68 + @Override
67 public String getName() { 69 public String getName() {
68 return name; 70 return name;
69 } 71 }
  1 +/**
  2 + * Copyright © 2016-2017 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.asset;
  17 +
  18 +import org.thingsboard.server.common.data.id.TenantId;
  19 +
  20 +public class TenantAssetType {
  21 +
  22 + private static final long serialVersionUID = 8057290243855622101L;
  23 +
  24 + private String type;
  25 + private TenantId tenantId;
  26 +
  27 + public TenantAssetType() {
  28 + super();
  29 + }
  30 +
  31 + public TenantAssetType(String type, TenantId tenantId) {
  32 + this.type = type;
  33 + this.tenantId = tenantId;
  34 + }
  35 +
  36 + public String getType() {
  37 + return type;
  38 + }
  39 +
  40 + public void setType(String type) {
  41 + this.type = type;
  42 + }
  43 +
  44 + public TenantId getTenantId() {
  45 + return tenantId;
  46 + }
  47 +
  48 + public void setTenantId(TenantId tenantId) {
  49 + this.tenantId = tenantId;
  50 + }
  51 +
  52 + @Override
  53 + public int hashCode() {
  54 + int result = type != null ? type.hashCode() : 0;
  55 + result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
  56 + return result;
  57 + }
  58 +
  59 + @Override
  60 + public boolean equals(Object o) {
  61 + if (this == o) return true;
  62 + if (o == null || getClass() != o.getClass()) return false;
  63 +
  64 + TenantAssetType that = (TenantAssetType) o;
  65 +
  66 + if (type != null ? !type.equals(that.type) : that.type != null) return false;
  67 + return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
  68 +
  69 + }
  70 +
  71 + @Override
  72 + public String toString() {
  73 + final StringBuilder sb = new StringBuilder("TenantAssetType{");
  74 + sb.append("type='").append(type).append('\'');
  75 + sb.append(", tenantId=").append(tenantId);
  76 + sb.append('}');
  77 + return sb.toString();
  78 + }
  79 +}
@@ -15,13 +15,14 @@ @@ -15,13 +15,14 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.plugin; 16 package org.thingsboard.server.common.data.plugin;
17 17
  18 +import org.thingsboard.server.common.data.HasName;
18 import org.thingsboard.server.common.data.SearchTextBased; 19 import org.thingsboard.server.common.data.SearchTextBased;
19 import org.thingsboard.server.common.data.id.PluginId; 20 import org.thingsboard.server.common.data.id.PluginId;
20 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
21 22
22 import com.fasterxml.jackson.databind.JsonNode; 23 import com.fasterxml.jackson.databind.JsonNode;
23 24
24 -public class PluginMetaData extends SearchTextBased<PluginId> { 25 +public class PluginMetaData extends SearchTextBased<PluginId> implements HasName {
25 26
26 private static final long serialVersionUID = 1L; 27 private static final long serialVersionUID = 1L;
27 28
@@ -75,6 +76,7 @@ public class PluginMetaData extends SearchTextBased<PluginId> { @@ -75,6 +76,7 @@ public class PluginMetaData extends SearchTextBased<PluginId> {
75 this.tenantId = tenantId; 76 this.tenantId = tenantId;
76 } 77 }
77 78
  79 + @Override
78 public String getName() { 80 public String getName() {
79 return name; 81 return name;
80 } 82 }
@@ -47,11 +47,11 @@ public class EntityRelation { @@ -47,11 +47,11 @@ public class EntityRelation {
47 this.additionalInfo = additionalInfo; 47 this.additionalInfo = additionalInfo;
48 } 48 }
49 49
50 - public EntityRelation(EntityRelation device) {  
51 - this.from = device.getFrom();  
52 - this.to = device.getTo();  
53 - this.type = device.getType();  
54 - this.additionalInfo = device.getAdditionalInfo(); 50 + public EntityRelation(EntityRelation entityRelation) {
  51 + this.from = entityRelation.getFrom();
  52 + this.to = entityRelation.getTo();
  53 + this.type = entityRelation.getType();
  54 + this.additionalInfo = entityRelation.getAdditionalInfo();
55 } 55 }
56 56
57 public EntityId getFrom() { 57 public EntityId getFrom() {
  1 +/**
  2 + * Copyright © 2016-2017 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 +package org.thingsboard.server.common.data.relation;
  18 +
  19 +public class EntityRelationInfo extends EntityRelation {
  20 +
  21 + private static final long serialVersionUID = 2807343097519543363L;
  22 +
  23 + private String toName;
  24 +
  25 + public EntityRelationInfo() {
  26 + super();
  27 + }
  28 +
  29 + public EntityRelationInfo(EntityRelation entityRelation) {
  30 + super(entityRelation);
  31 + }
  32 +
  33 + public String getToName() {
  34 + return toName;
  35 + }
  36 +
  37 + public void setToName(String toName) {
  38 + this.toName = toName;
  39 + }
  40 +
  41 + @Override
  42 + public boolean equals(Object o) {
  43 + if (this == o) return true;
  44 + if (o == null || getClass() != o.getClass()) return false;
  45 + if (!super.equals(o)) return false;
  46 +
  47 + EntityRelationInfo that = (EntityRelationInfo) o;
  48 +
  49 + return toName != null ? toName.equals(that.toName) : that.toName == null;
  50 +
  51 + }
  52 +
  53 + @Override
  54 + public int hashCode() {
  55 + int result = super.hashCode();
  56 + result = 31 * result + (toName != null ? toName.hashCode() : 0);
  57 + return result;
  58 + }
  59 +}
@@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.rule; @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.rule;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.ToString; 19 import lombok.ToString;
  20 +import org.thingsboard.server.common.data.HasName;
20 import org.thingsboard.server.common.data.SearchTextBased; 21 import org.thingsboard.server.common.data.SearchTextBased;
21 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
22 import org.thingsboard.server.common.data.id.RuleId; 23 import org.thingsboard.server.common.data.id.RuleId;
@@ -26,7 +27,7 @@ import com.fasterxml.jackson.databind.JsonNode; @@ -26,7 +27,7 @@ import com.fasterxml.jackson.databind.JsonNode;
26 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; 27 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
27 28
28 @Data 29 @Data
29 -public class RuleMetaData extends SearchTextBased<RuleId> { 30 +public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
30 31
31 private static final long serialVersionUID = -5656679015122935465L; 32 private static final long serialVersionUID = -5656679015122935465L;
32 33
@@ -66,4 +67,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> { @@ -66,4 +67,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> {
66 return name; 67 return name;
67 } 68 }
68 69
  70 + @Override
  71 + public String getName() {
  72 + return name;
  73 + }
  74 +
69 } 75 }
@@ -28,6 +28,10 @@ import java.util.Optional; @@ -28,6 +28,10 @@ import java.util.Optional;
28 */ 28 */
29 public interface AlarmService { 29 public interface AlarmService {
30 30
  31 + Alarm findAlarmById(AlarmId alarmId);
  32 +
  33 + ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId);
  34 +
31 Optional<Alarm> saveIfNotExists(Alarm alarm); 35 Optional<Alarm> saveIfNotExists(Alarm alarm);
32 36
33 ListenableFuture<Boolean> updateAlarm(Alarm alarm); 37 ListenableFuture<Boolean> updateAlarm(Alarm alarm);
  1 +/**
  2 + * Copyright © 2016-2017 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.alarm;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.stereotype.Service;
  21 +import org.thingsboard.server.common.data.alarm.Alarm;
  22 +import org.thingsboard.server.common.data.alarm.AlarmId;
  23 +import org.thingsboard.server.common.data.alarm.AlarmQuery;
  24 +import org.thingsboard.server.common.data.page.TimePageData;
  25 +
  26 +import java.util.Optional;
  27 +
  28 +@Service
  29 +@Slf4j
  30 +public class BaseAlarmService implements AlarmService {
  31 +
  32 + @Override
  33 + public Alarm findAlarmById(AlarmId alarmId) {
  34 + return null;
  35 + }
  36 +
  37 + @Override
  38 + public ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId) {
  39 + return null;
  40 + }
  41 +
  42 + @Override
  43 + public Optional<Alarm> saveIfNotExists(Alarm alarm) {
  44 + return null;
  45 + }
  46 +
  47 + @Override
  48 + public ListenableFuture<Boolean> updateAlarm(Alarm alarm) {
  49 + return null;
  50 + }
  51 +
  52 + @Override
  53 + public ListenableFuture<Boolean> ackAlarm(Alarm alarm) {
  54 + return null;
  55 + }
  56 +
  57 + @Override
  58 + public ListenableFuture<Boolean> clearAlarm(AlarmId alarmId) {
  59 + return null;
  60 + }
  61 +
  62 + @Override
  63 + public ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query) {
  64 + return null;
  65 + }
  66 +}
@@ -16,12 +16,11 @@ @@ -16,12 +16,11 @@
16 package org.thingsboard.server.dao.asset; 16 package org.thingsboard.server.dao.asset;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 -import org.thingsboard.server.common.data.Device;  
20 import org.thingsboard.server.common.data.asset.Asset; 19 import org.thingsboard.server.common.data.asset.Asset;
21 import org.thingsboard.server.common.data.page.TextPageLink; 20 import org.thingsboard.server.common.data.page.TextPageLink;
22 import org.thingsboard.server.dao.Dao; 21 import org.thingsboard.server.dao.Dao;
23 import org.thingsboard.server.dao.model.AssetEntity; 22 import org.thingsboard.server.dao.model.AssetEntity;
24 -import org.thingsboard.server.dao.model.DeviceEntity; 23 +import org.thingsboard.server.dao.model.TenantAssetTypeEntity;
25 24
26 import java.util.List; 25 import java.util.List;
27 import java.util.Optional; 26 import java.util.Optional;
@@ -51,6 +50,16 @@ public interface AssetDao extends Dao<AssetEntity> { @@ -51,6 +50,16 @@ public interface AssetDao extends Dao<AssetEntity> {
51 List<AssetEntity> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink); 50 List<AssetEntity> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink);
52 51
53 /** 52 /**
  53 + * Find assets by tenantId, type and page link.
  54 + *
  55 + * @param tenantId the tenantId
  56 + * @param type the type
  57 + * @param pageLink the page link
  58 + * @return the list of asset objects
  59 + */
  60 + List<AssetEntity> findAssetsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink);
  61 +
  62 + /**
54 * Find assets by tenantId and assets Ids. 63 * Find assets by tenantId and assets Ids.
55 * 64 *
56 * @param tenantId the tenantId 65 * @param tenantId the tenantId
@@ -70,6 +79,17 @@ public interface AssetDao extends Dao<AssetEntity> { @@ -70,6 +79,17 @@ public interface AssetDao extends Dao<AssetEntity> {
70 List<AssetEntity> findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); 79 List<AssetEntity> findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink);
71 80
72 /** 81 /**
  82 + * Find assets by tenantId, customerId, type and page link.
  83 + *
  84 + * @param tenantId the tenantId
  85 + * @param customerId the customerId
  86 + * @param type the type
  87 + * @param pageLink the page link
  88 + * @return the list of asset objects
  89 + */
  90 + List<AssetEntity> findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink);
  91 +
  92 + /**
73 * Find assets by tenantId, customerId and assets Ids. 93 * Find assets by tenantId, customerId and assets Ids.
74 * 94 *
75 * @param tenantId the tenantId 95 * @param tenantId the tenantId
@@ -87,4 +107,12 @@ public interface AssetDao extends Dao<AssetEntity> { @@ -87,4 +107,12 @@ public interface AssetDao extends Dao<AssetEntity> {
87 * @return the optional asset object 107 * @return the optional asset object
88 */ 108 */
89 Optional<AssetEntity> findAssetsByTenantIdAndName(UUID tenantId, String name); 109 Optional<AssetEntity> findAssetsByTenantIdAndName(UUID tenantId, String name);
  110 +
  111 + /**
  112 + * Find tenants asset types.
  113 + *
  114 + * @return the list of tenant asset type objects
  115 + */
  116 + ListenableFuture<List<TenantAssetTypeEntity>> findTenantAssetTypesAsync();
  117 +
90 } 118 }
@@ -15,7 +15,12 @@ @@ -15,7 +15,12 @@
15 */ 15 */
16 package org.thingsboard.server.dao.asset; 16 package org.thingsboard.server.dao.asset;
17 17
  18 +import com.datastax.driver.core.ResultSet;
  19 +import com.datastax.driver.core.ResultSetFuture;
18 import com.datastax.driver.core.querybuilder.Select; 20 import com.datastax.driver.core.querybuilder.Select;
  21 +import com.datastax.driver.mapping.Result;
  22 +import com.google.common.base.Function;
  23 +import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture; 24 import com.google.common.util.concurrent.ListenableFuture;
20 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.stereotype.Component; 26 import org.springframework.stereotype.Component;
@@ -23,7 +28,9 @@ import org.thingsboard.server.common.data.asset.Asset; @@ -23,7 +28,9 @@ import org.thingsboard.server.common.data.asset.Asset;
23 import org.thingsboard.server.common.data.page.TextPageLink; 28 import org.thingsboard.server.common.data.page.TextPageLink;
24 import org.thingsboard.server.dao.AbstractSearchTextDao; 29 import org.thingsboard.server.dao.AbstractSearchTextDao;
25 import org.thingsboard.server.dao.model.AssetEntity; 30 import org.thingsboard.server.dao.model.AssetEntity;
  31 +import org.thingsboard.server.dao.model.TenantAssetTypeEntity;
26 32
  33 +import javax.annotation.Nullable;
27 import java.util.*; 34 import java.util.*;
28 35
29 import static com.datastax.driver.core.querybuilder.QueryBuilder.*; 36 import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
@@ -60,6 +67,16 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements @@ -60,6 +67,16 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements
60 } 67 }
61 68
62 @Override 69 @Override
  70 + public List<AssetEntity> findAssetsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
  71 + log.debug("Try to find assets by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
  72 + List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  73 + Arrays.asList(eq(ASSET_TYPE_PROPERTY, type),
  74 + eq(ASSET_TENANT_ID_PROPERTY, tenantId)), pageLink);
  75 + log.trace("Found assets [{}] by tenantId [{}], type [{}] and pageLink [{}]", assetEntities, tenantId, type, pageLink);
  76 + return assetEntities;
  77 + }
  78 +
  79 + @Override
63 public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List<UUID> assetIds) { 80 public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List<UUID> assetIds) {
64 log.debug("Try to find assets by tenantId [{}] and asset Ids [{}]", tenantId, assetIds); 81 log.debug("Try to find assets by tenantId [{}] and asset Ids [{}]", tenantId, assetIds);
65 Select select = select().from(getColumnFamilyName()); 82 Select select = select().from(getColumnFamilyName());
@@ -82,6 +99,19 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements @@ -82,6 +99,19 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements
82 } 99 }
83 100
84 @Override 101 @Override
  102 + public List<AssetEntity> findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
  103 + log.debug("Try to find assets by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink);
  104 + List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  105 + Arrays.asList(eq(ASSET_TYPE_PROPERTY, type),
  106 + eq(ASSET_CUSTOMER_ID_PROPERTY, customerId),
  107 + eq(ASSET_TENANT_ID_PROPERTY, tenantId)),
  108 + pageLink);
  109 +
  110 + log.trace("Found assets [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", assetEntities, tenantId, customerId, type, pageLink);
  111 + return assetEntities;
  112 + }
  113 +
  114 + @Override
85 public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> assetIds) { 115 public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> assetIds) {
86 log.debug("Try to find assets by tenantId [{}], customerId [{}] and asset Ids [{}]", tenantId, customerId, assetIds); 116 log.debug("Try to find assets by tenantId [{}], customerId [{}] and asset Ids [{}]", tenantId, customerId, assetIds);
87 Select select = select().from(getColumnFamilyName()); 117 Select select = select().from(getColumnFamilyName());
@@ -101,4 +131,24 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements @@ -101,4 +131,24 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements
101 return Optional.ofNullable(findOneByStatement(query)); 131 return Optional.ofNullable(findOneByStatement(query));
102 } 132 }
103 133
  134 + @Override
  135 + public ListenableFuture<List<TenantAssetTypeEntity>> findTenantAssetTypesAsync() {
  136 + Select statement = select().distinct().column(ASSET_TYPE_PROPERTY).column(ASSET_TENANT_ID_PROPERTY).from(ASSET_TYPES_BY_TENANT_VIEW_NAME);
  137 + statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
  138 + ResultSetFuture resultSetFuture = getSession().executeAsync(statement);
  139 + ListenableFuture<List<TenantAssetTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantAssetTypeEntity>>() {
  140 + @Nullable
  141 + @Override
  142 + public List<TenantAssetTypeEntity> apply(@Nullable ResultSet resultSet) {
  143 + Result<TenantAssetTypeEntity> result = cluster.getMapper(TenantAssetTypeEntity.class).map(resultSet);
  144 + if (result != null) {
  145 + return result.all();
  146 + } else {
  147 + return Collections.emptyList();
  148 + }
  149 + }
  150 + });
  151 + return result;
  152 + }
  153 +
104 } 154 }
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset; @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.asset.Asset; 19 import org.thingsboard.server.common.data.asset.Asset;
  20 +import org.thingsboard.server.common.data.asset.TenantAssetType;
20 import org.thingsboard.server.common.data.id.AssetId; 21 import org.thingsboard.server.common.data.id.AssetId;
21 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
22 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
@@ -34,7 +35,7 @@ public interface AssetService { @@ -34,7 +35,7 @@ public interface AssetService {
34 35
35 Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name); 36 Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name);
36 37
37 - Asset saveAsset(Asset device); 38 + Asset saveAsset(Asset asset);
38 39
39 Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId); 40 Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId);
40 41
@@ -44,16 +45,21 @@ public interface AssetService { @@ -44,16 +45,21 @@ public interface AssetService {
44 45
45 TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink); 46 TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink);
46 47
  48 + TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink);
  49 +
47 ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); 50 ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds);
48 51
49 void deleteAssetsByTenantId(TenantId tenantId); 52 void deleteAssetsByTenantId(TenantId tenantId);
50 53
51 TextPageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); 54 TextPageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink);
52 55
  56 + TextPageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink);
  57 +
53 ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); 58 ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds);
54 59
55 void unassignCustomerAssets(TenantId tenantId, CustomerId customerId); 60 void unassignCustomerAssets(TenantId tenantId, CustomerId customerId);
56 61
57 ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query); 62 ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query);
58 63
  64 + ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId);
59 } 65 }
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service;
26 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
27 import org.thingsboard.server.common.data.EntityType; 27 import org.thingsboard.server.common.data.EntityType;
28 import org.thingsboard.server.common.data.asset.Asset; 28 import org.thingsboard.server.common.data.asset.Asset;
  29 +import org.thingsboard.server.common.data.asset.TenantAssetType;
29 import org.thingsboard.server.common.data.id.AssetId; 30 import org.thingsboard.server.common.data.id.AssetId;
30 import org.thingsboard.server.common.data.id.CustomerId; 31 import org.thingsboard.server.common.data.id.CustomerId;
31 import org.thingsboard.server.common.data.id.EntityId; 32 import org.thingsboard.server.common.data.id.EntityId;
@@ -34,12 +35,9 @@ import org.thingsboard.server.common.data.page.TextPageData; @@ -34,12 +35,9 @@ import org.thingsboard.server.common.data.page.TextPageData;
34 import org.thingsboard.server.common.data.page.TextPageLink; 35 import org.thingsboard.server.common.data.page.TextPageLink;
35 import org.thingsboard.server.common.data.relation.EntityRelation; 36 import org.thingsboard.server.common.data.relation.EntityRelation;
36 import org.thingsboard.server.dao.customer.CustomerDao; 37 import org.thingsboard.server.dao.customer.CustomerDao;
37 -import org.thingsboard.server.dao.entity.BaseEntityService; 38 +import org.thingsboard.server.dao.entity.AbstractEntityService;
38 import org.thingsboard.server.dao.exception.DataValidationException; 39 import org.thingsboard.server.dao.exception.DataValidationException;
39 -import org.thingsboard.server.dao.model.AssetEntity;  
40 -import org.thingsboard.server.dao.model.CustomerEntity;  
41 -import org.thingsboard.server.dao.model.TenantEntity;  
42 -import org.thingsboard.server.dao.relation.EntityRelationsQuery; 40 +import org.thingsboard.server.dao.model.*;
43 import org.thingsboard.server.dao.relation.EntitySearchDirection; 41 import org.thingsboard.server.dao.relation.EntitySearchDirection;
44 import org.thingsboard.server.dao.service.DataValidator; 42 import org.thingsboard.server.dao.service.DataValidator;
45 import org.thingsboard.server.dao.service.PaginatedRemover; 43 import org.thingsboard.server.dao.service.PaginatedRemover;
@@ -57,7 +55,7 @@ import static org.thingsboard.server.dao.service.Validator.*; @@ -57,7 +55,7 @@ import static org.thingsboard.server.dao.service.Validator.*;
57 55
58 @Service 56 @Service
59 @Slf4j 57 @Slf4j
60 -public class BaseAssetService extends BaseEntityService implements AssetService { 58 +public class BaseAssetService extends AbstractEntityService implements AssetService {
61 59
62 @Autowired 60 @Autowired
63 private AssetDao assetDao; 61 private AssetDao assetDao;
@@ -132,7 +130,18 @@ public class BaseAssetService extends BaseEntityService implements AssetService @@ -132,7 +130,18 @@ public class BaseAssetService extends BaseEntityService implements AssetService
132 validatePageLink(pageLink, "Incorrect page link " + pageLink); 130 validatePageLink(pageLink, "Incorrect page link " + pageLink);
133 List<AssetEntity> assetEntities = assetDao.findAssetsByTenantId(tenantId.getId(), pageLink); 131 List<AssetEntity> assetEntities = assetDao.findAssetsByTenantId(tenantId.getId(), pageLink);
134 List<Asset> assets = convertDataList(assetEntities); 132 List<Asset> assets = convertDataList(assetEntities);
135 - return new TextPageData<Asset>(assets, pageLink); 133 + return new TextPageData<>(assets, pageLink);
  134 + }
  135 +
  136 + @Override
  137 + public TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink) {
  138 + log.trace("Executing findAssetsByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink);
  139 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  140 + validateString(type, "Incorrect type " + type);
  141 + validatePageLink(pageLink, "Incorrect page link " + pageLink);
  142 + List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndType(tenantId.getId(), type, pageLink);
  143 + List<Asset> assets = convertDataList(assetEntities);
  144 + return new TextPageData<>(assets, pageLink);
136 } 145 }
137 146
138 @Override 147 @Override
@@ -159,7 +168,19 @@ public class BaseAssetService extends BaseEntityService implements AssetService @@ -159,7 +168,19 @@ public class BaseAssetService extends BaseEntityService implements AssetService
159 validatePageLink(pageLink, "Incorrect page link " + pageLink); 168 validatePageLink(pageLink, "Incorrect page link " + pageLink);
160 List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); 169 List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink);
161 List<Asset> assets = convertDataList(assetEntities); 170 List<Asset> assets = convertDataList(assetEntities);
162 - return new TextPageData<Asset>(assets, pageLink); 171 + return new TextPageData<>(assets, pageLink);
  172 + }
  173 +
  174 + @Override
  175 + public TextPageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink) {
  176 + log.trace("Executing findAssetsByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink);
  177 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  178 + validateId(customerId, "Incorrect customerId " + customerId);
  179 + validateString(type, "Incorrect type " + type);
  180 + validatePageLink(pageLink, "Incorrect page link " + pageLink);
  181 + List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink);
  182 + List<Asset> assets = convertDataList(assetEntities);
  183 + return new TextPageData<>(assets, pageLink);
163 } 184 }
164 185
165 @Override 186 @Override
@@ -207,6 +228,25 @@ public class BaseAssetService extends BaseEntityService implements AssetService @@ -207,6 +228,25 @@ public class BaseAssetService extends BaseEntityService implements AssetService
207 return assets; 228 return assets;
208 } 229 }
209 230
  231 + @Override
  232 + public ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId) {
  233 + log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId);
  234 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  235 + ListenableFuture<List<TenantAssetTypeEntity>> tenantAssetTypeEntities = assetDao.findTenantAssetTypesAsync();
  236 + ListenableFuture<List<TenantAssetType>> tenantAssetTypes = Futures.transform(tenantAssetTypeEntities,
  237 + (Function<List<TenantAssetTypeEntity>, List<TenantAssetType>>) assetTypeEntities -> {
  238 + List<TenantAssetType> assetTypes = new ArrayList<>();
  239 + for (TenantAssetTypeEntity assetTypeEntity : assetTypeEntities) {
  240 + if (assetTypeEntity.getTenantId().equals(tenantId.getId())) {
  241 + assetTypes.add(assetTypeEntity.toTenantAssetType());
  242 + }
  243 + }
  244 + assetTypes.sort((TenantAssetType o1, TenantAssetType o2) -> o1.getType().compareTo(o2.getType()));
  245 + return assetTypes;
  246 + });
  247 + return tenantAssetTypes;
  248 + }
  249 +
210 private DataValidator<Asset> assetValidator = 250 private DataValidator<Asset> assetValidator =
211 new DataValidator<Asset>() { 251 new DataValidator<Asset>() {
212 252
@@ -232,6 +272,9 @@ public class BaseAssetService extends BaseEntityService implements AssetService @@ -232,6 +272,9 @@ public class BaseAssetService extends BaseEntityService implements AssetService
232 272
233 @Override 273 @Override
234 protected void validateDataImpl(Asset asset) { 274 protected void validateDataImpl(Asset asset) {
  275 + if (StringUtils.isEmpty(asset.getType())) {
  276 + throw new DataValidationException("Asset type should be specified!");
  277 + }
235 if (StringUtils.isEmpty(asset.getName())) { 278 if (StringUtils.isEmpty(asset.getName())) {
236 throw new DataValidationException("Asset name should be specified!"); 279 throw new DataValidationException("Asset name should be specified!");
237 } 280 }
@@ -45,7 +45,6 @@ public class ServiceCacheConfiguration { @@ -45,7 +45,6 @@ public class ServiceCacheConfiguration {
45 @Value("${cache.device_credentials.time_to_live}") 45 @Value("${cache.device_credentials.time_to_live}")
46 private Integer cacheDeviceCredentialsTTL; 46 private Integer cacheDeviceCredentialsTTL;
47 47
48 -  
49 @Value("${zk.enabled}") 48 @Value("${zk.enabled}")
50 private boolean zkEnabled; 49 private boolean zkEnabled;
51 @Value("${zk.url}") 50 @Value("${zk.url}")
@@ -31,17 +31,15 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -31,17 +31,15 @@ import com.google.common.util.concurrent.ListenableFuture;
31 import lombok.extern.slf4j.Slf4j; 31 import lombok.extern.slf4j.Slf4j;
32 import org.apache.commons.lang3.StringUtils; 32 import org.apache.commons.lang3.StringUtils;
33 import org.thingsboard.server.common.data.Customer; 33 import org.thingsboard.server.common.data.Customer;
34 -import org.thingsboard.server.common.data.asset.Asset;  
35 import org.thingsboard.server.common.data.id.CustomerId; 34 import org.thingsboard.server.common.data.id.CustomerId;
36 import org.thingsboard.server.common.data.id.TenantId; 35 import org.thingsboard.server.common.data.id.TenantId;
37 import org.thingsboard.server.common.data.page.TextPageData; 36 import org.thingsboard.server.common.data.page.TextPageData;
38 import org.thingsboard.server.common.data.page.TextPageLink; 37 import org.thingsboard.server.common.data.page.TextPageLink;
39 import org.thingsboard.server.dao.dashboard.DashboardService; 38 import org.thingsboard.server.dao.dashboard.DashboardService;
40 import org.thingsboard.server.dao.device.DeviceService; 39 import org.thingsboard.server.dao.device.DeviceService;
41 -import org.thingsboard.server.dao.entity.BaseEntityService; 40 +import org.thingsboard.server.dao.entity.AbstractEntityService;
42 import org.thingsboard.server.dao.exception.DataValidationException; 41 import org.thingsboard.server.dao.exception.DataValidationException;
43 import org.thingsboard.server.dao.exception.IncorrectParameterException; 42 import org.thingsboard.server.dao.exception.IncorrectParameterException;
44 -import org.thingsboard.server.dao.model.AssetEntity;  
45 import org.thingsboard.server.dao.model.CustomerEntity; 43 import org.thingsboard.server.dao.model.CustomerEntity;
46 import org.thingsboard.server.dao.model.TenantEntity; 44 import org.thingsboard.server.dao.model.TenantEntity;
47 import org.thingsboard.server.dao.service.DataValidator; 45 import org.thingsboard.server.dao.service.DataValidator;
@@ -53,7 +51,7 @@ import org.springframework.stereotype.Service; @@ -53,7 +51,7 @@ import org.springframework.stereotype.Service;
53 import org.thingsboard.server.dao.service.Validator; 51 import org.thingsboard.server.dao.service.Validator;
54 @Service 52 @Service
55 @Slf4j 53 @Slf4j
56 -public class CustomerServiceImpl extends BaseEntityService implements CustomerService { 54 +public class CustomerServiceImpl extends AbstractEntityService implements CustomerService {
57 55
58 private static final String PUBLIC_CUSTOMER_TITLE = "Public"; 56 private static final String PUBLIC_CUSTOMER_TITLE = "Public";
59 57
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.dao.dashboard; 16 package org.thingsboard.server.dao.dashboard;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 import org.thingsboard.server.common.data.Dashboard; 19 import org.thingsboard.server.common.data.Dashboard;
19 import org.thingsboard.server.common.data.DashboardInfo; 20 import org.thingsboard.server.common.data.DashboardInfo;
20 import org.thingsboard.server.common.data.id.CustomerId; 21 import org.thingsboard.server.common.data.id.CustomerId;
@@ -27,8 +28,12 @@ public interface DashboardService { @@ -27,8 +28,12 @@ public interface DashboardService {
27 28
28 public Dashboard findDashboardById(DashboardId dashboardId); 29 public Dashboard findDashboardById(DashboardId dashboardId);
29 30
  31 + public ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId);
  32 +
30 public DashboardInfo findDashboardInfoById(DashboardId dashboardId); 33 public DashboardInfo findDashboardInfoById(DashboardId dashboardId);
31 34
  35 + public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId);
  36 +
32 public Dashboard saveDashboard(Dashboard dashboard); 37 public Dashboard saveDashboard(Dashboard dashboard);
33 38
34 public Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId); 39 public Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId);
@@ -17,9 +17,13 @@ package org.thingsboard.server.dao.dashboard; @@ -17,9 +17,13 @@ package org.thingsboard.server.dao.dashboard;
17 17
18 import static org.thingsboard.server.dao.DaoUtil.convertDataList; 18 import static org.thingsboard.server.dao.DaoUtil.convertDataList;
19 import static org.thingsboard.server.dao.DaoUtil.getData; 19 import static org.thingsboard.server.dao.DaoUtil.getData;
  20 +import static org.thingsboard.server.dao.service.Validator.validateId;
20 21
21 import java.util.List; 22 import java.util.List;
22 23
  24 +import com.google.common.base.Function;
  25 +import com.google.common.util.concurrent.Futures;
  26 +import com.google.common.util.concurrent.ListenableFuture;
23 import lombok.extern.slf4j.Slf4j; 27 import lombok.extern.slf4j.Slf4j;
24 import org.apache.commons.lang3.StringUtils; 28 import org.apache.commons.lang3.StringUtils;
25 import org.thingsboard.server.common.data.Dashboard; 29 import org.thingsboard.server.common.data.Dashboard;
@@ -30,7 +34,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -30,7 +34,7 @@ import org.thingsboard.server.common.data.id.TenantId;
30 import org.thingsboard.server.common.data.page.TextPageData; 34 import org.thingsboard.server.common.data.page.TextPageData;
31 import org.thingsboard.server.common.data.page.TextPageLink; 35 import org.thingsboard.server.common.data.page.TextPageLink;
32 import org.thingsboard.server.dao.customer.CustomerDao; 36 import org.thingsboard.server.dao.customer.CustomerDao;
33 -import org.thingsboard.server.dao.entity.BaseEntityService; 37 +import org.thingsboard.server.dao.entity.AbstractEntityService;
34 import org.thingsboard.server.dao.exception.DataValidationException; 38 import org.thingsboard.server.dao.exception.DataValidationException;
35 import org.thingsboard.server.dao.model.*; 39 import org.thingsboard.server.dao.model.*;
36 import org.thingsboard.server.dao.service.DataValidator; 40 import org.thingsboard.server.dao.service.DataValidator;
@@ -42,7 +46,7 @@ import org.thingsboard.server.dao.service.Validator; @@ -42,7 +46,7 @@ import org.thingsboard.server.dao.service.Validator;
42 46
43 @Service 47 @Service
44 @Slf4j 48 @Slf4j
45 -public class DashboardServiceImpl extends BaseEntityService implements DashboardService { 49 +public class DashboardServiceImpl extends AbstractEntityService implements DashboardService {
46 50
47 @Autowired 51 @Autowired
48 private DashboardDao dashboardDao; 52 private DashboardDao dashboardDao;
@@ -65,6 +69,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard @@ -65,6 +69,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard
65 } 69 }
66 70
67 @Override 71 @Override
  72 + public ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId) {
  73 + log.trace("Executing findDashboardByIdAsync [{}]", dashboardId);
  74 + validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
  75 + ListenableFuture<DashboardEntity> dashboardEntity = dashboardDao.findByIdAsync(dashboardId.getId());
  76 + return Futures.transform(dashboardEntity, (Function<? super DashboardEntity, ? extends Dashboard>) input -> getData(input));
  77 + }
  78 +
  79 + @Override
68 public DashboardInfo findDashboardInfoById(DashboardId dashboardId) { 80 public DashboardInfo findDashboardInfoById(DashboardId dashboardId) {
69 log.trace("Executing findDashboardInfoById [{}]", dashboardId); 81 log.trace("Executing findDashboardInfoById [{}]", dashboardId);
70 Validator.validateId(dashboardId, "Incorrect dashboardId " + dashboardId); 82 Validator.validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
@@ -73,6 +85,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard @@ -73,6 +85,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard
73 } 85 }
74 86
75 @Override 87 @Override
  88 + public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId) {
  89 + log.trace("Executing findDashboardInfoByIdAsync [{}]", dashboardId);
  90 + validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
  91 + ListenableFuture<DashboardInfoEntity> dashboardInfoEntity = dashboardInfoDao.findByIdAsync(dashboardId.getId());
  92 + return Futures.transform(dashboardInfoEntity, (Function<? super DashboardInfoEntity, ? extends DashboardInfo>) input -> getData(input));
  93 + }
  94 +
  95 + @Override
76 public Dashboard saveDashboard(Dashboard dashboard) { 96 public Dashboard saveDashboard(Dashboard dashboard) {
77 log.trace("Executing saveDashboard [{}]", dashboard); 97 log.trace("Executing saveDashboard [{}]", dashboard);
78 dashboardValidator.validate(dashboard); 98 dashboardValidator.validate(dashboard);
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device; @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device;
24 import org.thingsboard.server.common.data.page.TextPageLink; 24 import org.thingsboard.server.common.data.page.TextPageLink;
25 import org.thingsboard.server.dao.Dao; 25 import org.thingsboard.server.dao.Dao;
26 import org.thingsboard.server.dao.model.DeviceEntity; 26 import org.thingsboard.server.dao.model.DeviceEntity;
  27 +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity;
27 28
28 /** 29 /**
29 * The Interface DeviceDao. 30 * The Interface DeviceDao.
@@ -49,6 +50,16 @@ public interface DeviceDao extends Dao<DeviceEntity> { @@ -49,6 +50,16 @@ public interface DeviceDao extends Dao<DeviceEntity> {
49 List<DeviceEntity> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink); 50 List<DeviceEntity> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink);
50 51
51 /** 52 /**
  53 + * Find devices by tenantId, type and page link.
  54 + *
  55 + * @param tenantId the tenantId
  56 + * @param type the type
  57 + * @param pageLink the page link
  58 + * @return the list of device objects
  59 + */
  60 + List<DeviceEntity> findDevicesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink);
  61 +
  62 + /**
52 * Find devices by tenantId and devices Ids. 63 * Find devices by tenantId and devices Ids.
53 * 64 *
54 * @param tenantId the tenantId 65 * @param tenantId the tenantId
@@ -68,6 +79,18 @@ public interface DeviceDao extends Dao<DeviceEntity> { @@ -68,6 +79,18 @@ public interface DeviceDao extends Dao<DeviceEntity> {
68 List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); 79 List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink);
69 80
70 /** 81 /**
  82 + * Find devices by tenantId, customerId, type and page link.
  83 + *
  84 + * @param tenantId the tenantId
  85 + * @param customerId the customerId
  86 + * @param type the type
  87 + * @param pageLink the page link
  88 + * @return the list of device objects
  89 + */
  90 + List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink);
  91 +
  92 +
  93 + /**
71 * Find devices by tenantId, customerId and devices Ids. 94 * Find devices by tenantId, customerId and devices Ids.
72 * 95 *
73 * @param tenantId the tenantId 96 * @param tenantId the tenantId
@@ -85,4 +108,11 @@ public interface DeviceDao extends Dao<DeviceEntity> { @@ -85,4 +108,11 @@ public interface DeviceDao extends Dao<DeviceEntity> {
85 * @return the optional device object 108 * @return the optional device object
86 */ 109 */
87 Optional<DeviceEntity> findDevicesByTenantIdAndName(UUID tenantId, String name); 110 Optional<DeviceEntity> findDevicesByTenantIdAndName(UUID tenantId, String name);
  111 +
  112 + /**
  113 + * Find tenants device types.
  114 + *
  115 + * @return the list of tenant device type objects
  116 + */
  117 + ListenableFuture<List<TenantDeviceTypeEntity>> findTenantDeviceTypesAsync();
88 } 118 }
@@ -22,7 +22,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.*; @@ -22,7 +22,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.*;
22 22
23 import java.util.*; 23 import java.util.*;
24 24
  25 +import com.datastax.driver.core.ResultSet;
  26 +import com.datastax.driver.core.ResultSetFuture;
25 import com.datastax.driver.core.querybuilder.Select; 27 import com.datastax.driver.core.querybuilder.Select;
  28 +import com.datastax.driver.mapping.Result;
  29 +import com.google.common.base.Function;
  30 +import com.google.common.util.concurrent.Futures;
26 import com.google.common.util.concurrent.ListenableFuture; 31 import com.google.common.util.concurrent.ListenableFuture;
27 import lombok.extern.slf4j.Slf4j; 32 import lombok.extern.slf4j.Slf4j;
28 import org.springframework.stereotype.Component; 33 import org.springframework.stereotype.Component;
@@ -32,6 +37,9 @@ import org.thingsboard.server.dao.AbstractSearchTextDao; @@ -32,6 +37,9 @@ import org.thingsboard.server.dao.AbstractSearchTextDao;
32 import org.thingsboard.server.dao.model.DeviceEntity; 37 import org.thingsboard.server.dao.model.DeviceEntity;
33 import org.slf4j.Logger; 38 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory; 39 import org.slf4j.LoggerFactory;
  40 +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity;
  41 +
  42 +import javax.annotation.Nullable;
35 43
36 @Component 44 @Component
37 @Slf4j 45 @Slf4j
@@ -64,6 +72,16 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement @@ -64,6 +72,16 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement
64 } 72 }
65 73
66 @Override 74 @Override
  75 + public List<DeviceEntity> findDevicesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
  76 + log.debug("Try to find devices by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
  77 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  78 + Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type),
  79 + eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), pageLink);
  80 + log.trace("Found devices [{}] by tenantId [{}], type [{}] and pageLink [{}]", deviceEntities, tenantId, type, pageLink);
  81 + return deviceEntities;
  82 + }
  83 +
  84 + @Override
67 public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) { 85 public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) {
68 log.debug("Try to find devices by tenantId [{}] and device Ids [{}]", tenantId, deviceIds); 86 log.debug("Try to find devices by tenantId [{}] and device Ids [{}]", tenantId, deviceIds);
69 Select select = select().from(getColumnFamilyName()); 87 Select select = select().from(getColumnFamilyName());
@@ -75,7 +93,7 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement @@ -75,7 +93,7 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement
75 93
76 @Override 94 @Override
77 public List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) { 95 public List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
78 - log.debug("Try to find devices by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink); 96 + log.debug("Try to find devices by tenantId [{}], customerId [{}] and pageLink [{}]", tenantId, customerId, pageLink);
79 List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, 97 List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
80 Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId), 98 Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId),
81 eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), 99 eq(DEVICE_TENANT_ID_PROPERTY, tenantId)),
@@ -86,6 +104,19 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement @@ -86,6 +104,19 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement
86 } 104 }
87 105
88 @Override 106 @Override
  107 + public List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
  108 + log.debug("Try to find devices by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink);
  109 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  110 + Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type),
  111 + eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId),
  112 + eq(DEVICE_TENANT_ID_PROPERTY, tenantId)),
  113 + pageLink);
  114 +
  115 + log.trace("Found devices [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", deviceEntities, tenantId, customerId, type, pageLink);
  116 + return deviceEntities;
  117 + }
  118 +
  119 + @Override
89 public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) { 120 public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) {
90 log.debug("Try to find devices by tenantId [{}], customerId [{}] and device Ids [{}]", tenantId, customerId, deviceIds); 121 log.debug("Try to find devices by tenantId [{}], customerId [{}] and device Ids [{}]", tenantId, customerId, deviceIds);
91 Select select = select().from(getColumnFamilyName()); 122 Select select = select().from(getColumnFamilyName());
@@ -105,4 +136,24 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement @@ -105,4 +136,24 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement
105 return Optional.ofNullable(findOneByStatement(query)); 136 return Optional.ofNullable(findOneByStatement(query));
106 } 137 }
107 138
  139 + @Override
  140 + public ListenableFuture<List<TenantDeviceTypeEntity>> findTenantDeviceTypesAsync() {
  141 + Select statement = select().distinct().column(DEVICE_TYPE_PROPERTY).column(DEVICE_TENANT_ID_PROPERTY).from(DEVICE_TYPES_BY_TENANT_VIEW_NAME);
  142 + statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
  143 + ResultSetFuture resultSetFuture = getSession().executeAsync(statement);
  144 + ListenableFuture<List<TenantDeviceTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantDeviceTypeEntity>>() {
  145 + @Nullable
  146 + @Override
  147 + public List<TenantDeviceTypeEntity> apply(@Nullable ResultSet resultSet) {
  148 + Result<TenantDeviceTypeEntity> result = cluster.getMapper(TenantDeviceTypeEntity.class).map(resultSet);
  149 + if (result != null) {
  150 + return result.all();
  151 + } else {
  152 + return Collections.emptyList();
  153 + }
  154 + }
  155 + });
  156 + return result;
  157 + }
  158 +
108 } 159 }
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device; @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.Device; 19 import org.thingsboard.server.common.data.Device;
  20 +import org.thingsboard.server.common.data.TenantDeviceType;
20 import org.thingsboard.server.common.data.id.CustomerId; 21 import org.thingsboard.server.common.data.id.CustomerId;
21 import org.thingsboard.server.common.data.id.DeviceId; 22 import org.thingsboard.server.common.data.id.DeviceId;
22 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
@@ -44,16 +45,22 @@ public interface DeviceService { @@ -44,16 +45,22 @@ public interface DeviceService {
44 45
45 TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink); 46 TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink);
46 47
  48 + TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink);
  49 +
47 ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); 50 ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds);
48 51
49 void deleteDevicesByTenantId(TenantId tenantId); 52 void deleteDevicesByTenantId(TenantId tenantId);
50 53
51 TextPageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); 54 TextPageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink);
52 55
  56 + TextPageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink);
  57 +
53 ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); 58 ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds);
54 59
55 void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); 60 void unassignCustomerDevices(TenantId tenantId, CustomerId customerId);
56 61
57 ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query); 62 ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query);
58 63
  64 + ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId);
  65 +
59 } 66 }
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service;
26 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
27 import org.thingsboard.server.common.data.Device; 27 import org.thingsboard.server.common.data.Device;
28 import org.thingsboard.server.common.data.EntityType; 28 import org.thingsboard.server.common.data.EntityType;
  29 +import org.thingsboard.server.common.data.TenantDeviceType;
29 import org.thingsboard.server.common.data.id.CustomerId; 30 import org.thingsboard.server.common.data.id.CustomerId;
30 import org.thingsboard.server.common.data.id.DeviceId; 31 import org.thingsboard.server.common.data.id.DeviceId;
31 import org.thingsboard.server.common.data.id.EntityId; 32 import org.thingsboard.server.common.data.id.EntityId;
@@ -36,10 +37,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation; @@ -36,10 +37,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
36 import org.thingsboard.server.common.data.security.DeviceCredentials; 37 import org.thingsboard.server.common.data.security.DeviceCredentials;
37 import org.thingsboard.server.common.data.security.DeviceCredentialsType; 38 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
38 import org.thingsboard.server.dao.customer.CustomerDao; 39 import org.thingsboard.server.dao.customer.CustomerDao;
39 -import org.thingsboard.server.dao.entity.BaseEntityService; 40 +import org.thingsboard.server.dao.entity.AbstractEntityService;
40 import org.thingsboard.server.dao.exception.DataValidationException; 41 import org.thingsboard.server.dao.exception.DataValidationException;
41 import org.thingsboard.server.dao.model.CustomerEntity; 42 import org.thingsboard.server.dao.model.CustomerEntity;
42 import org.thingsboard.server.dao.model.DeviceEntity; 43 import org.thingsboard.server.dao.model.DeviceEntity;
  44 +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity;
43 import org.thingsboard.server.dao.model.TenantEntity; 45 import org.thingsboard.server.dao.model.TenantEntity;
44 import org.thingsboard.server.dao.relation.EntitySearchDirection; 46 import org.thingsboard.server.dao.relation.EntitySearchDirection;
45 import org.thingsboard.server.dao.service.DataValidator; 47 import org.thingsboard.server.dao.service.DataValidator;
@@ -47,9 +49,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; @@ -47,9 +49,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover;
47 import org.thingsboard.server.dao.tenant.TenantDao; 49 import org.thingsboard.server.dao.tenant.TenantDao;
48 50
49 import javax.annotation.Nullable; 51 import javax.annotation.Nullable;
50 -import java.util.ArrayList;  
51 -import java.util.List;  
52 -import java.util.Optional; 52 +import java.util.*;
53 import java.util.stream.Collectors; 53 import java.util.stream.Collectors;
54 54
55 import static org.thingsboard.server.dao.DaoUtil.*; 55 import static org.thingsboard.server.dao.DaoUtil.*;
@@ -58,7 +58,7 @@ import static org.thingsboard.server.dao.service.Validator.*; @@ -58,7 +58,7 @@ import static org.thingsboard.server.dao.service.Validator.*;
58 58
59 @Service 59 @Service
60 @Slf4j 60 @Slf4j
61 -public class DeviceServiceImpl extends BaseEntityService implements DeviceService { 61 +public class DeviceServiceImpl extends AbstractEntityService implements DeviceService {
62 62
63 @Autowired 63 @Autowired
64 private DeviceDao deviceDao; 64 private DeviceDao deviceDao;
@@ -148,7 +148,18 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic @@ -148,7 +148,18 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic
148 validatePageLink(pageLink, "Incorrect page link " + pageLink); 148 validatePageLink(pageLink, "Incorrect page link " + pageLink);
149 List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantId(tenantId.getId(), pageLink); 149 List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantId(tenantId.getId(), pageLink);
150 List<Device> devices = convertDataList(deviceEntities); 150 List<Device> devices = convertDataList(deviceEntities);
151 - return new TextPageData<Device>(devices, pageLink); 151 + return new TextPageData<>(devices, pageLink);
  152 + }
  153 +
  154 + @Override
  155 + public TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink) {
  156 + log.trace("Executing findDevicesByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink);
  157 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  158 + validateString(type, "Incorrect type " + type);
  159 + validatePageLink(pageLink, "Incorrect page link " + pageLink);
  160 + List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndType(tenantId.getId(), type, pageLink);
  161 + List<Device> devices = convertDataList(deviceEntities);
  162 + return new TextPageData<>(devices, pageLink);
152 } 163 }
153 164
154 @Override 165 @Override
@@ -176,7 +187,19 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic @@ -176,7 +187,19 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic
176 validatePageLink(pageLink, "Incorrect page link " + pageLink); 187 validatePageLink(pageLink, "Incorrect page link " + pageLink);
177 List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); 188 List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink);
178 List<Device> devices = convertDataList(deviceEntities); 189 List<Device> devices = convertDataList(deviceEntities);
179 - return new TextPageData<Device>(devices, pageLink); 190 + return new TextPageData<>(devices, pageLink);
  191 + }
  192 +
  193 + @Override
  194 + public TextPageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink) {
  195 + log.trace("Executing findDevicesByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink);
  196 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  197 + validateId(customerId, "Incorrect customerId " + customerId);
  198 + validateString(type, "Incorrect type " + type);
  199 + validatePageLink(pageLink, "Incorrect page link " + pageLink);
  200 + List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink);
  201 + List<Device> devices = convertDataList(deviceEntities);
  202 + return new TextPageData<>(devices, pageLink);
180 } 203 }
181 204
182 @Override 205 @Override
@@ -224,6 +247,25 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic @@ -224,6 +247,25 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic
224 return devices; 247 return devices;
225 } 248 }
226 249
  250 + @Override
  251 + public ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId) {
  252 + log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId);
  253 + validateId(tenantId, "Incorrect tenantId " + tenantId);
  254 + ListenableFuture<List<TenantDeviceTypeEntity>> tenantDeviceTypeEntities = deviceDao.findTenantDeviceTypesAsync();
  255 + ListenableFuture<List<TenantDeviceType>> tenantDeviceTypes = Futures.transform(tenantDeviceTypeEntities,
  256 + (Function<List<TenantDeviceTypeEntity>, List<TenantDeviceType>>) deviceTypeEntities -> {
  257 + List<TenantDeviceType> deviceTypes = new ArrayList<>();
  258 + for (TenantDeviceTypeEntity deviceTypeEntity : deviceTypeEntities) {
  259 + if (deviceTypeEntity.getTenantId().equals(tenantId.getId())) {
  260 + deviceTypes.add(deviceTypeEntity.toTenantDeviceType());
  261 + }
  262 + }
  263 + deviceTypes.sort((TenantDeviceType o1, TenantDeviceType o2) -> o1.getType().compareTo(o2.getType()));
  264 + return deviceTypes;
  265 + });
  266 + return tenantDeviceTypes;
  267 + }
  268 +
227 private DataValidator<Device> deviceValidator = 269 private DataValidator<Device> deviceValidator =
228 new DataValidator<Device>() { 270 new DataValidator<Device>() {
229 271
@@ -249,6 +291,9 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic @@ -249,6 +291,9 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic
249 291
250 @Override 292 @Override
251 protected void validateDataImpl(Device device) { 293 protected void validateDataImpl(Device device) {
  294 + if (StringUtils.isEmpty(device.getType())) {
  295 + throw new DataValidationException("Device type should be specified!");
  296 + }
252 if (StringUtils.isEmpty(device.getName())) { 297 if (StringUtils.isEmpty(device.getName())) {
253 throw new DataValidationException("Device name should be specified!"); 298 throw new DataValidationException("Device name should be specified!");
254 } 299 }
  1 +/**
  2 + * Copyright © 2016-2017 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 +package org.thingsboard.server.dao.entity;
  18 +
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.thingsboard.server.common.data.id.EntityId;
  22 +import org.thingsboard.server.dao.relation.RelationService;
  23 +
  24 +@Slf4j
  25 +public abstract class AbstractEntityService {
  26 +
  27 + @Autowired
  28 + protected RelationService relationService;
  29 +
  30 + protected void deleteEntityRelations(EntityId entityId) {
  31 + log.trace("Executing deleteEntityRelations [{}]", entityId);
  32 + relationService.deleteEntityRelations(entityId);
  33 + }
  34 +
  35 +
  36 +}
@@ -15,23 +15,102 @@ @@ -15,23 +15,102 @@
15 */ 15 */
16 package org.thingsboard.server.dao.entity; 16 package org.thingsboard.server.dao.entity;
17 17
  18 +import com.google.common.base.Function;
  19 +import com.google.common.util.concurrent.Futures;
  20 +import com.google.common.util.concurrent.ListenableFuture;
18 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
20 -import org.thingsboard.server.common.data.id.EntityId;  
21 -import org.thingsboard.server.dao.relation.RelationService; 23 +import org.springframework.stereotype.Service;
  24 +import org.thingsboard.server.common.data.*;
  25 +import org.thingsboard.server.common.data.alarm.AlarmId;
  26 +import org.thingsboard.server.common.data.id.*;
  27 +import org.thingsboard.server.dao.alarm.AlarmService;
  28 +import org.thingsboard.server.dao.asset.AssetService;
  29 +import org.thingsboard.server.dao.customer.CustomerService;
  30 +import org.thingsboard.server.dao.dashboard.DashboardService;
  31 +import org.thingsboard.server.dao.device.DeviceService;
  32 +import org.thingsboard.server.dao.plugin.PluginService;
  33 +import org.thingsboard.server.dao.rule.RuleService;
  34 +import org.thingsboard.server.dao.tenant.TenantService;
  35 +import org.thingsboard.server.dao.user.UserService;
22 36
23 /** 37 /**
24 * Created by ashvayka on 04.05.17. 38 * Created by ashvayka on 04.05.17.
25 */ 39 */
  40 +@Service
26 @Slf4j 41 @Slf4j
27 -public class BaseEntityService { 42 +public class BaseEntityService extends AbstractEntityService implements EntityService {
28 43
29 @Autowired 44 @Autowired
30 - protected RelationService relationService; 45 + private AssetService assetService;
31 46
32 - protected void deleteEntityRelations(EntityId entityId) {  
33 - log.trace("Executing deleteEntityRelations [{}]", entityId);  
34 - relationService.deleteEntityRelations(entityId); 47 + @Autowired
  48 + private DeviceService deviceService;
  49 +
  50 + @Autowired
  51 + private RuleService ruleService;
  52 +
  53 + @Autowired
  54 + private PluginService pluginService;
  55 +
  56 + @Autowired
  57 + private TenantService tenantService;
  58 +
  59 + @Autowired
  60 + private CustomerService customerService;
  61 +
  62 + @Autowired
  63 + private UserService userService;
  64 +
  65 + @Autowired
  66 + private DashboardService dashboardService;
  67 +
  68 + @Autowired
  69 + private AlarmService alarmService;
  70 +
  71 + @Override
  72 + public void deleteEntityRelations(EntityId entityId) {
  73 + super.deleteEntityRelations(entityId);
  74 + }
  75 +
  76 + @Override
  77 + public ListenableFuture<String> fetchEntityNameAsync(EntityId entityId) {
  78 + log.trace("Executing fetchEntityNameAsync [{}]", entityId);
  79 + ListenableFuture<String> entityName;
  80 + ListenableFuture<? extends HasName> hasName;
  81 + switch (entityId.getEntityType()) {
  82 + case ASSET:
  83 + hasName = assetService.findAssetByIdAsync(new AssetId(entityId.getId()));
  84 + break;
  85 + case DEVICE:
  86 + hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId()));
  87 + break;
  88 + case RULE:
  89 + hasName = ruleService.findRuleByIdAsync(new RuleId(entityId.getId()));
  90 + break;
  91 + case PLUGIN:
  92 + hasName = pluginService.findPluginByIdAsync(new PluginId(entityId.getId()));
  93 + break;
  94 + case TENANT:
  95 + hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
  96 + break;
  97 + case CUSTOMER:
  98 + hasName = customerService.findCustomerByIdAsync(new CustomerId(entityId.getId()));
  99 + break;
  100 + case USER:
  101 + hasName = userService.findUserByIdAsync(new UserId(entityId.getId()));
  102 + break;
  103 + case DASHBOARD:
  104 + hasName = dashboardService.findDashboardInfoByIdAsync(new DashboardId(entityId.getId()));
  105 + break;
  106 + case ALARM:
  107 + hasName = alarmService.findAlarmByIdAsync(new AlarmId(entityId.getId()));
  108 + break;
  109 + default:
  110 + throw new IllegalStateException("Not Implemented!");
  111 + }
  112 + entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1.getName() );
  113 + return entityName;
35 } 114 }
36 115
37 } 116 }
  1 +/**
  2 + * Copyright © 2016-2017 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 +package org.thingsboard.server.dao.entity;
  18 +
  19 +import com.google.common.util.concurrent.ListenableFuture;
  20 +import org.thingsboard.server.common.data.id.EntityId;
  21 +
  22 +public interface EntityService {
  23 +
  24 + ListenableFuture<String> fetchEntityNameAsync(EntityId entityId);
  25 +
  26 + void deleteEntityRelations(EntityId entityId);
  27 +
  28 +}
@@ -49,12 +49,13 @@ public final class AssetEntity implements SearchTextEntity<Asset> { @@ -49,12 +49,13 @@ public final class AssetEntity implements SearchTextEntity<Asset> {
49 @Column(name = ASSET_CUSTOMER_ID_PROPERTY) 49 @Column(name = ASSET_CUSTOMER_ID_PROPERTY)
50 private UUID customerId; 50 private UUID customerId;
51 51
52 - @Column(name = ASSET_NAME_PROPERTY)  
53 - private String name;  
54 - 52 + @PartitionKey(value = 3)
55 @Column(name = ASSET_TYPE_PROPERTY) 53 @Column(name = ASSET_TYPE_PROPERTY)
56 private String type; 54 private String type;
57 55
  56 + @Column(name = ASSET_NAME_PROPERTY)
  57 + private String name;
  58 +
58 @Column(name = SEARCH_TEXT_PROPERTY) 59 @Column(name = SEARCH_TEXT_PROPERTY)
59 private String searchText; 60 private String searchText;
60 61
@@ -49,12 +49,13 @@ public final class DeviceEntity implements SearchTextEntity<Device> { @@ -49,12 +49,13 @@ public final class DeviceEntity implements SearchTextEntity<Device> {
49 @Column(name = DEVICE_CUSTOMER_ID_PROPERTY) 49 @Column(name = DEVICE_CUSTOMER_ID_PROPERTY)
50 private UUID customerId; 50 private UUID customerId;
51 51
52 - @Column(name = DEVICE_NAME_PROPERTY)  
53 - private String name;  
54 - 52 + @PartitionKey(value = 3)
55 @Column(name = DEVICE_TYPE_PROPERTY) 53 @Column(name = DEVICE_TYPE_PROPERTY)
56 private String type; 54 private String type;
57 55
  56 + @Column(name = DEVICE_NAME_PROPERTY)
  57 + private String name;
  58 +
58 @Column(name = SEARCH_TEXT_PROPERTY) 59 @Column(name = SEARCH_TEXT_PROPERTY)
59 private String searchText; 60 private String searchText;
60 61
@@ -124,8 +124,11 @@ public class ModelConstants { @@ -124,8 +124,11 @@ public class ModelConstants {
124 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 124 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
125 125
126 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; 126 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text";
  127 + public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text";
127 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; 128 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text";
  129 + public static final String DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_by_type_and_search_text";
128 public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name"; 130 public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name";
  131 + public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant";
129 132
130 /** 133 /**
131 * Cassandra asset constants. 134 * Cassandra asset constants.
@@ -138,8 +141,11 @@ public class ModelConstants { @@ -138,8 +141,11 @@ public class ModelConstants {
138 public static final String ASSET_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 141 public static final String ASSET_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
139 142
140 public static final String ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_and_search_text"; 143 public static final String ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_and_search_text";
  144 + public static final String ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_by_type_and_search_text";
141 public static final String ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_and_search_text"; 145 public static final String ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_and_search_text";
  146 + public static final String ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_by_type_and_search_text";
142 public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name"; 147 public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name";
  148 + public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant";
143 149
144 /** 150 /**
145 * Cassandra entity relation constants. 151 * Cassandra entity relation constants.
  1 +/**
  2 + * Copyright © 2016-2017 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 +package org.thingsboard.server.dao.model;
  18 +
  19 +import com.datastax.driver.mapping.annotations.Column;
  20 +import com.datastax.driver.mapping.annotations.PartitionKey;
  21 +import com.datastax.driver.mapping.annotations.Table;
  22 +import com.datastax.driver.mapping.annotations.Transient;
  23 +import org.thingsboard.server.common.data.asset.TenantAssetType;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +import static org.thingsboard.server.dao.model.ModelConstants.*;
  29 +
  30 +@Table(name = ASSET_TYPES_BY_TENANT_VIEW_NAME)
  31 +public class TenantAssetTypeEntity {
  32 +
  33 + @Transient
  34 + private static final long serialVersionUID = -1268181161886910152L;
  35 +
  36 + @PartitionKey(value = 0)
  37 + @Column(name = ASSET_TYPE_PROPERTY)
  38 + private String type;
  39 +
  40 + @PartitionKey(value = 1)
  41 + @Column(name = ASSET_TENANT_ID_PROPERTY)
  42 + private UUID tenantId;
  43 +
  44 + public TenantAssetTypeEntity() {
  45 + super();
  46 + }
  47 +
  48 + public TenantAssetTypeEntity(TenantAssetType tenantAssetType) {
  49 + this.type = tenantAssetType.getType();
  50 + if (tenantAssetType.getTenantId() != null) {
  51 + this.tenantId = tenantAssetType.getTenantId().getId();
  52 + }
  53 + }
  54 +
  55 + public String getType() {
  56 + return type;
  57 + }
  58 +
  59 + public void setType(String type) {
  60 + this.type = type;
  61 + }
  62 +
  63 + public UUID getTenantId() {
  64 + return tenantId;
  65 + }
  66 +
  67 + public void setTenantId(UUID tenantId) {
  68 + this.tenantId = tenantId;
  69 + }
  70 +
  71 + @Override
  72 + public int hashCode() {
  73 + int result = type != null ? type.hashCode() : 0;
  74 + result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
  75 + return result;
  76 + }
  77 +
  78 + @Override
  79 + public boolean equals(Object o) {
  80 + if (this == o) return true;
  81 + if (o == null || getClass() != o.getClass()) return false;
  82 +
  83 + TenantAssetTypeEntity that = (TenantAssetTypeEntity) o;
  84 +
  85 + if (type != null ? !type.equals(that.type) : that.type != null) return false;
  86 + return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
  87 +
  88 + }
  89 +
  90 + @Override
  91 + public String toString() {
  92 + final StringBuilder sb = new StringBuilder("TenantAssetTypeEntity{");
  93 + sb.append("type='").append(type).append('\'');
  94 + sb.append(", tenantId=").append(tenantId);
  95 + sb.append('}');
  96 + return sb.toString();
  97 + }
  98 +
  99 + public TenantAssetType toTenantAssetType() {
  100 + TenantAssetType tenantAssetType = new TenantAssetType();
  101 + tenantAssetType.setType(type);
  102 + if (tenantId != null) {
  103 + tenantAssetType.setTenantId(new TenantId(tenantId));
  104 + }
  105 + return tenantAssetType;
  106 + }
  107 +}
  1 +/**
  2 + * Copyright © 2016-2017 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 +package org.thingsboard.server.dao.model;
  18 +
  19 +import com.datastax.driver.mapping.annotations.Column;
  20 +import com.datastax.driver.mapping.annotations.PartitionKey;
  21 +import com.datastax.driver.mapping.annotations.Table;
  22 +import com.datastax.driver.mapping.annotations.Transient;
  23 +import org.thingsboard.server.common.data.TenantDeviceType;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +import static org.thingsboard.server.dao.model.ModelConstants.*;
  29 +
  30 +@Table(name = DEVICE_TYPES_BY_TENANT_VIEW_NAME)
  31 +public class TenantDeviceTypeEntity {
  32 +
  33 + @Transient
  34 + private static final long serialVersionUID = -1268181166886910152L;
  35 +
  36 + @PartitionKey(value = 0)
  37 + @Column(name = DEVICE_TYPE_PROPERTY)
  38 + private String type;
  39 +
  40 + @PartitionKey(value = 1)
  41 + @Column(name = DEVICE_TENANT_ID_PROPERTY)
  42 + private UUID tenantId;
  43 +
  44 + public TenantDeviceTypeEntity() {
  45 + super();
  46 + }
  47 +
  48 + public TenantDeviceTypeEntity(TenantDeviceType tenantDeviceType) {
  49 + this.type = tenantDeviceType.getType();
  50 + if (tenantDeviceType.getTenantId() != null) {
  51 + this.tenantId = tenantDeviceType.getTenantId().getId();
  52 + }
  53 + }
  54 +
  55 + public String getType() {
  56 + return type;
  57 + }
  58 +
  59 + public void setType(String type) {
  60 + this.type = type;
  61 + }
  62 +
  63 + public UUID getTenantId() {
  64 + return tenantId;
  65 + }
  66 +
  67 + public void setTenantId(UUID tenantId) {
  68 + this.tenantId = tenantId;
  69 + }
  70 +
  71 + @Override
  72 + public int hashCode() {
  73 + int result = type != null ? type.hashCode() : 0;
  74 + result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
  75 + return result;
  76 + }
  77 +
  78 + @Override
  79 + public boolean equals(Object o) {
  80 + if (this == o) return true;
  81 + if (o == null || getClass() != o.getClass()) return false;
  82 +
  83 + TenantDeviceTypeEntity that = (TenantDeviceTypeEntity) o;
  84 +
  85 + if (type != null ? !type.equals(that.type) : that.type != null) return false;
  86 + return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
  87 +
  88 + }
  89 +
  90 + @Override
  91 + public String toString() {
  92 + final StringBuilder sb = new StringBuilder("TenantDeviceTypeEntity{");
  93 + sb.append("type='").append(type).append('\'');
  94 + sb.append(", tenantId=").append(tenantId);
  95 + sb.append('}');
  96 + return sb.toString();
  97 + }
  98 +
  99 + public TenantDeviceType toTenantDeviceType() {
  100 + TenantDeviceType tenantDeviceType = new TenantDeviceType();
  101 + tenantDeviceType.setType(type);
  102 + if (tenantId != null) {
  103 + tenantDeviceType.setTenantId(new TenantId(tenantId));
  104 + }
  105 + return tenantDeviceType;
  106 + }
  107 +}
@@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils; @@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
24 import org.thingsboard.server.common.data.id.PluginId; 24 import org.thingsboard.server.common.data.id.PluginId;
25 -import org.thingsboard.server.common.data.id.RuleId;  
26 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.data.page.TextPageData; 26 import org.thingsboard.server.common.data.page.TextPageData;
28 import org.thingsboard.server.common.data.page.TextPageLink; 27 import org.thingsboard.server.common.data.page.TextPageLink;
@@ -30,9 +29,8 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; @@ -30,9 +29,8 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
30 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; 29 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
31 import org.thingsboard.server.common.data.plugin.ComponentType; 30 import org.thingsboard.server.common.data.plugin.ComponentType;
32 import org.thingsboard.server.common.data.plugin.PluginMetaData; 31 import org.thingsboard.server.common.data.plugin.PluginMetaData;
33 -import org.thingsboard.server.common.data.rule.RuleMetaData;  
34 import org.thingsboard.server.dao.component.ComponentDescriptorService; 32 import org.thingsboard.server.dao.component.ComponentDescriptorService;
35 -import org.thingsboard.server.dao.entity.BaseEntityService; 33 +import org.thingsboard.server.dao.entity.AbstractEntityService;
36 import org.thingsboard.server.dao.exception.DataValidationException; 34 import org.thingsboard.server.dao.exception.DataValidationException;
37 import org.thingsboard.server.dao.exception.DatabaseException; 35 import org.thingsboard.server.dao.exception.DatabaseException;
38 import org.thingsboard.server.dao.exception.IncorrectParameterException; 36 import org.thingsboard.server.dao.exception.IncorrectParameterException;
@@ -55,7 +53,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @@ -55,7 +53,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
55 53
56 @Service 54 @Service
57 @Slf4j 55 @Slf4j
58 -public class BasePluginService extends BaseEntityService implements PluginService { 56 +public class BasePluginService extends AbstractEntityService implements PluginService {
59 57
60 //TODO: move to a better place. 58 //TODO: move to a better place.
61 public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); 59 public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID);
@@ -23,9 +23,24 @@ import lombok.extern.slf4j.Slf4j; @@ -23,9 +23,24 @@ import lombok.extern.slf4j.Slf4j;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
25 import org.springframework.util.StringUtils; 25 import org.springframework.util.StringUtils;
  26 +import org.thingsboard.server.common.data.BaseData;
  27 +import org.thingsboard.server.common.data.Device;
  28 +import org.thingsboard.server.common.data.EntityType;
  29 +import org.thingsboard.server.common.data.asset.Asset;
  30 +import org.thingsboard.server.common.data.id.AssetId;
  31 +import org.thingsboard.server.common.data.id.DeviceId;
26 import org.thingsboard.server.common.data.id.EntityId; 32 import org.thingsboard.server.common.data.id.EntityId;
  33 +import org.thingsboard.server.common.data.id.UUIDBased;
27 import org.thingsboard.server.common.data.relation.EntityRelation; 34 import org.thingsboard.server.common.data.relation.EntityRelation;
  35 +import org.thingsboard.server.common.data.relation.EntityRelationInfo;
  36 +import org.thingsboard.server.dao.asset.AssetService;
  37 +import org.thingsboard.server.dao.customer.CustomerService;
  38 +import org.thingsboard.server.dao.device.DeviceService;
  39 +import org.thingsboard.server.dao.entity.EntityService;
28 import org.thingsboard.server.dao.exception.DataValidationException; 40 import org.thingsboard.server.dao.exception.DataValidationException;
  41 +import org.thingsboard.server.dao.plugin.PluginService;
  42 +import org.thingsboard.server.dao.rule.RuleService;
  43 +import org.thingsboard.server.dao.tenant.TenantService;
29 44
30 import javax.annotation.Nullable; 45 import javax.annotation.Nullable;
31 import java.util.*; 46 import java.util.*;
@@ -41,6 +56,9 @@ public class BaseRelationService implements RelationService { @@ -41,6 +56,9 @@ public class BaseRelationService implements RelationService {
41 @Autowired 56 @Autowired
42 private RelationDao relationDao; 57 private RelationDao relationDao;
43 58
  59 + @Autowired
  60 + private EntityService entityService;
  61 +
44 @Override 62 @Override
45 public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType) { 63 public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType) {
46 log.trace("Executing checkRelation [{}][{}][{}]", from, to, relationType); 64 log.trace("Executing checkRelation [{}][{}][{}]", from, to, relationType);
@@ -100,6 +118,31 @@ public class BaseRelationService implements RelationService { @@ -100,6 +118,31 @@ public class BaseRelationService implements RelationService {
100 } 118 }
101 119
102 @Override 120 @Override
  121 + public ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from) {
  122 + log.trace("Executing findInfoByFrom [{}]", from);
  123 + validate(from);
  124 + ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(from);
  125 + ListenableFuture<List<EntityRelationInfo>> relationsInfo = Futures.transform(relations,
  126 + (AsyncFunction<List<EntityRelation>, List<EntityRelationInfo>>) relations1 -> {
  127 + List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
  128 + relations1.stream().forEach(relation -> futures.add(fetchRelationInfoAsync(relation)));
  129 + return Futures.successfulAsList(futures);
  130 + });
  131 + return relationsInfo;
  132 + }
  133 +
  134 + private ListenableFuture<EntityRelationInfo> fetchRelationInfoAsync(EntityRelation relation) {
  135 + ListenableFuture<String> entityName = entityService.fetchEntityNameAsync(relation.getTo());
  136 + ListenableFuture<EntityRelationInfo> entityRelationInfo =
  137 + Futures.transform(entityName, (Function<String, EntityRelationInfo>) entityName1 -> {
  138 + EntityRelationInfo entityRelationInfo1 = new EntityRelationInfo(relation);
  139 + entityRelationInfo1.setToName(entityName1);
  140 + return entityRelationInfo1;
  141 + });
  142 + return entityRelationInfo;
  143 + }
  144 +
  145 + @Override
103 public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) { 146 public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
104 log.trace("Executing findByFromAndType [{}][{}]", from, relationType); 147 log.trace("Executing findByFromAndType [{}][{}]", from, relationType);
105 validate(from); 148 validate(from);
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.relation; @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.relation;
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.id.EntityId; 19 import org.thingsboard.server.common.data.id.EntityId;
20 import org.thingsboard.server.common.data.relation.EntityRelation; 20 import org.thingsboard.server.common.data.relation.EntityRelation;
  21 +import org.thingsboard.server.common.data.relation.EntityRelationInfo;
21 22
22 import java.util.List; 23 import java.util.List;
23 24
@@ -38,6 +39,8 @@ public interface RelationService { @@ -38,6 +39,8 @@ public interface RelationService {
38 39
39 ListenableFuture<List<EntityRelation>> findByFrom(EntityId from); 40 ListenableFuture<List<EntityRelation>> findByFrom(EntityId from);
40 41
  42 + ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from);
  43 +
41 ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType); 44 ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType);
42 45
43 ListenableFuture<List<EntityRelation>> findByTo(EntityId to); 46 ListenableFuture<List<EntityRelation>> findByTo(EntityId to);
@@ -23,7 +23,6 @@ import lombok.extern.slf4j.Slf4j; @@ -23,7 +23,6 @@ import lombok.extern.slf4j.Slf4j;
23 import org.apache.commons.lang3.StringUtils; 23 import org.apache.commons.lang3.StringUtils;
24 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
26 -import org.thingsboard.server.common.data.asset.Asset;  
27 import org.thingsboard.server.common.data.id.RuleId; 26 import org.thingsboard.server.common.data.id.RuleId;
28 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
29 import org.thingsboard.server.common.data.page.TextPageData; 28 import org.thingsboard.server.common.data.page.TextPageData;
@@ -34,11 +33,10 @@ import org.thingsboard.server.common.data.plugin.ComponentType; @@ -34,11 +33,10 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
34 import org.thingsboard.server.common.data.plugin.PluginMetaData; 33 import org.thingsboard.server.common.data.plugin.PluginMetaData;
35 import org.thingsboard.server.common.data.rule.RuleMetaData; 34 import org.thingsboard.server.common.data.rule.RuleMetaData;
36 import org.thingsboard.server.dao.component.ComponentDescriptorService; 35 import org.thingsboard.server.dao.component.ComponentDescriptorService;
37 -import org.thingsboard.server.dao.entity.BaseEntityService; 36 +import org.thingsboard.server.dao.entity.AbstractEntityService;
38 import org.thingsboard.server.dao.exception.DataValidationException; 37 import org.thingsboard.server.dao.exception.DataValidationException;
39 import org.thingsboard.server.dao.exception.DatabaseException; 38 import org.thingsboard.server.dao.exception.DatabaseException;
40 import org.thingsboard.server.dao.exception.IncorrectParameterException; 39 import org.thingsboard.server.dao.exception.IncorrectParameterException;
41 -import org.thingsboard.server.dao.model.AssetEntity;  
42 import org.thingsboard.server.dao.model.RuleMetaDataEntity; 40 import org.thingsboard.server.dao.model.RuleMetaDataEntity;
43 import org.thingsboard.server.dao.plugin.PluginService; 41 import org.thingsboard.server.dao.plugin.PluginService;
44 import org.thingsboard.server.dao.service.DataValidator; 42 import org.thingsboard.server.dao.service.DataValidator;
@@ -58,7 +56,7 @@ import static org.thingsboard.server.dao.service.Validator.validatePageLink; @@ -58,7 +56,7 @@ import static org.thingsboard.server.dao.service.Validator.validatePageLink;
58 56
59 @Service 57 @Service
60 @Slf4j 58 @Slf4j
61 -public class BaseRuleService extends BaseEntityService implements RuleService { 59 +public class BaseRuleService extends AbstractEntityService implements RuleService {
62 60
63 private final TenantId systemTenantId = new TenantId(NULL_UUID); 61 private final TenantId systemTenantId = new TenantId(NULL_UUID);
64 62
@@ -26,7 +26,6 @@ import com.google.common.util.concurrent.Futures; @@ -26,7 +26,6 @@ import com.google.common.util.concurrent.Futures;
26 import com.google.common.util.concurrent.ListenableFuture; 26 import com.google.common.util.concurrent.ListenableFuture;
27 import lombok.extern.slf4j.Slf4j; 27 import lombok.extern.slf4j.Slf4j;
28 import org.apache.commons.lang3.StringUtils; 28 import org.apache.commons.lang3.StringUtils;
29 -import org.thingsboard.server.common.data.Customer;  
30 import org.thingsboard.server.common.data.Tenant; 29 import org.thingsboard.server.common.data.Tenant;
31 import org.thingsboard.server.common.data.id.TenantId; 30 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.page.TextPageData; 31 import org.thingsboard.server.common.data.page.TextPageData;
@@ -34,9 +33,8 @@ import org.thingsboard.server.common.data.page.TextPageLink; @@ -34,9 +33,8 @@ import org.thingsboard.server.common.data.page.TextPageLink;
34 import org.thingsboard.server.dao.customer.CustomerService; 33 import org.thingsboard.server.dao.customer.CustomerService;
35 import org.thingsboard.server.dao.dashboard.DashboardService; 34 import org.thingsboard.server.dao.dashboard.DashboardService;
36 import org.thingsboard.server.dao.device.DeviceService; 35 import org.thingsboard.server.dao.device.DeviceService;
37 -import org.thingsboard.server.dao.entity.BaseEntityService; 36 +import org.thingsboard.server.dao.entity.AbstractEntityService;
38 import org.thingsboard.server.dao.exception.DataValidationException; 37 import org.thingsboard.server.dao.exception.DataValidationException;
39 -import org.thingsboard.server.dao.model.CustomerEntity;  
40 import org.thingsboard.server.dao.model.TenantEntity; 38 import org.thingsboard.server.dao.model.TenantEntity;
41 import org.thingsboard.server.dao.plugin.PluginService; 39 import org.thingsboard.server.dao.plugin.PluginService;
42 import org.thingsboard.server.dao.rule.RuleService; 40 import org.thingsboard.server.dao.rule.RuleService;
@@ -50,7 +48,7 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService; @@ -50,7 +48,7 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService;
50 48
51 @Service 49 @Service
52 @Slf4j 50 @Slf4j
53 -public class TenantServiceImpl extends BaseEntityService implements TenantService { 51 +public class TenantServiceImpl extends AbstractEntityService implements TenantService {
54 52
55 private static final String DEFAULT_TENANT_REGION = "Global"; 53 private static final String DEFAULT_TENANT_REGION = "Global";
56 54
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.dao.user; 16 package org.thingsboard.server.dao.user;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 import org.thingsboard.server.common.data.User; 19 import org.thingsboard.server.common.data.User;
19 import org.thingsboard.server.common.data.id.CustomerId; 20 import org.thingsboard.server.common.data.id.CustomerId;
20 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
@@ -27,6 +28,8 @@ public interface UserService { @@ -27,6 +28,8 @@ public interface UserService {
27 28
28 public User findUserById(UserId userId); 29 public User findUserById(UserId userId);
29 30
  31 + public ListenableFuture<User> findUserByIdAsync(UserId userId);
  32 +
30 public User findUserByEmail(String email); 33 public User findUserByEmail(String email);
31 34
32 public User saveUser(User user); 35 public User saveUser(User user);
@@ -23,6 +23,9 @@ import static org.thingsboard.server.dao.service.Validator.validateString; @@ -23,6 +23,9 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
23 23
24 import java.util.List; 24 import java.util.List;
25 25
  26 +import com.google.common.base.Function;
  27 +import com.google.common.util.concurrent.Futures;
  28 +import com.google.common.util.concurrent.ListenableFuture;
26 import lombok.extern.slf4j.Slf4j; 29 import lombok.extern.slf4j.Slf4j;
27 import org.apache.commons.lang3.RandomStringUtils; 30 import org.apache.commons.lang3.RandomStringUtils;
28 import org.apache.commons.lang3.StringUtils; 31 import org.apache.commons.lang3.StringUtils;
@@ -35,7 +38,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; @@ -35,7 +38,7 @@ import org.thingsboard.server.common.data.page.TextPageLink;
35 import org.thingsboard.server.common.data.security.Authority; 38 import org.thingsboard.server.common.data.security.Authority;
36 import org.thingsboard.server.common.data.security.UserCredentials; 39 import org.thingsboard.server.common.data.security.UserCredentials;
37 import org.thingsboard.server.dao.customer.CustomerDao; 40 import org.thingsboard.server.dao.customer.CustomerDao;
38 -import org.thingsboard.server.dao.entity.BaseEntityService; 41 +import org.thingsboard.server.dao.entity.AbstractEntityService;
39 import org.thingsboard.server.dao.exception.DataValidationException; 42 import org.thingsboard.server.dao.exception.DataValidationException;
40 import org.thingsboard.server.dao.exception.IncorrectParameterException; 43 import org.thingsboard.server.dao.exception.IncorrectParameterException;
41 import org.thingsboard.server.dao.model.*; 44 import org.thingsboard.server.dao.model.*;
@@ -47,7 +50,7 @@ import org.springframework.stereotype.Service; @@ -47,7 +50,7 @@ import org.springframework.stereotype.Service;
47 50
48 @Service 51 @Service
49 @Slf4j 52 @Slf4j
50 -public class UserServiceImpl extends BaseEntityService implements UserService { 53 +public class UserServiceImpl extends AbstractEntityService implements UserService {
51 54
52 @Autowired 55 @Autowired
53 private UserDao userDao; 56 private UserDao userDao;
@@ -78,6 +81,14 @@ public class UserServiceImpl extends BaseEntityService implements UserService { @@ -78,6 +81,14 @@ public class UserServiceImpl extends BaseEntityService implements UserService {
78 } 81 }
79 82
80 @Override 83 @Override
  84 + public ListenableFuture<User> findUserByIdAsync(UserId userId) {
  85 + log.trace("Executing findUserByIdAsync [{}]", userId);
  86 + validateId(userId, "Incorrect userId " + userId);
  87 + ListenableFuture<UserEntity> userEntity = userDao.findByIdAsync(userId.getId());
  88 + return Futures.transform(userEntity, (Function<? super UserEntity, ? extends User>) input -> getData(input));
  89 + }
  90 +
  91 + @Override
81 public User saveUser(User user) { 92 public User saveUser(User user) {
82 log.trace("Executing saveUser [{}]", user); 93 log.trace("Executing saveUser [{}]", user);
83 userValidator.validate(user); 94 userValidator.validate(user);
@@ -149,66 +149,73 @@ VALUES ( @@ -149,66 +149,73 @@ VALUES (
149 149
150 /** Demo device **/ 150 /** Demo device **/
151 151
152 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text) 152 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text)
153 VALUES ( 153 VALUES (
154 minTimeuuid ( '2016-11-01 01:02:05+0000' ), 154 minTimeuuid ( '2016-11-01 01:02:05+0000' ),
155 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 155 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
156 minTimeuuid ( '2016-11-01 01:02:03+0000' ), 156 minTimeuuid ( '2016-11-01 01:02:03+0000' ),
  157 + 'default',
157 'Test Device A1', 158 'Test Device A1',
158 'test device a1' 159 'test device a1'
159 ); 160 );
160 161
161 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text) 162 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text)
162 VALUES ( 163 VALUES (
163 minTimeuuid ( '2016-11-01 01:02:05+0001' ), 164 minTimeuuid ( '2016-11-01 01:02:05+0001' ),
164 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 165 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
165 minTimeuuid ( '2016-11-01 01:02:03+0000' ), 166 minTimeuuid ( '2016-11-01 01:02:03+0000' ),
  167 + 'default',
166 'Test Device A2', 168 'Test Device A2',
167 'test device a2' 169 'test device a2'
168 ); 170 );
169 171
170 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text) 172 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text)
171 VALUES ( 173 VALUES (
172 minTimeuuid ( '2016-11-01 01:02:05+0002' ), 174 minTimeuuid ( '2016-11-01 01:02:05+0002' ),
173 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 175 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
174 minTimeuuid ( '2016-11-01 01:02:03+0000' ), 176 minTimeuuid ( '2016-11-01 01:02:03+0000' ),
  177 + 'default',
175 'Test Device A3', 178 'Test Device A3',
176 'test device a3' 179 'test device a3'
177 ); 180 );
178 181
179 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text) 182 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text)
180 VALUES ( 183 VALUES (
181 minTimeuuid ( '2016-11-01 01:02:05+0003' ), 184 minTimeuuid ( '2016-11-01 01:02:05+0003' ),
182 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 185 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
183 minTimeuuid ( '2016-11-01 01:02:03+0001' ), 186 minTimeuuid ( '2016-11-01 01:02:03+0001' ),
  187 + 'default',
184 'Test Device B1', 188 'Test Device B1',
185 'test device b1' 189 'test device b1'
186 ); 190 );
187 191
188 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text) 192 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text)
189 VALUES ( 193 VALUES (
190 minTimeuuid ( '2016-11-01 01:02:05+0004' ), 194 minTimeuuid ( '2016-11-01 01:02:05+0004' ),
191 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 195 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
192 minTimeuuid ( '2016-11-01 01:02:03+0002' ), 196 minTimeuuid ( '2016-11-01 01:02:03+0002' ),
  197 + 'default',
193 'Test Device C1', 198 'Test Device C1',
194 'test device c1' 199 'test device c1'
195 ); 200 );
196 201
197 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text, additional_info) 202 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text, additional_info)
198 VALUES ( 203 VALUES (
199 c8f1a6f0-b993-11e6-8a04-9ff4e1b7933c, 204 c8f1a6f0-b993-11e6-8a04-9ff4e1b7933c,
200 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 205 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
201 minTimeuuid ( 0 ), 206 minTimeuuid ( 0 ),
  207 + 'default',
202 'DHT11 Demo Device', 208 'DHT11 Demo Device',
203 'dht11 demo device', 209 'dht11 demo device',
204 '{"description":"Demo device that is used in sample applications that upload data from DHT11 temperature and humidity sensor"}' 210 '{"description":"Demo device that is used in sample applications that upload data from DHT11 temperature and humidity sensor"}'
205 ); 211 );
206 212
207 -INSERT INTO thingsboard.device ( id, tenant_id, customer_id, name, search_text, additional_info) 213 +INSERT INTO thingsboard.device ( id, tenant_id, customer_id, type, name, search_text, additional_info)
208 VALUES ( 214 VALUES (
209 c8f1a6f0-b993-11e6-8a04-9ff4e1b7933d, 215 c8f1a6f0-b993-11e6-8a04-9ff4e1b7933d,
210 minTimeuuid ( '2016-11-01 01:02:01+0000' ), 216 minTimeuuid ( '2016-11-01 01:02:01+0000' ),
211 minTimeuuid ( 0 ), 217 minTimeuuid ( 0 ),
  218 + 'default',
212 'Raspberry Pi Demo Device', 219 'Raspberry Pi Demo Device',
213 'raspberry pi demo device', 220 'raspberry pi demo device',
214 '{"description":"Demo device that is used in Raspberry Pi GPIO control sample application"}' 221 '{"description":"Demo device that is used in Raspberry Pi GPIO control sample application"}'
@@ -152,36 +152,57 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.customer_by_tenant_and_search @@ -152,36 +152,57 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.customer_by_tenant_and_search
152 WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); 152 WITH CLUSTERING ORDER BY ( search_text ASC, id DESC );
153 153
154 CREATE TABLE IF NOT EXISTS thingsboard.device ( 154 CREATE TABLE IF NOT EXISTS thingsboard.device (
155 - id timeuuid,  
156 - tenant_id timeuuid,  
157 - customer_id timeuuid,  
158 - name text,  
159 - type text,  
160 - search_text text,  
161 - additional_info text,  
162 - PRIMARY KEY (id, tenant_id, customer_id) 155 + id timeuuid,
  156 + tenant_id timeuuid,
  157 + customer_id timeuuid,
  158 + name text,
  159 + type text,
  160 + search_text text,
  161 + additional_info text,
  162 + PRIMARY KEY (id, tenant_id, customer_id, type)
163 ); 163 );
164 164
165 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_name AS 165 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_name AS
166 - SELECT *  
167 - from thingsboard.device  
168 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL  
169 - PRIMARY KEY ( tenant_id, name, id, customer_id)  
170 - WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); 166 + SELECT *
  167 + from thingsboard.device
  168 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL
  169 + PRIMARY KEY ( tenant_id, name, id, customer_id, type)
  170 + WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC);
171 171
172 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_search_text AS 172 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_search_text AS
173 - SELECT *  
174 - from thingsboard.device  
175 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL  
176 - PRIMARY KEY ( tenant_id, search_text, id, customer_id)  
177 - WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC); 173 + SELECT *
  174 + from thingsboard.device
  175 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  176 + PRIMARY KEY ( tenant_id, search_text, id, customer_id, type)
  177 + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC);
  178 +
  179 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_by_type_and_search_text AS
  180 + SELECT *
  181 + from thingsboard.device
  182 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  183 + PRIMARY KEY ( tenant_id, type, search_text, id, customer_id)
  184 + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC);
178 185
179 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_and_search_text AS 186 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_and_search_text AS
180 - SELECT *  
181 - from thingsboard.device  
182 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL  
183 - PRIMARY KEY ( customer_id, tenant_id, search_text, id )  
184 - WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC ); 187 + SELECT *
  188 + from thingsboard.device
  189 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  190 + PRIMARY KEY ( customer_id, tenant_id, search_text, id, type )
  191 + WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC );
  192 +
  193 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_and_search_text AS
  194 + SELECT *
  195 + from thingsboard.device
  196 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  197 + PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
  198 + WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
  199 +
  200 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS
  201 + SELECT *
  202 + from thingsboard.device
  203 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
  204 + PRIMARY KEY ( (type, tenant_id), id, customer_id)
  205 + WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
185 206
186 CREATE TABLE IF NOT EXISTS thingsboard.device_credentials ( 207 CREATE TABLE IF NOT EXISTS thingsboard.device_credentials (
187 id timeuuid PRIMARY KEY, 208 id timeuuid PRIMARY KEY,
@@ -203,38 +224,58 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_credentials_by_credent @@ -203,38 +224,58 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_credentials_by_credent
203 WHERE credentials_id IS NOT NULL AND id IS NOT NULL 224 WHERE credentials_id IS NOT NULL AND id IS NOT NULL
204 PRIMARY KEY ( credentials_id, id ); 225 PRIMARY KEY ( credentials_id, id );
205 226
206 -  
207 CREATE TABLE IF NOT EXISTS thingsboard.asset ( 227 CREATE TABLE IF NOT EXISTS thingsboard.asset (
208 - id timeuuid,  
209 - tenant_id timeuuid,  
210 - customer_id timeuuid,  
211 - name text,  
212 - type text,  
213 - search_text text,  
214 - additional_info text,  
215 - PRIMARY KEY (id, tenant_id, customer_id) 228 + id timeuuid,
  229 + tenant_id timeuuid,
  230 + customer_id timeuuid,
  231 + name text,
  232 + type text,
  233 + search_text text,
  234 + additional_info text,
  235 + PRIMARY KEY (id, tenant_id, customer_id, type)
216 ); 236 );
217 237
218 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_name AS 238 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_name AS
219 - SELECT *  
220 - from thingsboard.asset  
221 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL  
222 - PRIMARY KEY ( tenant_id, name, id, customer_id)  
223 - WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); 239 + SELECT *
  240 + from thingsboard.asset
  241 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL
  242 + PRIMARY KEY ( tenant_id, name, id, customer_id, type)
  243 + WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC);
224 244
225 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_search_text AS 245 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_search_text AS
226 - SELECT *  
227 - from thingsboard.asset  
228 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL  
229 - PRIMARY KEY ( tenant_id, search_text, id, customer_id)  
230 - WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC); 246 + SELECT *
  247 + from thingsboard.asset
  248 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  249 + PRIMARY KEY ( tenant_id, search_text, id, customer_id, type)
  250 + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC);
  251 +
  252 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_by_type_and_search_text AS
  253 + SELECT *
  254 + from thingsboard.asset
  255 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  256 + PRIMARY KEY ( tenant_id, type, search_text, id, customer_id)
  257 + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC);
231 258
232 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_and_search_text AS 259 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_and_search_text AS
233 - SELECT *  
234 - from thingsboard.asset  
235 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL  
236 - PRIMARY KEY ( customer_id, tenant_id, search_text, id )  
237 - WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC ); 260 + SELECT *
  261 + from thingsboard.asset
  262 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  263 + PRIMARY KEY ( customer_id, tenant_id, search_text, id, type )
  264 + WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC );
  265 +
  266 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and_search_text AS
  267 + SELECT *
  268 + from thingsboard.asset
  269 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  270 + PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
  271 + WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
  272 +
  273 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS
  274 + SELECT *
  275 + from thingsboard.asset
  276 + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
  277 + PRIMARY KEY ( (type, tenant_id), id, customer_id)
  278 + WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
238 279
239 CREATE TABLE IF NOT EXISTS thingsboard.relation ( 280 CREATE TABLE IF NOT EXISTS thingsboard.relation (
240 from_id timeuuid, 281 from_id timeuuid,
@@ -247,11 +288,11 @@ CREATE TABLE IF NOT EXISTS thingsboard.relation ( @@ -247,11 +288,11 @@ CREATE TABLE IF NOT EXISTS thingsboard.relation (
247 ); 288 );
248 289
249 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.reverse_relation AS 290 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.reverse_relation AS
250 -SELECT *  
251 -from thingsboard.relation  
252 -WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL  
253 -PRIMARY KEY ((to_id, to_type), relation_type, from_id, from_type)  
254 -WITH CLUSTERING ORDER BY ( relation_type ASC, from_id ASC, from_type ASC); 291 + SELECT *
  292 + from thingsboard.relation
  293 + WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL
  294 + PRIMARY KEY ((to_id, to_type), relation_type, from_id, from_type)
  295 + WITH CLUSTERING ORDER BY ( relation_type ASC, from_id ASC, from_type ASC);
255 296
256 CREATE TABLE IF NOT EXISTS thingsboard.widgets_bundle ( 297 CREATE TABLE IF NOT EXISTS thingsboard.widgets_bundle (
257 id timeuuid, 298 id timeuuid,
@@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.plugin.ComponentScope; @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.plugin.ComponentScope;
40 import org.thingsboard.server.common.data.plugin.ComponentType; 40 import org.thingsboard.server.common.data.plugin.ComponentType;
41 import org.thingsboard.server.common.data.plugin.PluginMetaData; 41 import org.thingsboard.server.common.data.plugin.PluginMetaData;
42 import org.thingsboard.server.common.data.rule.RuleMetaData; 42 import org.thingsboard.server.common.data.rule.RuleMetaData;
  43 +import org.thingsboard.server.dao.asset.AssetService;
43 import org.thingsboard.server.dao.component.ComponentDescriptorService; 44 import org.thingsboard.server.dao.component.ComponentDescriptorService;
44 import org.thingsboard.server.dao.customer.CustomerService; 45 import org.thingsboard.server.dao.customer.CustomerService;
45 import org.thingsboard.server.dao.dashboard.DashboardService; 46 import org.thingsboard.server.dao.dashboard.DashboardService;
@@ -88,6 +89,9 @@ public abstract class AbstractServiceTest { @@ -88,6 +89,9 @@ public abstract class AbstractServiceTest {
88 protected DeviceService deviceService; 89 protected DeviceService deviceService;
89 90
90 @Autowired 91 @Autowired
  92 + protected AssetService assetService;
  93 +
  94 + @Autowired
91 protected DeviceCredentialsService deviceCredentialsService; 95 protected DeviceCredentialsService deviceCredentialsService;
92 96
93 @Autowired 97 @Autowired
  1 +/**
  2 + * Copyright © 2016-2017 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.service;
  17 +
  18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import org.apache.commons.lang3.RandomStringUtils;
  20 +import org.junit.After;
  21 +import org.junit.Assert;
  22 +import org.junit.Before;
  23 +import org.junit.Test;
  24 +import org.thingsboard.server.common.data.Customer;
  25 +import org.thingsboard.server.common.data.Tenant;
  26 +import org.thingsboard.server.common.data.asset.Asset;
  27 +import org.thingsboard.server.common.data.asset.TenantAssetType;
  28 +import org.thingsboard.server.common.data.id.CustomerId;
  29 +import org.thingsboard.server.common.data.id.TenantId;
  30 +import org.thingsboard.server.common.data.page.TextPageData;
  31 +import org.thingsboard.server.common.data.page.TextPageLink;
  32 +import org.thingsboard.server.dao.exception.DataValidationException;
  33 +
  34 +import java.util.ArrayList;
  35 +import java.util.Collections;
  36 +import java.util.List;
  37 +
  38 +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
  39 +
  40 +public class BaseAssetServiceTest extends AbstractServiceTest {
  41 +
  42 + private IdComparator<Asset> idComparator = new IdComparator<>();
  43 +
  44 + private TenantId tenantId;
  45 +
  46 + @Before
  47 + public void before() {
  48 + Tenant tenant = new Tenant();
  49 + tenant.setTitle("My tenant");
  50 + Tenant savedTenant = tenantService.saveTenant(tenant);
  51 + Assert.assertNotNull(savedTenant);
  52 + tenantId = savedTenant.getId();
  53 + }
  54 +
  55 + @After
  56 + public void after() {
  57 + tenantService.deleteTenant(tenantId);
  58 + }
  59 +
  60 + @Test
  61 + public void testSaveAsset() {
  62 + Asset asset = new Asset();
  63 + asset.setTenantId(tenantId);
  64 + asset.setName("My asset");
  65 + asset.setType("default");
  66 + Asset savedAsset = assetService.saveAsset(asset);
  67 +
  68 + Assert.assertNotNull(savedAsset);
  69 + Assert.assertNotNull(savedAsset.getId());
  70 + Assert.assertTrue(savedAsset.getCreatedTime() > 0);
  71 + Assert.assertEquals(asset.getTenantId(), savedAsset.getTenantId());
  72 + Assert.assertNotNull(savedAsset.getCustomerId());
  73 + Assert.assertEquals(NULL_UUID, savedAsset.getCustomerId().getId());
  74 + Assert.assertEquals(asset.getName(), savedAsset.getName());
  75 +
  76 + savedAsset.setName("My new asset");
  77 +
  78 + assetService.saveAsset(savedAsset);
  79 + Asset foundAsset = assetService.findAssetById(savedAsset.getId());
  80 + Assert.assertEquals(foundAsset.getName(), savedAsset.getName());
  81 +
  82 + assetService.deleteAsset(savedAsset.getId());
  83 + }
  84 +
  85 + @Test(expected = DataValidationException.class)
  86 + public void testSaveAssetWithEmptyName() {
  87 + Asset asset = new Asset();
  88 + asset.setTenantId(tenantId);
  89 + asset.setType("default");
  90 + assetService.saveAsset(asset);
  91 + }
  92 +
  93 + @Test(expected = DataValidationException.class)
  94 + public void testSaveAssetWithEmptyTenant() {
  95 + Asset asset = new Asset();
  96 + asset.setName("My asset");
  97 + asset.setType("default");
  98 + assetService.saveAsset(asset);
  99 + }
  100 +
  101 + @Test(expected = DataValidationException.class)
  102 + public void testSaveAssetWithInvalidTenant() {
  103 + Asset asset = new Asset();
  104 + asset.setName("My asset");
  105 + asset.setType("default");
  106 + asset.setTenantId(new TenantId(UUIDs.timeBased()));
  107 + assetService.saveAsset(asset);
  108 + }
  109 +
  110 + @Test(expected = DataValidationException.class)
  111 + public void testAssignAssetToNonExistentCustomer() {
  112 + Asset asset = new Asset();
  113 + asset.setName("My asset");
  114 + asset.setType("default");
  115 + asset.setTenantId(tenantId);
  116 + asset = assetService.saveAsset(asset);
  117 + try {
  118 + assetService.assignAssetToCustomer(asset.getId(), new CustomerId(UUIDs.timeBased()));
  119 + } finally {
  120 + assetService.deleteAsset(asset.getId());
  121 + }
  122 + }
  123 +
  124 + @Test(expected = DataValidationException.class)
  125 + public void testAssignAssetToCustomerFromDifferentTenant() {
  126 + Asset asset = new Asset();
  127 + asset.setName("My asset");
  128 + asset.setType("default");
  129 + asset.setTenantId(tenantId);
  130 + asset = assetService.saveAsset(asset);
  131 + Tenant tenant = new Tenant();
  132 + tenant.setTitle("Test different tenant");
  133 + tenant = tenantService.saveTenant(tenant);
  134 + Customer customer = new Customer();
  135 + customer.setTenantId(tenant.getId());
  136 + customer.setTitle("Test different customer");
  137 + customer = customerService.saveCustomer(customer);
  138 + try {
  139 + assetService.assignAssetToCustomer(asset.getId(), customer.getId());
  140 + } finally {
  141 + assetService.deleteAsset(asset.getId());
  142 + tenantService.deleteTenant(tenant.getId());
  143 + }
  144 + }
  145 +
  146 + @Test
  147 + public void testFindAssetById() {
  148 + Asset asset = new Asset();
  149 + asset.setTenantId(tenantId);
  150 + asset.setName("My asset");
  151 + asset.setType("default");
  152 + Asset savedAsset = assetService.saveAsset(asset);
  153 + Asset foundAsset = assetService.findAssetById(savedAsset.getId());
  154 + Assert.assertNotNull(foundAsset);
  155 + Assert.assertEquals(savedAsset, foundAsset);
  156 + assetService.deleteAsset(savedAsset.getId());
  157 + }
  158 +
  159 + @Test
  160 + public void testFindAssetTypesByTenantId() throws Exception {
  161 + List<Asset> assets = new ArrayList<>();
  162 + try {
  163 + for (int i=0;i<3;i++) {
  164 + Asset asset = new Asset();
  165 + asset.setTenantId(tenantId);
  166 + asset.setName("My asset B"+i);
  167 + asset.setType("typeB");
  168 + assets.add(assetService.saveAsset(asset));
  169 + }
  170 + for (int i=0;i<7;i++) {
  171 + Asset asset = new Asset();
  172 + asset.setTenantId(tenantId);
  173 + asset.setName("My asset C"+i);
  174 + asset.setType("typeC");
  175 + assets.add(assetService.saveAsset(asset));
  176 + }
  177 + for (int i=0;i<9;i++) {
  178 + Asset asset = new Asset();
  179 + asset.setTenantId(tenantId);
  180 + asset.setName("My asset A"+i);
  181 + asset.setType("typeA");
  182 + assets.add(assetService.saveAsset(asset));
  183 + }
  184 + List<TenantAssetType> assetTypes = assetService.findAssetTypesByTenantId(tenantId).get();
  185 + Assert.assertNotNull(assetTypes);
  186 + Assert.assertEquals(3, assetTypes.size());
  187 + Assert.assertEquals("typeA", assetTypes.get(0).getType());
  188 + Assert.assertEquals("typeB", assetTypes.get(1).getType());
  189 + Assert.assertEquals("typeC", assetTypes.get(2).getType());
  190 + } finally {
  191 + assets.forEach((asset) -> { assetService.deleteAsset(asset.getId()); });
  192 + }
  193 + }
  194 +
  195 + @Test
  196 + public void testDeleteAsset() {
  197 + Asset asset = new Asset();
  198 + asset.setTenantId(tenantId);
  199 + asset.setName("My asset");
  200 + asset.setType("default");
  201 + Asset savedAsset = assetService.saveAsset(asset);
  202 + Asset foundAsset = assetService.findAssetById(savedAsset.getId());
  203 + Assert.assertNotNull(foundAsset);
  204 + assetService.deleteAsset(savedAsset.getId());
  205 + foundAsset = assetService.findAssetById(savedAsset.getId());
  206 + Assert.assertNull(foundAsset);
  207 + }
  208 +
  209 + @Test
  210 + public void testFindAssetsByTenantId() {
  211 + Tenant tenant = new Tenant();
  212 + tenant.setTitle("Test tenant");
  213 + tenant = tenantService.saveTenant(tenant);
  214 +
  215 + TenantId tenantId = tenant.getId();
  216 +
  217 + List<Asset> assets = new ArrayList<>();
  218 + for (int i=0;i<178;i++) {
  219 + Asset asset = new Asset();
  220 + asset.setTenantId(tenantId);
  221 + asset.setName("Asset"+i);
  222 + asset.setType("default");
  223 + assets.add(assetService.saveAsset(asset));
  224 + }
  225 +
  226 + List<Asset> loadedAssets = new ArrayList<>();
  227 + TextPageLink pageLink = new TextPageLink(23);
  228 + TextPageData<Asset> pageData = null;
  229 + do {
  230 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  231 + loadedAssets.addAll(pageData.getData());
  232 + if (pageData.hasNext()) {
  233 + pageLink = pageData.getNextPageLink();
  234 + }
  235 + } while (pageData.hasNext());
  236 +
  237 + Collections.sort(assets, idComparator);
  238 + Collections.sort(loadedAssets, idComparator);
  239 +
  240 + Assert.assertEquals(assets, loadedAssets);
  241 +
  242 + assetService.deleteAssetsByTenantId(tenantId);
  243 +
  244 + pageLink = new TextPageLink(33);
  245 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  246 + Assert.assertFalse(pageData.hasNext());
  247 + Assert.assertTrue(pageData.getData().isEmpty());
  248 +
  249 + tenantService.deleteTenant(tenantId);
  250 + }
  251 +
  252 + @Test
  253 + public void testFindAssetsByTenantIdAndName() {
  254 + String title1 = "Asset title 1";
  255 + List<Asset> assetsTitle1 = new ArrayList<>();
  256 + for (int i=0;i<143;i++) {
  257 + Asset asset = new Asset();
  258 + asset.setTenantId(tenantId);
  259 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  260 + String name = title1+suffix;
  261 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  262 + asset.setName(name);
  263 + asset.setType("default");
  264 + assetsTitle1.add(assetService.saveAsset(asset));
  265 + }
  266 + String title2 = "Asset title 2";
  267 + List<Asset> assetsTitle2 = new ArrayList<>();
  268 + for (int i=0;i<175;i++) {
  269 + Asset asset = new Asset();
  270 + asset.setTenantId(tenantId);
  271 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  272 + String name = title2+suffix;
  273 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  274 + asset.setName(name);
  275 + asset.setType("default");
  276 + assetsTitle2.add(assetService.saveAsset(asset));
  277 + }
  278 +
  279 + List<Asset> loadedAssetsTitle1 = new ArrayList<>();
  280 + TextPageLink pageLink = new TextPageLink(15, title1);
  281 + TextPageData<Asset> pageData = null;
  282 + do {
  283 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  284 + loadedAssetsTitle1.addAll(pageData.getData());
  285 + if (pageData.hasNext()) {
  286 + pageLink = pageData.getNextPageLink();
  287 + }
  288 + } while (pageData.hasNext());
  289 +
  290 + Collections.sort(assetsTitle1, idComparator);
  291 + Collections.sort(loadedAssetsTitle1, idComparator);
  292 +
  293 + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
  294 +
  295 + List<Asset> loadedAssetsTitle2 = new ArrayList<>();
  296 + pageLink = new TextPageLink(4, title2);
  297 + do {
  298 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  299 + loadedAssetsTitle2.addAll(pageData.getData());
  300 + if (pageData.hasNext()) {
  301 + pageLink = pageData.getNextPageLink();
  302 + }
  303 + } while (pageData.hasNext());
  304 +
  305 + Collections.sort(assetsTitle2, idComparator);
  306 + Collections.sort(loadedAssetsTitle2, idComparator);
  307 +
  308 + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
  309 +
  310 + for (Asset asset : loadedAssetsTitle1) {
  311 + assetService.deleteAsset(asset.getId());
  312 + }
  313 +
  314 + pageLink = new TextPageLink(4, title1);
  315 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  316 + Assert.assertFalse(pageData.hasNext());
  317 + Assert.assertEquals(0, pageData.getData().size());
  318 +
  319 + for (Asset asset : loadedAssetsTitle2) {
  320 + assetService.deleteAsset(asset.getId());
  321 + }
  322 +
  323 + pageLink = new TextPageLink(4, title2);
  324 + pageData = assetService.findAssetsByTenantId(tenantId, pageLink);
  325 + Assert.assertFalse(pageData.hasNext());
  326 + Assert.assertEquals(0, pageData.getData().size());
  327 + }
  328 +
  329 + @Test
  330 + public void testFindAssetsByTenantIdAndType() {
  331 + String title1 = "Asset title 1";
  332 + String type1 = "typeA";
  333 + List<Asset> assetsType1 = new ArrayList<>();
  334 + for (int i=0;i<143;i++) {
  335 + Asset asset = new Asset();
  336 + asset.setTenantId(tenantId);
  337 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  338 + String name = title1+suffix;
  339 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  340 + asset.setName(name);
  341 + asset.setType(type1);
  342 + assetsType1.add(assetService.saveAsset(asset));
  343 + }
  344 + String title2 = "Asset title 2";
  345 + String type2 = "typeB";
  346 + List<Asset> assetsType2 = new ArrayList<>();
  347 + for (int i=0;i<175;i++) {
  348 + Asset asset = new Asset();
  349 + asset.setTenantId(tenantId);
  350 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  351 + String name = title2+suffix;
  352 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  353 + asset.setName(name);
  354 + asset.setType(type2);
  355 + assetsType2.add(assetService.saveAsset(asset));
  356 + }
  357 +
  358 + List<Asset> loadedAssetsType1 = new ArrayList<>();
  359 + TextPageLink pageLink = new TextPageLink(15);
  360 + TextPageData<Asset> pageData = null;
  361 + do {
  362 + pageData = assetService.findAssetsByTenantIdAndType(tenantId, type1, pageLink);
  363 + loadedAssetsType1.addAll(pageData.getData());
  364 + if (pageData.hasNext()) {
  365 + pageLink = pageData.getNextPageLink();
  366 + }
  367 + } while (pageData.hasNext());
  368 +
  369 + Collections.sort(assetsType1, idComparator);
  370 + Collections.sort(loadedAssetsType1, idComparator);
  371 +
  372 + Assert.assertEquals(assetsType1, loadedAssetsType1);
  373 +
  374 + List<Asset> loadedAssetsType2 = new ArrayList<>();
  375 + pageLink = new TextPageLink(4);
  376 + do {
  377 + pageData = assetService.findAssetsByTenantIdAndType(tenantId, type2, pageLink);
  378 + loadedAssetsType2.addAll(pageData.getData());
  379 + if (pageData.hasNext()) {
  380 + pageLink = pageData.getNextPageLink();
  381 + }
  382 + } while (pageData.hasNext());
  383 +
  384 + Collections.sort(assetsType2, idComparator);
  385 + Collections.sort(loadedAssetsType2, idComparator);
  386 +
  387 + Assert.assertEquals(assetsType2, loadedAssetsType2);
  388 +
  389 + for (Asset asset : loadedAssetsType1) {
  390 + assetService.deleteAsset(asset.getId());
  391 + }
  392 +
  393 + pageLink = new TextPageLink(4);
  394 + pageData = assetService.findAssetsByTenantIdAndType(tenantId, type1, pageLink);
  395 + Assert.assertFalse(pageData.hasNext());
  396 + Assert.assertEquals(0, pageData.getData().size());
  397 +
  398 + for (Asset asset : loadedAssetsType2) {
  399 + assetService.deleteAsset(asset.getId());
  400 + }
  401 +
  402 + pageLink = new TextPageLink(4);
  403 + pageData = assetService.findAssetsByTenantIdAndType(tenantId, type2, pageLink);
  404 + Assert.assertFalse(pageData.hasNext());
  405 + Assert.assertEquals(0, pageData.getData().size());
  406 + }
  407 +
  408 + @Test
  409 + public void testFindAssetsByTenantIdAndCustomerId() {
  410 + Tenant tenant = new Tenant();
  411 + tenant.setTitle("Test tenant");
  412 + tenant = tenantService.saveTenant(tenant);
  413 +
  414 + TenantId tenantId = tenant.getId();
  415 +
  416 + Customer customer = new Customer();
  417 + customer.setTitle("Test customer");
  418 + customer.setTenantId(tenantId);
  419 + customer = customerService.saveCustomer(customer);
  420 + CustomerId customerId = customer.getId();
  421 +
  422 + List<Asset> assets = new ArrayList<>();
  423 + for (int i=0;i<278;i++) {
  424 + Asset asset = new Asset();
  425 + asset.setTenantId(tenantId);
  426 + asset.setName("Asset"+i);
  427 + asset.setType("default");
  428 + asset = assetService.saveAsset(asset);
  429 + assets.add(assetService.assignAssetToCustomer(asset.getId(), customerId));
  430 + }
  431 +
  432 + List<Asset> loadedAssets = new ArrayList<>();
  433 + TextPageLink pageLink = new TextPageLink(23);
  434 + TextPageData<Asset> pageData = null;
  435 + do {
  436 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  437 + loadedAssets.addAll(pageData.getData());
  438 + if (pageData.hasNext()) {
  439 + pageLink = pageData.getNextPageLink();
  440 + }
  441 + } while (pageData.hasNext());
  442 +
  443 + Collections.sort(assets, idComparator);
  444 + Collections.sort(loadedAssets, idComparator);
  445 +
  446 + Assert.assertEquals(assets, loadedAssets);
  447 +
  448 + assetService.unassignCustomerAssets(tenantId, customerId);
  449 +
  450 + pageLink = new TextPageLink(33);
  451 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  452 + Assert.assertFalse(pageData.hasNext());
  453 + Assert.assertTrue(pageData.getData().isEmpty());
  454 +
  455 + tenantService.deleteTenant(tenantId);
  456 + }
  457 +
  458 + @Test
  459 + public void testFindAssetsByTenantIdCustomerIdAndName() {
  460 +
  461 + Customer customer = new Customer();
  462 + customer.setTitle("Test customer");
  463 + customer.setTenantId(tenantId);
  464 + customer = customerService.saveCustomer(customer);
  465 + CustomerId customerId = customer.getId();
  466 +
  467 + String title1 = "Asset title 1";
  468 + List<Asset> assetsTitle1 = new ArrayList<>();
  469 + for (int i=0;i<175;i++) {
  470 + Asset asset = new Asset();
  471 + asset.setTenantId(tenantId);
  472 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  473 + String name = title1+suffix;
  474 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  475 + asset.setName(name);
  476 + asset.setType("default");
  477 + asset = assetService.saveAsset(asset);
  478 + assetsTitle1.add(assetService.assignAssetToCustomer(asset.getId(), customerId));
  479 + }
  480 + String title2 = "Asset title 2";
  481 + List<Asset> assetsTitle2 = new ArrayList<>();
  482 + for (int i=0;i<143;i++) {
  483 + Asset asset = new Asset();
  484 + asset.setTenantId(tenantId);
  485 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  486 + String name = title2+suffix;
  487 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  488 + asset.setName(name);
  489 + asset.setType("default");
  490 + asset = assetService.saveAsset(asset);
  491 + assetsTitle2.add(assetService.assignAssetToCustomer(asset.getId(), customerId));
  492 + }
  493 +
  494 + List<Asset> loadedAssetsTitle1 = new ArrayList<>();
  495 + TextPageLink pageLink = new TextPageLink(15, title1);
  496 + TextPageData<Asset> pageData = null;
  497 + do {
  498 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  499 + loadedAssetsTitle1.addAll(pageData.getData());
  500 + if (pageData.hasNext()) {
  501 + pageLink = pageData.getNextPageLink();
  502 + }
  503 + } while (pageData.hasNext());
  504 +
  505 + Collections.sort(assetsTitle1, idComparator);
  506 + Collections.sort(loadedAssetsTitle1, idComparator);
  507 +
  508 + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
  509 +
  510 + List<Asset> loadedAssetsTitle2 = new ArrayList<>();
  511 + pageLink = new TextPageLink(4, title2);
  512 + do {
  513 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  514 + loadedAssetsTitle2.addAll(pageData.getData());
  515 + if (pageData.hasNext()) {
  516 + pageLink = pageData.getNextPageLink();
  517 + }
  518 + } while (pageData.hasNext());
  519 +
  520 + Collections.sort(assetsTitle2, idComparator);
  521 + Collections.sort(loadedAssetsTitle2, idComparator);
  522 +
  523 + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
  524 +
  525 + for (Asset asset : loadedAssetsTitle1) {
  526 + assetService.deleteAsset(asset.getId());
  527 + }
  528 +
  529 + pageLink = new TextPageLink(4, title1);
  530 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  531 + Assert.assertFalse(pageData.hasNext());
  532 + Assert.assertEquals(0, pageData.getData().size());
  533 +
  534 + for (Asset asset : loadedAssetsTitle2) {
  535 + assetService.deleteAsset(asset.getId());
  536 + }
  537 +
  538 + pageLink = new TextPageLink(4, title2);
  539 + pageData = assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink);
  540 + Assert.assertFalse(pageData.hasNext());
  541 + Assert.assertEquals(0, pageData.getData().size());
  542 + customerService.deleteCustomer(customerId);
  543 + }
  544 +
  545 + @Test
  546 + public void testFindAssetsByTenantIdCustomerIdAndType() {
  547 +
  548 + Customer customer = new Customer();
  549 + customer.setTitle("Test customer");
  550 + customer.setTenantId(tenantId);
  551 + customer = customerService.saveCustomer(customer);
  552 + CustomerId customerId = customer.getId();
  553 +
  554 + String title1 = "Asset title 1";
  555 + String type1 = "typeC";
  556 + List<Asset> assetsType1 = new ArrayList<>();
  557 + for (int i=0;i<175;i++) {
  558 + Asset asset = new Asset();
  559 + asset.setTenantId(tenantId);
  560 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  561 + String name = title1+suffix;
  562 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  563 + asset.setName(name);
  564 + asset.setType(type1);
  565 + asset = assetService.saveAsset(asset);
  566 + assetsType1.add(assetService.assignAssetToCustomer(asset.getId(), customerId));
  567 + }
  568 + String title2 = "Asset title 2";
  569 + String type2 = "typeD";
  570 + List<Asset> assetsType2 = new ArrayList<>();
  571 + for (int i=0;i<143;i++) {
  572 + Asset asset = new Asset();
  573 + asset.setTenantId(tenantId);
  574 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  575 + String name = title2+suffix;
  576 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  577 + asset.setName(name);
  578 + asset.setType(type2);
  579 + asset = assetService.saveAsset(asset);
  580 + assetsType2.add(assetService.assignAssetToCustomer(asset.getId(), customerId));
  581 + }
  582 +
  583 + List<Asset> loadedAssetsType1 = new ArrayList<>();
  584 + TextPageLink pageLink = new TextPageLink(15);
  585 + TextPageData<Asset> pageData = null;
  586 + do {
  587 + pageData = assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type1, pageLink);
  588 + loadedAssetsType1.addAll(pageData.getData());
  589 + if (pageData.hasNext()) {
  590 + pageLink = pageData.getNextPageLink();
  591 + }
  592 + } while (pageData.hasNext());
  593 +
  594 + Collections.sort(assetsType1, idComparator);
  595 + Collections.sort(loadedAssetsType1, idComparator);
  596 +
  597 + Assert.assertEquals(assetsType1, loadedAssetsType1);
  598 +
  599 + List<Asset> loadedAssetsType2 = new ArrayList<>();
  600 + pageLink = new TextPageLink(4);
  601 + do {
  602 + pageData = assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type2, pageLink);
  603 + loadedAssetsType2.addAll(pageData.getData());
  604 + if (pageData.hasNext()) {
  605 + pageLink = pageData.getNextPageLink();
  606 + }
  607 + } while (pageData.hasNext());
  608 +
  609 + Collections.sort(assetsType2, idComparator);
  610 + Collections.sort(loadedAssetsType2, idComparator);
  611 +
  612 + Assert.assertEquals(assetsType2, loadedAssetsType2);
  613 +
  614 + for (Asset asset : loadedAssetsType1) {
  615 + assetService.deleteAsset(asset.getId());
  616 + }
  617 +
  618 + pageLink = new TextPageLink(4);
  619 + pageData = assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type1, pageLink);
  620 + Assert.assertFalse(pageData.hasNext());
  621 + Assert.assertEquals(0, pageData.getData().size());
  622 +
  623 + for (Asset asset : loadedAssetsType2) {
  624 + assetService.deleteAsset(asset.getId());
  625 + }
  626 +
  627 + pageLink = new TextPageLink(4);
  628 + pageData = assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type2, pageLink);
  629 + Assert.assertFalse(pageData.hasNext());
  630 + Assert.assertEquals(0, pageData.getData().size());
  631 + customerService.deleteCustomer(customerId);
  632 + }
  633 +
  634 +}
@@ -58,6 +58,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -58,6 +58,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
58 public void testSaveDeviceCredentialsWithEmptyDevice() { 58 public void testSaveDeviceCredentialsWithEmptyDevice() {
59 Device device = new Device(); 59 Device device = new Device();
60 device.setName("My device"); 60 device.setName("My device");
  61 + device.setType("default");
61 device.setTenantId(tenantId); 62 device.setTenantId(tenantId);
62 device = deviceService.saveDevice(device); 63 device = deviceService.saveDevice(device);
63 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 64 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -73,6 +74,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -73,6 +74,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
73 public void testSaveDeviceCredentialsWithEmptyCredentialsType() { 74 public void testSaveDeviceCredentialsWithEmptyCredentialsType() {
74 Device device = new Device(); 75 Device device = new Device();
75 device.setName("My device"); 76 device.setName("My device");
  77 + device.setType("default");
76 device.setTenantId(tenantId); 78 device.setTenantId(tenantId);
77 device = deviceService.saveDevice(device); 79 device = deviceService.saveDevice(device);
78 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 80 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -88,6 +90,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -88,6 +90,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
88 public void testSaveDeviceCredentialsWithEmptyCredentialsId() { 90 public void testSaveDeviceCredentialsWithEmptyCredentialsId() {
89 Device device = new Device(); 91 Device device = new Device();
90 device.setName("My device"); 92 device.setName("My device");
  93 + device.setType("default");
91 device.setTenantId(tenantId); 94 device.setTenantId(tenantId);
92 device = deviceService.saveDevice(device); 95 device = deviceService.saveDevice(device);
93 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 96 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -103,6 +106,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -103,6 +106,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
103 public void testSaveNonExistentDeviceCredentials() { 106 public void testSaveNonExistentDeviceCredentials() {
104 Device device = new Device(); 107 Device device = new Device();
105 device.setName("My device"); 108 device.setName("My device");
  109 + device.setType("default");
106 device.setTenantId(tenantId); 110 device.setTenantId(tenantId);
107 device = deviceService.saveDevice(device); 111 device = deviceService.saveDevice(device);
108 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 112 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -122,6 +126,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -122,6 +126,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
122 public void testSaveDeviceCredentialsWithNonExistentDevice() { 126 public void testSaveDeviceCredentialsWithNonExistentDevice() {
123 Device device = new Device(); 127 Device device = new Device();
124 device.setName("My device"); 128 device.setName("My device");
  129 + device.setType("default");
125 device.setTenantId(tenantId); 130 device.setTenantId(tenantId);
126 device = deviceService.saveDevice(device); 131 device = deviceService.saveDevice(device);
127 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 132 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -137,6 +142,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -137,6 +142,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
137 public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() { 142 public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() {
138 Device device = new Device(); 143 Device device = new Device();
139 device.setName("My device"); 144 device.setName("My device");
  145 + device.setType("default");
140 device.setTenantId(tenantId); 146 device.setTenantId(tenantId);
141 device = deviceService.saveDevice(device); 147 device = deviceService.saveDevice(device);
142 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); 148 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId());
@@ -153,6 +159,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -153,6 +159,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
153 Device device = new Device(); 159 Device device = new Device();
154 device.setTenantId(tenantId); 160 device.setTenantId(tenantId);
155 device.setName("My device"); 161 device.setName("My device");
  162 + device.setType("default");
156 Device savedDevice = deviceService.saveDevice(device); 163 Device savedDevice = deviceService.saveDevice(device);
157 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); 164 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId());
158 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); 165 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId());
@@ -166,6 +173,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -166,6 +173,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
166 Device device = new Device(); 173 Device device = new Device();
167 device.setTenantId(tenantId); 174 device.setTenantId(tenantId);
168 device.setName("My device"); 175 device.setName("My device");
  176 + device.setType("default");
169 Device savedDevice = deviceService.saveDevice(device); 177 Device savedDevice = deviceService.saveDevice(device);
170 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); 178 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId());
171 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); 179 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId());
@@ -181,6 +189,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { @@ -181,6 +189,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest {
181 Device device = new Device(); 189 Device device = new Device();
182 device.setTenantId(tenantId); 190 device.setTenantId(tenantId);
183 device.setName("My device"); 191 device.setName("My device");
  192 + device.setType("default");
184 Device savedDevice = deviceService.saveDevice(device); 193 Device savedDevice = deviceService.saveDevice(device);
185 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); 194 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId());
186 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); 195 Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId());
@@ -24,6 +24,7 @@ import org.junit.Test; @@ -24,6 +24,7 @@ import org.junit.Test;
24 import org.thingsboard.server.common.data.Customer; 24 import org.thingsboard.server.common.data.Customer;
25 import org.thingsboard.server.common.data.Device; 25 import org.thingsboard.server.common.data.Device;
26 import org.thingsboard.server.common.data.Tenant; 26 import org.thingsboard.server.common.data.Tenant;
  27 +import org.thingsboard.server.common.data.TenantDeviceType;
27 import org.thingsboard.server.common.data.id.CustomerId; 28 import org.thingsboard.server.common.data.id.CustomerId;
28 import org.thingsboard.server.common.data.id.DeviceCredentialsId; 29 import org.thingsboard.server.common.data.id.DeviceCredentialsId;
29 import org.thingsboard.server.common.data.id.DeviceId; 30 import org.thingsboard.server.common.data.id.DeviceId;
@@ -37,6 +38,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; @@ -37,6 +38,7 @@ import org.thingsboard.server.dao.exception.DataValidationException;
37 import java.util.ArrayList; 38 import java.util.ArrayList;
38 import java.util.Collections; 39 import java.util.Collections;
39 import java.util.List; 40 import java.util.List;
  41 +import java.util.concurrent.Executors;
40 42
41 import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; 43 import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
42 44
@@ -65,6 +67,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -65,6 +67,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
65 Device device = new Device(); 67 Device device = new Device();
66 device.setTenantId(tenantId); 68 device.setTenantId(tenantId);
67 device.setName("My device"); 69 device.setName("My device");
  70 + device.setType("default");
68 Device savedDevice = deviceService.saveDevice(device); 71 Device savedDevice = deviceService.saveDevice(device);
69 72
70 Assert.assertNotNull(savedDevice); 73 Assert.assertNotNull(savedDevice);
@@ -95,6 +98,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -95,6 +98,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
95 @Test(expected = DataValidationException.class) 98 @Test(expected = DataValidationException.class)
96 public void testSaveDeviceWithEmptyName() { 99 public void testSaveDeviceWithEmptyName() {
97 Device device = new Device(); 100 Device device = new Device();
  101 + device.setType("default");
98 device.setTenantId(tenantId); 102 device.setTenantId(tenantId);
99 deviceService.saveDevice(device); 103 deviceService.saveDevice(device);
100 } 104 }
@@ -103,6 +107,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -103,6 +107,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
103 public void testSaveDeviceWithEmptyTenant() { 107 public void testSaveDeviceWithEmptyTenant() {
104 Device device = new Device(); 108 Device device = new Device();
105 device.setName("My device"); 109 device.setName("My device");
  110 + device.setType("default");
106 deviceService.saveDevice(device); 111 deviceService.saveDevice(device);
107 } 112 }
108 113
@@ -110,6 +115,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -110,6 +115,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
110 public void testSaveDeviceWithInvalidTenant() { 115 public void testSaveDeviceWithInvalidTenant() {
111 Device device = new Device(); 116 Device device = new Device();
112 device.setName("My device"); 117 device.setName("My device");
  118 + device.setType("default");
113 device.setTenantId(new TenantId(UUIDs.timeBased())); 119 device.setTenantId(new TenantId(UUIDs.timeBased()));
114 deviceService.saveDevice(device); 120 deviceService.saveDevice(device);
115 } 121 }
@@ -118,6 +124,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -118,6 +124,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
118 public void testAssignDeviceToNonExistentCustomer() { 124 public void testAssignDeviceToNonExistentCustomer() {
119 Device device = new Device(); 125 Device device = new Device();
120 device.setName("My device"); 126 device.setName("My device");
  127 + device.setType("default");
121 device.setTenantId(tenantId); 128 device.setTenantId(tenantId);
122 device = deviceService.saveDevice(device); 129 device = deviceService.saveDevice(device);
123 try { 130 try {
@@ -131,6 +138,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -131,6 +138,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
131 public void testAssignDeviceToCustomerFromDifferentTenant() { 138 public void testAssignDeviceToCustomerFromDifferentTenant() {
132 Device device = new Device(); 139 Device device = new Device();
133 device.setName("My device"); 140 device.setName("My device");
  141 + device.setType("default");
134 device.setTenantId(tenantId); 142 device.setTenantId(tenantId);
135 device = deviceService.saveDevice(device); 143 device = deviceService.saveDevice(device);
136 Tenant tenant = new Tenant(); 144 Tenant tenant = new Tenant();
@@ -153,18 +161,56 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -153,18 +161,56 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
153 Device device = new Device(); 161 Device device = new Device();
154 device.setTenantId(tenantId); 162 device.setTenantId(tenantId);
155 device.setName("My device"); 163 device.setName("My device");
  164 + device.setType("default");
156 Device savedDevice = deviceService.saveDevice(device); 165 Device savedDevice = deviceService.saveDevice(device);
157 Device foundDevice = deviceService.findDeviceById(savedDevice.getId()); 166 Device foundDevice = deviceService.findDeviceById(savedDevice.getId());
158 Assert.assertNotNull(foundDevice); 167 Assert.assertNotNull(foundDevice);
159 Assert.assertEquals(savedDevice, foundDevice); 168 Assert.assertEquals(savedDevice, foundDevice);
160 deviceService.deleteDevice(savedDevice.getId()); 169 deviceService.deleteDevice(savedDevice.getId());
161 } 170 }
  171 +
  172 + @Test
  173 + public void testFindDeviceTypesByTenantId() throws Exception {
  174 + List<Device> devices = new ArrayList<>();
  175 + try {
  176 + for (int i=0;i<3;i++) {
  177 + Device device = new Device();
  178 + device.setTenantId(tenantId);
  179 + device.setName("My device B"+i);
  180 + device.setType("typeB");
  181 + devices.add(deviceService.saveDevice(device));
  182 + }
  183 + for (int i=0;i<7;i++) {
  184 + Device device = new Device();
  185 + device.setTenantId(tenantId);
  186 + device.setName("My device C"+i);
  187 + device.setType("typeC");
  188 + devices.add(deviceService.saveDevice(device));
  189 + }
  190 + for (int i=0;i<9;i++) {
  191 + Device device = new Device();
  192 + device.setTenantId(tenantId);
  193 + device.setName("My device A"+i);
  194 + device.setType("typeA");
  195 + devices.add(deviceService.saveDevice(device));
  196 + }
  197 + List<TenantDeviceType> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get();
  198 + Assert.assertNotNull(deviceTypes);
  199 + Assert.assertEquals(3, deviceTypes.size());
  200 + Assert.assertEquals("typeA", deviceTypes.get(0).getType());
  201 + Assert.assertEquals("typeB", deviceTypes.get(1).getType());
  202 + Assert.assertEquals("typeC", deviceTypes.get(2).getType());
  203 + } finally {
  204 + devices.forEach((device) -> { deviceService.deleteDevice(device.getId()); });
  205 + }
  206 + }
162 207
163 @Test 208 @Test
164 public void testDeleteDevice() { 209 public void testDeleteDevice() {
165 Device device = new Device(); 210 Device device = new Device();
166 device.setTenantId(tenantId); 211 device.setTenantId(tenantId);
167 device.setName("My device"); 212 device.setName("My device");
  213 + device.setType("default");
168 Device savedDevice = deviceService.saveDevice(device); 214 Device savedDevice = deviceService.saveDevice(device);
169 Device foundDevice = deviceService.findDeviceById(savedDevice.getId()); 215 Device foundDevice = deviceService.findDeviceById(savedDevice.getId());
170 Assert.assertNotNull(foundDevice); 216 Assert.assertNotNull(foundDevice);
@@ -188,6 +234,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -188,6 +234,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
188 Device device = new Device(); 234 Device device = new Device();
189 device.setTenantId(tenantId); 235 device.setTenantId(tenantId);
190 device.setName("Device"+i); 236 device.setName("Device"+i);
  237 + device.setType("default");
191 devices.add(deviceService.saveDevice(device)); 238 devices.add(deviceService.saveDevice(device));
192 } 239 }
193 240
@@ -216,7 +263,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -216,7 +263,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
216 263
217 tenantService.deleteTenant(tenantId); 264 tenantService.deleteTenant(tenantId);
218 } 265 }
219 - 266 +
220 @Test 267 @Test
221 public void testFindDevicesByTenantIdAndName() { 268 public void testFindDevicesByTenantIdAndName() {
222 String title1 = "Device title 1"; 269 String title1 = "Device title 1";
@@ -228,6 +275,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -228,6 +275,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
228 String name = title1+suffix; 275 String name = title1+suffix;
229 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 276 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
230 device.setName(name); 277 device.setName(name);
  278 + device.setType("default");
231 devicesTitle1.add(deviceService.saveDevice(device)); 279 devicesTitle1.add(deviceService.saveDevice(device));
232 } 280 }
233 String title2 = "Device title 2"; 281 String title2 = "Device title 2";
@@ -239,6 +287,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -239,6 +287,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
239 String name = title2+suffix; 287 String name = title2+suffix;
240 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 288 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
241 device.setName(name); 289 device.setName(name);
  290 + device.setType("default");
242 devicesTitle2.add(deviceService.saveDevice(device)); 291 devicesTitle2.add(deviceService.saveDevice(device));
243 } 292 }
244 293
@@ -291,6 +340,85 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -291,6 +340,85 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
291 Assert.assertFalse(pageData.hasNext()); 340 Assert.assertFalse(pageData.hasNext());
292 Assert.assertEquals(0, pageData.getData().size()); 341 Assert.assertEquals(0, pageData.getData().size());
293 } 342 }
  343 +
  344 + @Test
  345 + public void testFindDevicesByTenantIdAndType() {
  346 + String title1 = "Device title 1";
  347 + String type1 = "typeA";
  348 + List<Device> devicesType1 = new ArrayList<>();
  349 + for (int i=0;i<143;i++) {
  350 + Device device = new Device();
  351 + device.setTenantId(tenantId);
  352 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  353 + String name = title1+suffix;
  354 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  355 + device.setName(name);
  356 + device.setType(type1);
  357 + devicesType1.add(deviceService.saveDevice(device));
  358 + }
  359 + String title2 = "Device title 2";
  360 + String type2 = "typeB";
  361 + List<Device> devicesType2 = new ArrayList<>();
  362 + for (int i=0;i<175;i++) {
  363 + Device device = new Device();
  364 + device.setTenantId(tenantId);
  365 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  366 + String name = title2+suffix;
  367 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  368 + device.setName(name);
  369 + device.setType(type2);
  370 + devicesType2.add(deviceService.saveDevice(device));
  371 + }
  372 +
  373 + List<Device> loadedDevicesType1 = new ArrayList<>();
  374 + TextPageLink pageLink = new TextPageLink(15);
  375 + TextPageData<Device> pageData = null;
  376 + do {
  377 + pageData = deviceService.findDevicesByTenantIdAndType(tenantId, type1, pageLink);
  378 + loadedDevicesType1.addAll(pageData.getData());
  379 + if (pageData.hasNext()) {
  380 + pageLink = pageData.getNextPageLink();
  381 + }
  382 + } while (pageData.hasNext());
  383 +
  384 + Collections.sort(devicesType1, idComparator);
  385 + Collections.sort(loadedDevicesType1, idComparator);
  386 +
  387 + Assert.assertEquals(devicesType1, loadedDevicesType1);
  388 +
  389 + List<Device> loadedDevicesType2 = new ArrayList<>();
  390 + pageLink = new TextPageLink(4);
  391 + do {
  392 + pageData = deviceService.findDevicesByTenantIdAndType(tenantId, type2, pageLink);
  393 + loadedDevicesType2.addAll(pageData.getData());
  394 + if (pageData.hasNext()) {
  395 + pageLink = pageData.getNextPageLink();
  396 + }
  397 + } while (pageData.hasNext());
  398 +
  399 + Collections.sort(devicesType2, idComparator);
  400 + Collections.sort(loadedDevicesType2, idComparator);
  401 +
  402 + Assert.assertEquals(devicesType2, loadedDevicesType2);
  403 +
  404 + for (Device device : loadedDevicesType1) {
  405 + deviceService.deleteDevice(device.getId());
  406 + }
  407 +
  408 + pageLink = new TextPageLink(4);
  409 + pageData = deviceService.findDevicesByTenantIdAndType(tenantId, type1, pageLink);
  410 + Assert.assertFalse(pageData.hasNext());
  411 + Assert.assertEquals(0, pageData.getData().size());
  412 +
  413 + for (Device device : loadedDevicesType2) {
  414 + deviceService.deleteDevice(device.getId());
  415 + }
  416 +
  417 + pageLink = new TextPageLink(4);
  418 + pageData = deviceService.findDevicesByTenantIdAndType(tenantId, type2, pageLink);
  419 + Assert.assertFalse(pageData.hasNext());
  420 + Assert.assertEquals(0, pageData.getData().size());
  421 + }
294 422
295 @Test 423 @Test
296 public void testFindDevicesByTenantIdAndCustomerId() { 424 public void testFindDevicesByTenantIdAndCustomerId() {
@@ -311,6 +439,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -311,6 +439,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
311 Device device = new Device(); 439 Device device = new Device();
312 device.setTenantId(tenantId); 440 device.setTenantId(tenantId);
313 device.setName("Device"+i); 441 device.setName("Device"+i);
  442 + device.setType("default");
314 device = deviceService.saveDevice(device); 443 device = deviceService.saveDevice(device);
315 devices.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); 444 devices.add(deviceService.assignDeviceToCustomer(device.getId(), customerId));
316 } 445 }
@@ -359,6 +488,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -359,6 +488,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
359 String name = title1+suffix; 488 String name = title1+suffix;
360 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 489 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
361 device.setName(name); 490 device.setName(name);
  491 + device.setType("default");
362 device = deviceService.saveDevice(device); 492 device = deviceService.saveDevice(device);
363 devicesTitle1.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); 493 devicesTitle1.add(deviceService.assignDeviceToCustomer(device.getId(), customerId));
364 } 494 }
@@ -371,6 +501,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -371,6 +501,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
371 String name = title2+suffix; 501 String name = title2+suffix;
372 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); 502 name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
373 device.setName(name); 503 device.setName(name);
  504 + device.setType("default");
374 device = deviceService.saveDevice(device); 505 device = deviceService.saveDevice(device);
375 devicesTitle2.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); 506 devicesTitle2.add(deviceService.assignDeviceToCustomer(device.getId(), customerId));
376 } 507 }
@@ -425,4 +556,94 @@ public class DeviceServiceImplTest extends AbstractServiceTest { @@ -425,4 +556,94 @@ public class DeviceServiceImplTest extends AbstractServiceTest {
425 Assert.assertEquals(0, pageData.getData().size()); 556 Assert.assertEquals(0, pageData.getData().size());
426 customerService.deleteCustomer(customerId); 557 customerService.deleteCustomer(customerId);
427 } 558 }
  559 +
  560 + @Test
  561 + public void testFindDevicesByTenantIdCustomerIdAndType() {
  562 +
  563 + Customer customer = new Customer();
  564 + customer.setTitle("Test customer");
  565 + customer.setTenantId(tenantId);
  566 + customer = customerService.saveCustomer(customer);
  567 + CustomerId customerId = customer.getId();
  568 +
  569 + String title1 = "Device title 1";
  570 + String type1 = "typeC";
  571 + List<Device> devicesType1 = new ArrayList<>();
  572 + for (int i=0;i<175;i++) {
  573 + Device device = new Device();
  574 + device.setTenantId(tenantId);
  575 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  576 + String name = title1+suffix;
  577 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  578 + device.setName(name);
  579 + device.setType(type1);
  580 + device = deviceService.saveDevice(device);
  581 + devicesType1.add(deviceService.assignDeviceToCustomer(device.getId(), customerId));
  582 + }
  583 + String title2 = "Device title 2";
  584 + String type2 = "typeD";
  585 + List<Device> devicesType2 = new ArrayList<>();
  586 + for (int i=0;i<143;i++) {
  587 + Device device = new Device();
  588 + device.setTenantId(tenantId);
  589 + String suffix = RandomStringUtils.randomAlphanumeric(15);
  590 + String name = title2+suffix;
  591 + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
  592 + device.setName(name);
  593 + device.setType(type2);
  594 + device = deviceService.saveDevice(device);
  595 + devicesType2.add(deviceService.assignDeviceToCustomer(device.getId(), customerId));
  596 + }
  597 +
  598 + List<Device> loadedDevicesType1 = new ArrayList<>();
  599 + TextPageLink pageLink = new TextPageLink(15);
  600 + TextPageData<Device> pageData = null;
  601 + do {
  602 + pageData = deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type1, pageLink);
  603 + loadedDevicesType1.addAll(pageData.getData());
  604 + if (pageData.hasNext()) {
  605 + pageLink = pageData.getNextPageLink();
  606 + }
  607 + } while (pageData.hasNext());
  608 +
  609 + Collections.sort(devicesType1, idComparator);
  610 + Collections.sort(loadedDevicesType1, idComparator);
  611 +
  612 + Assert.assertEquals(devicesType1, loadedDevicesType1);
  613 +
  614 + List<Device> loadedDevicesType2 = new ArrayList<>();
  615 + pageLink = new TextPageLink(4);
  616 + do {
  617 + pageData = deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type2, pageLink);
  618 + loadedDevicesType2.addAll(pageData.getData());
  619 + if (pageData.hasNext()) {
  620 + pageLink = pageData.getNextPageLink();
  621 + }
  622 + } while (pageData.hasNext());
  623 +
  624 + Collections.sort(devicesType2, idComparator);
  625 + Collections.sort(loadedDevicesType2, idComparator);
  626 +
  627 + Assert.assertEquals(devicesType2, loadedDevicesType2);
  628 +
  629 + for (Device device : loadedDevicesType1) {
  630 + deviceService.deleteDevice(device.getId());
  631 + }
  632 +
  633 + pageLink = new TextPageLink(4);
  634 + pageData = deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type1, pageLink);
  635 + Assert.assertFalse(pageData.hasNext());
  636 + Assert.assertEquals(0, pageData.getData().size());
  637 +
  638 + for (Device device : loadedDevicesType2) {
  639 + deviceService.deleteDevice(device.getId());
  640 + }
  641 +
  642 + pageLink = new TextPageLink(4);
  643 + pageData = deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type2, pageLink);
  644 + Assert.assertFalse(pageData.hasNext());
  645 + Assert.assertEquals(0, pageData.getData().size());
  646 + customerService.deleteCustomer(customerId);
  647 + }
  648 +
428 } 649 }
1 CASSANDRA_DATA_DIR=/home/docker/cassandra_volume 1 CASSANDRA_DATA_DIR=/home/docker/cassandra_volume
  2 +
  3 +# cassandra schema container environment variables
  4 +CREATE_SCHEMA=true
  5 +ADD_SYSTEM_DATA=false
  6 +ADD_DEMO_DATA=false
  7 +CASSANDRA_URL=cassandra
  1 +#
  2 +# Copyright © 2016-2017 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 +apiVersion: v1
  18 +kind: Service
  19 +metadata:
  20 + name: cassandra-headless
  21 + labels:
  22 + app: cassandra-headless
  23 +spec:
  24 + ports:
  25 + - port: 9042
  26 + name: cql
  27 + clusterIP: None
  28 + selector:
  29 + app: cassandra
  30 +---
  31 +apiVersion: "apps/v1beta1"
  32 +kind: StatefulSet
  33 +metadata:
  34 + name: cassandra
  35 +spec:
  36 + serviceName: cassandra-headless
  37 + replicas: 2
  38 + template:
  39 + metadata:
  40 + labels:
  41 + app: cassandra
  42 + spec:
  43 + nodeSelector:
  44 + machinetype: other
  45 + affinity:
  46 + podAntiAffinity:
  47 + requiredDuringSchedulingIgnoredDuringExecution:
  48 + - labelSelector:
  49 + matchExpressions:
  50 + - key: "app"
  51 + operator: In
  52 + values:
  53 + - cassandra-headless
  54 + topologyKey: "kubernetes.io/hostname"
  55 + containers:
  56 + - name: cassandra
  57 + image: cassandra:3.9
  58 + imagePullPolicy: Always
  59 + ports:
  60 + - containerPort: 7000
  61 + name: intra-node
  62 + - containerPort: 7001
  63 + name: tls-intra-node
  64 + - containerPort: 7199
  65 + name: jmx
  66 + - containerPort: 9042
  67 + name: cql
  68 + - containerPort: 9160
  69 + name: thrift
  70 + securityContext:
  71 + capabilities:
  72 + add:
  73 + - IPC_LOCK
  74 + lifecycle:
  75 + preStop:
  76 + exec:
  77 + command: ["/bin/sh", "-c", "PID=$(pidof java) && kill $PID && while ps -p $PID > /dev/null; do sleep 1; done"]
  78 + env:
  79 + - name: MAX_HEAP_SIZE
  80 + value: 2048M
  81 + - name: HEAP_NEWSIZE
  82 + value: 100M
  83 + - name: CASSANDRA_SEEDS
  84 + value: "cassandra-0.cassandra-headless.default.svc.cluster.local"
  85 + - name: CASSANDRA_CLUSTER_NAME
  86 + value: "Thingsboard-Cluster"
  87 + - name: CASSANDRA_DC
  88 + value: "DC1-Thingsboard-Cluster"
  89 + - name: CASSANDRA_RACK
  90 + value: "Rack-Thingsboard-Cluster"
  91 + - name: CASSANDRA_AUTO_BOOTSTRAP
  92 + value: "false"
  93 + - name: POD_IP
  94 + valueFrom:
  95 + fieldRef:
  96 + fieldPath: status.podIP
  97 + - name: POD_NAMESPACE
  98 + valueFrom:
  99 + fieldRef:
  100 + fieldPath: metadata.namespace
  101 + readinessProbe:
  102 + exec:
  103 + command:
  104 + - /bin/bash
  105 + - -c
  106 + - /ready-probe.sh
  107 + initialDelaySeconds: 15
  108 + timeoutSeconds: 5
  109 + volumeMounts:
  110 + - name: cassandra-data
  111 + mountPath: /var/lib/cassandra/data
  112 + - name: cassandra-commitlog
  113 + mountPath: /var/lib/cassandra/commitlog
  114 + volumeClaimTemplates:
  115 + - metadata:
  116 + name: cassandra-data
  117 + annotations:
  118 + volume.beta.kubernetes.io/storage-class: fast
  119 + spec:
  120 + accessModes: [ "ReadWriteOnce" ]
  121 + resources:
  122 + requests:
  123 + storage: 3Gi
  124 + - metadata:
  125 + name: cassandra-commitlog
  126 + annotations:
  127 + volume.beta.kubernetes.io/storage-class: fast
  128 + spec:
  129 + accessModes: [ "ReadWriteOnce" ]
  130 + resources:
  131 + requests:
  132 + storage: 2Gi
docker/common/common.yaml renamed from docker/docker-compose.random.yml
@@ -14,13 +14,20 @@ @@ -14,13 +14,20 @@
14 # limitations under the License. 14 # limitations under the License.
15 # 15 #
16 16
17 -version: '2'  
18 -  
19 -services:  
20 - db:  
21 - ports:  
22 - - "9042"  
23 - - "9160"  
24 - zk:  
25 - ports:  
26 - - "2181" 17 +---
  18 +apiVersion: storage.k8s.io/v1beta1
  19 +kind: StorageClass
  20 +metadata:
  21 + name: slow
  22 +provisioner: kubernetes.io/gce-pd
  23 +parameters:
  24 + type: pd-standard
  25 +---
  26 +apiVersion: storage.k8s.io/v1beta1
  27 +kind: StorageClass
  28 +metadata:
  29 + name: fast
  30 +provisioner: kubernetes.io/gce-pd
  31 +parameters:
  32 + type: pd-ssd
  33 +---
1 -#!/bin/bash  
2 -#  
3 -# Copyright © 2016-2017 The Thingsboard Authors  
4 -#  
5 -# Licensed under the Apache License, Version 2.0 (the "License");  
6 -# you may not use this file except in compliance with the License.  
7 -# You may obtain a copy of the License at  
8 -#  
9 -# http://www.apache.org/licenses/LICENSE-2.0  
10 -#  
11 -# Unless required by applicable law or agreed to in writing, software  
12 -# distributed under the License is distributed on an "AS IS" BASIS,  
13 -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
14 -# See the License for the specific language governing permissions and  
15 -# limitations under the License.  
16 -#  
17 -  
18 -  
19 -command='docker-compose -f docker-compose.yml -f docker-compose.random.yml'  
20 -  
21 -echo "stopping images.."  
22 -$command stop  
23 -  
24 -echo "removing stopped images.."  
25 -$command rm -f  
26 -  
27 -echo "building images.."  
28 -$command build  
29 -  
30 -echo "starting images..."  
31 -$command up -d  
1 -#!/bin/bash  
2 -#  
3 -# Copyright © 2016-2017 The Thingsboard Authors  
4 -#  
5 -# Licensed under the Apache License, Version 2.0 (the "License");  
6 -# you may not use this file except in compliance with the License.  
7 -# You may obtain a copy of the License at  
8 -#  
9 -# http://www.apache.org/licenses/LICENSE-2.0  
10 -#  
11 -# Unless required by applicable law or agreed to in writing, software  
12 -# distributed under the License is distributed on an "AS IS" BASIS,  
13 -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
14 -# See the License for the specific language governing permissions and  
15 -# limitations under the License.  
16 -#  
17 -  
18 -  
19 -command='docker-compose -f docker-compose.yml -f docker-compose.static.yml'  
20 -  
21 -echo "stopping images.."  
22 -$command stop  
23 -  
24 -echo "removing stopped images.."  
25 -$command rm -f  
26 -  
27 -echo "building images.."  
28 -$command build  
29 -  
30 -echo "starting cassandra, zookeeper, thingsboard-db-schema images..."  
31 -$command up -d db zk thingsboard-db-schema