Showing
47 changed files
with
2688 additions
and
1072 deletions
Too many changes to show.
To preserve performance only 47 of 94 files are displayed.
... | ... | @@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; |
21 | 21 | import org.springframework.web.bind.annotation.*; |
22 | 22 | import org.thingsboard.server.common.data.Customer; |
23 | 23 | import org.thingsboard.server.common.data.asset.Asset; |
24 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | |
24 | 25 | import org.thingsboard.server.common.data.id.AssetId; |
25 | 26 | import org.thingsboard.server.common.data.id.CustomerId; |
26 | 27 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -136,13 +137,18 @@ public class AssetController extends BaseController { |
136 | 137 | @ResponseBody |
137 | 138 | public TextPageData<Asset> getTenantAssets( |
138 | 139 | @RequestParam int limit, |
140 | + @RequestParam(required = false) String type, | |
139 | 141 | @RequestParam(required = false) String textSearch, |
140 | 142 | @RequestParam(required = false) String idOffset, |
141 | 143 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
142 | 144 | try { |
143 | 145 | TenantId tenantId = getCurrentUser().getTenantId(); |
144 | 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 | 152 | } catch (Exception e) { |
147 | 153 | throw handleException(e); |
148 | 154 | } |
... | ... | @@ -167,6 +173,7 @@ public class AssetController extends BaseController { |
167 | 173 | public TextPageData<Asset> getCustomerAssets( |
168 | 174 | @PathVariable("customerId") String strCustomerId, |
169 | 175 | @RequestParam int limit, |
176 | + @RequestParam(required = false) String type, | |
170 | 177 | @RequestParam(required = false) String textSearch, |
171 | 178 | @RequestParam(required = false) String idOffset, |
172 | 179 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
... | ... | @@ -176,7 +183,11 @@ public class AssetController extends BaseController { |
176 | 183 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
177 | 184 | checkCustomerId(customerId); |
178 | 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 | 191 | } catch (Exception e) { |
181 | 192 | throw handleException(e); |
182 | 193 | } |
... | ... | @@ -231,4 +242,18 @@ public class AssetController extends BaseController { |
231 | 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 | 21 | import org.springframework.web.bind.annotation.*; |
22 | 22 | import org.thingsboard.server.common.data.Customer; |
23 | 23 | import org.thingsboard.server.common.data.Device; |
24 | +import org.thingsboard.server.common.data.TenantDeviceType; | |
24 | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
25 | 26 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | 27 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -166,13 +167,18 @@ public class DeviceController extends BaseController { |
166 | 167 | @ResponseBody |
167 | 168 | public TextPageData<Device> getTenantDevices( |
168 | 169 | @RequestParam int limit, |
170 | + @RequestParam(required = false) String type, | |
169 | 171 | @RequestParam(required = false) String textSearch, |
170 | 172 | @RequestParam(required = false) String idOffset, |
171 | 173 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
172 | 174 | try { |
173 | 175 | TenantId tenantId = getCurrentUser().getTenantId(); |
174 | 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 | 182 | } catch (Exception e) { |
177 | 183 | throw handleException(e); |
178 | 184 | } |
... | ... | @@ -197,6 +203,7 @@ public class DeviceController extends BaseController { |
197 | 203 | public TextPageData<Device> getCustomerDevices( |
198 | 204 | @PathVariable("customerId") String strCustomerId, |
199 | 205 | @RequestParam int limit, |
206 | + @RequestParam(required = false) String type, | |
200 | 207 | @RequestParam(required = false) String textSearch, |
201 | 208 | @RequestParam(required = false) String idOffset, |
202 | 209 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
... | ... | @@ -206,7 +213,11 @@ public class DeviceController extends BaseController { |
206 | 213 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
207 | 214 | checkCustomerId(customerId); |
208 | 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 | 221 | } catch (Exception e) { |
211 | 222 | throw handleException(e); |
212 | 223 | } |
... | ... | @@ -261,4 +272,19 @@ public class DeviceController extends BaseController { |
261 | 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 | } | ... | ... |
... | ... | @@ -98,13 +98,15 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC |
98 | 98 | @IntegrationTest("server.port:0") |
99 | 99 | public abstract class AbstractControllerTest { |
100 | 100 | |
101 | + protected static final String TEST_TENANT_NAME = "TEST TENANT"; | |
102 | + | |
101 | 103 | protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; |
102 | 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 | 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 | 110 | private static final String CUSTOMER_USER_PASSWORD = "customer"; |
109 | 111 | |
110 | 112 | protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), |
... | ... | @@ -147,7 +149,7 @@ public abstract class AbstractControllerTest { |
147 | 149 | loginSysAdmin(); |
148 | 150 | |
149 | 151 | Tenant tenant = new Tenant(); |
150 | - tenant.setTitle("Tenant"); | |
152 | + tenant.setTitle(TEST_TENANT_NAME); | |
151 | 153 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
152 | 154 | Assert.assertNotNull(savedTenant); |
153 | 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 | 24 | import java.util.List; |
25 | 25 | |
26 | 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 | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
32 | 29 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; |
33 | 30 | import org.thingsboard.server.common.data.id.DeviceId; |
... | ... | @@ -83,6 +80,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
83 | 80 | public void testSaveDevice() throws Exception { |
84 | 81 | Device device = new Device(); |
85 | 82 | device.setName("My device"); |
83 | + device.setType("default"); | |
86 | 84 | Device savedDevice = doPost("/api/device", device, Device.class); |
87 | 85 | |
88 | 86 | Assert.assertNotNull(savedDevice); |
... | ... | @@ -114,16 +112,49 @@ public class DeviceControllerTest extends AbstractControllerTest { |
114 | 112 | public void testFindDeviceById() throws Exception { |
115 | 113 | Device device = new Device(); |
116 | 114 | device.setName("My device"); |
115 | + device.setType("default"); | |
117 | 116 | Device savedDevice = doPost("/api/device", device, Device.class); |
118 | 117 | Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); |
119 | 118 | Assert.assertNotNull(foundDevice); |
120 | 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 | 153 | @Test |
124 | 154 | public void testDeleteDevice() throws Exception { |
125 | 155 | Device device = new Device(); |
126 | 156 | device.setName("My device"); |
157 | + device.setType("default"); | |
127 | 158 | Device savedDevice = doPost("/api/device", device, Device.class); |
128 | 159 | |
129 | 160 | doDelete("/api/device/"+savedDevice.getId().getId().toString()) |
... | ... | @@ -132,10 +163,20 @@ public class DeviceControllerTest extends AbstractControllerTest { |
132 | 163 | doGet("/api/device/"+savedDevice.getId().getId().toString()) |
133 | 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 | 176 | @Test |
137 | 177 | public void testSaveDeviceWithEmptyName() throws Exception { |
138 | 178 | Device device = new Device(); |
179 | + device.setType("default"); | |
139 | 180 | doPost("/api/device", device) |
140 | 181 | .andExpect(status().isBadRequest()) |
141 | 182 | .andExpect(statusReason(containsString("Device name should be specified"))); |
... | ... | @@ -145,6 +186,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
145 | 186 | public void testAssignUnassignDeviceToCustomer() throws Exception { |
146 | 187 | Device device = new Device(); |
147 | 188 | device.setName("My device"); |
189 | + device.setType("default"); | |
148 | 190 | Device savedDevice = doPost("/api/device", device, Device.class); |
149 | 191 | |
150 | 192 | Customer customer = new Customer(); |
... | ... | @@ -170,6 +212,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
170 | 212 | public void testAssignDeviceToNonExistentCustomer() throws Exception { |
171 | 213 | Device device = new Device(); |
172 | 214 | device.setName("My device"); |
215 | + device.setType("default"); | |
173 | 216 | Device savedDevice = doPost("/api/device", device, Device.class); |
174 | 217 | |
175 | 218 | doPost("/api/customer/" + UUIDs.timeBased().toString() |
... | ... | @@ -203,6 +246,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
203 | 246 | |
204 | 247 | Device device = new Device(); |
205 | 248 | device.setName("My device"); |
249 | + device.setType("default"); | |
206 | 250 | Device savedDevice = doPost("/api/device", device, Device.class); |
207 | 251 | |
208 | 252 | doPost("/api/customer/" + savedCustomer.getId().getId().toString() |
... | ... | @@ -219,6 +263,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
219 | 263 | public void testFindDeviceCredentialsByDeviceId() throws Exception { |
220 | 264 | Device device = new Device(); |
221 | 265 | device.setName("My device"); |
266 | + device.setType("default"); | |
222 | 267 | Device savedDevice = doPost("/api/device", device, Device.class); |
223 | 268 | DeviceCredentials deviceCredentials = |
224 | 269 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -229,6 +274,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
229 | 274 | public void testSaveDeviceCredentials() throws Exception { |
230 | 275 | Device device = new Device(); |
231 | 276 | device.setName("My device"); |
277 | + device.setType("default"); | |
232 | 278 | Device savedDevice = doPost("/api/device", device, Device.class); |
233 | 279 | DeviceCredentials deviceCredentials = |
234 | 280 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -255,6 +301,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
255 | 301 | public void testSaveDeviceCredentialsWithEmptyCredentialsType() throws Exception { |
256 | 302 | Device device = new Device(); |
257 | 303 | device.setName("My device"); |
304 | + device.setType("default"); | |
258 | 305 | Device savedDevice = doPost("/api/device", device, Device.class); |
259 | 306 | DeviceCredentials deviceCredentials = |
260 | 307 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -268,6 +315,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
268 | 315 | public void testSaveDeviceCredentialsWithEmptyCredentialsId() throws Exception { |
269 | 316 | Device device = new Device(); |
270 | 317 | device.setName("My device"); |
318 | + device.setType("default"); | |
271 | 319 | Device savedDevice = doPost("/api/device", device, Device.class); |
272 | 320 | DeviceCredentials deviceCredentials = |
273 | 321 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -281,6 +329,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
281 | 329 | public void testSaveNonExistentDeviceCredentials() throws Exception { |
282 | 330 | Device device = new Device(); |
283 | 331 | device.setName("My device"); |
332 | + device.setType("default"); | |
284 | 333 | Device savedDevice = doPost("/api/device", device, Device.class); |
285 | 334 | DeviceCredentials deviceCredentials = |
286 | 335 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -298,6 +347,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
298 | 347 | public void testSaveDeviceCredentialsWithNonExistentDevice() throws Exception { |
299 | 348 | Device device = new Device(); |
300 | 349 | device.setName("My device"); |
350 | + device.setType("default"); | |
301 | 351 | Device savedDevice = doPost("/api/device", device, Device.class); |
302 | 352 | DeviceCredentials deviceCredentials = |
303 | 353 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -307,9 +357,10 @@ public class DeviceControllerTest extends AbstractControllerTest { |
307 | 357 | } |
308 | 358 | |
309 | 359 | @Test |
310 | - public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() throws Exception { | |
360 | + public void testSaveDeviceCredentialsWithInvalidCredentialsIdLength() throws Exception { | |
311 | 361 | Device device = new Device(); |
312 | 362 | device.setName("My device"); |
363 | + device.setType("default"); | |
313 | 364 | Device savedDevice = doPost("/api/device", device, Device.class); |
314 | 365 | DeviceCredentials deviceCredentials = |
315 | 366 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
... | ... | @@ -325,6 +376,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
325 | 376 | for (int i=0;i<178;i++) { |
326 | 377 | Device device = new Device(); |
327 | 378 | device.setName("Device"+i); |
379 | + device.setType("default"); | |
328 | 380 | devices.add(doPost("/api/device", device, Device.class)); |
329 | 381 | } |
330 | 382 | List<Device> loadedDevices = new ArrayList<>(); |
... | ... | @@ -355,6 +407,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
355 | 407 | String name = title1+suffix; |
356 | 408 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
357 | 409 | device.setName(name); |
410 | + device.setType("default"); | |
358 | 411 | devicesTitle1.add(doPost("/api/device", device, Device.class)); |
359 | 412 | } |
360 | 413 | String title2 = "Device title 2"; |
... | ... | @@ -365,6 +418,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
365 | 418 | String name = title2+suffix; |
366 | 419 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
367 | 420 | device.setName(name); |
421 | + device.setType("default"); | |
368 | 422 | devicesTitle2.add(doPost("/api/device", device, Device.class)); |
369 | 423 | } |
370 | 424 | |
... | ... | @@ -423,6 +477,89 @@ public class DeviceControllerTest extends AbstractControllerTest { |
423 | 477 | Assert.assertFalse(pageData.hasNext()); |
424 | 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 | 564 | @Test |
428 | 565 | public void testFindCustomerDevices() throws Exception { |
... | ... | @@ -435,6 +572,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
435 | 572 | for (int i=0;i<128;i++) { |
436 | 573 | Device device = new Device(); |
437 | 574 | device.setName("Device"+i); |
575 | + device.setType("default"); | |
438 | 576 | device = doPost("/api/device", device, Device.class); |
439 | 577 | devices.add(doPost("/api/customer/" + customerId.getId().toString() |
440 | 578 | + "/device/" + device.getId().getId().toString(), Device.class)); |
... | ... | @@ -473,6 +611,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
473 | 611 | String name = title1+suffix; |
474 | 612 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
475 | 613 | device.setName(name); |
614 | + device.setType("default"); | |
476 | 615 | device = doPost("/api/device", device, Device.class); |
477 | 616 | devicesTitle1.add(doPost("/api/customer/" + customerId.getId().toString() |
478 | 617 | + "/device/" + device.getId().getId().toString(), Device.class)); |
... | ... | @@ -485,6 +624,7 @@ public class DeviceControllerTest extends AbstractControllerTest { |
485 | 624 | String name = title2+suffix; |
486 | 625 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
487 | 626 | device.setName(name); |
627 | + device.setType("default"); | |
488 | 628 | device = doPost("/api/device", device, Device.class); |
489 | 629 | devicesTitle2.add(doPost("/api/customer/" + customerId.getId().toString() |
490 | 630 | + "/device/" + device.getId().getId().toString(), Device.class)); |
... | ... | @@ -546,4 +686,96 @@ public class DeviceControllerTest extends AbstractControllerTest { |
546 | 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 | 130 | Assert.assertEquals(tenants, loadedTenants); |
131 | 131 | |
132 | 132 | for (Tenant tenant : loadedTenants) { |
133 | - if (!tenant.getTitle().equals("Tenant")) { | |
133 | + if (!tenant.getTitle().equals(TEST_TENANT_NAME)) { | |
134 | 134 | doDelete("/api/tenant/"+tenant.getId().getId().toString()) |
135 | 135 | .andExpect(status().isOk()); |
136 | 136 | } | ... | ... |
... | ... | @@ -182,7 +182,7 @@ public class UserControllerTest extends AbstractControllerTest { |
182 | 182 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
183 | 183 | Assert.assertNotNull(savedTenant); |
184 | 184 | |
185 | - String email = "tenant@thingsboard.org"; | |
185 | + String email = TENANT_ADMIN_EMAIL; | |
186 | 186 | User user = new User(); |
187 | 187 | user.setAuthority(Authority.TENANT_ADMIN); |
188 | 188 | user.setTenantId(savedTenant.getId()); | ... | ... |
... | ... | @@ -47,6 +47,7 @@ public class HttpDeviceApiTest extends AbstractControllerTest { |
47 | 47 | loginTenantAdmin(); |
48 | 48 | device = new Device(); |
49 | 49 | device.setName("My device"); |
50 | + device.setType("default"); | |
50 | 51 | device = doPost("/api/device", device, Device.class); |
51 | 52 | |
52 | 53 | deviceCredentials = | ... | ... |
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 | +} | ... | ... |
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 | +} | ... | ... |
... | ... | @@ -16,12 +16,11 @@ |
16 | 16 | package org.thingsboard.server.dao.asset; |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | -import org.thingsboard.server.common.data.Device; | |
20 | 19 | import org.thingsboard.server.common.data.asset.Asset; |
21 | 20 | import org.thingsboard.server.common.data.page.TextPageLink; |
22 | 21 | import org.thingsboard.server.dao.Dao; |
23 | 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 | 25 | import java.util.List; |
27 | 26 | import java.util.Optional; |
... | ... | @@ -51,6 +50,16 @@ public interface AssetDao extends Dao<AssetEntity> { |
51 | 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 | 63 | * Find assets by tenantId and assets Ids. |
55 | 64 | * |
56 | 65 | * @param tenantId the tenantId |
... | ... | @@ -70,6 +79,17 @@ public interface AssetDao extends Dao<AssetEntity> { |
70 | 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 | 93 | * Find assets by tenantId, customerId and assets Ids. |
74 | 94 | * |
75 | 95 | * @param tenantId the tenantId |
... | ... | @@ -87,4 +107,12 @@ public interface AssetDao extends Dao<AssetEntity> { |
87 | 107 | * @return the optional asset object |
88 | 108 | */ |
89 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.dao.asset; |
17 | 17 | |
18 | +import com.datastax.driver.core.ResultSet; | |
19 | +import com.datastax.driver.core.ResultSetFuture; | |
18 | 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 | 24 | import com.google.common.util.concurrent.ListenableFuture; |
20 | 25 | import lombok.extern.slf4j.Slf4j; |
21 | 26 | import org.springframework.stereotype.Component; |
... | ... | @@ -23,7 +28,9 @@ import org.thingsboard.server.common.data.asset.Asset; |
23 | 28 | import org.thingsboard.server.common.data.page.TextPageLink; |
24 | 29 | import org.thingsboard.server.dao.AbstractSearchTextDao; |
25 | 30 | import org.thingsboard.server.dao.model.AssetEntity; |
31 | +import org.thingsboard.server.dao.model.TenantAssetTypeEntity; | |
26 | 32 | |
33 | +import javax.annotation.Nullable; | |
27 | 34 | import java.util.*; |
28 | 35 | |
29 | 36 | import static com.datastax.driver.core.querybuilder.QueryBuilder.*; |
... | ... | @@ -60,6 +67,16 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements |
60 | 67 | } |
61 | 68 | |
62 | 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 | 80 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List<UUID> assetIds) { |
64 | 81 | log.debug("Try to find assets by tenantId [{}] and asset Ids [{}]", tenantId, assetIds); |
65 | 82 | Select select = select().from(getColumnFamilyName()); |
... | ... | @@ -82,6 +99,19 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements |
82 | 99 | } |
83 | 100 | |
84 | 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 | 115 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> assetIds) { |
86 | 116 | log.debug("Try to find assets by tenantId [{}], customerId [{}] and asset Ids [{}]", tenantId, customerId, assetIds); |
87 | 117 | Select select = select().from(getColumnFamilyName()); |
... | ... | @@ -101,4 +131,24 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements |
101 | 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 | 17 | |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import org.thingsboard.server.common.data.asset.Asset; |
20 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | |
20 | 21 | import org.thingsboard.server.common.data.id.AssetId; |
21 | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -34,7 +35,7 @@ public interface AssetService { |
34 | 35 | |
35 | 36 | Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name); |
36 | 37 | |
37 | - Asset saveAsset(Asset device); | |
38 | + Asset saveAsset(Asset asset); | |
38 | 39 | |
39 | 40 | Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId); |
40 | 41 | |
... | ... | @@ -44,16 +45,21 @@ public interface AssetService { |
44 | 45 | |
45 | 46 | TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink); |
46 | 47 | |
48 | + TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | |
49 | + | |
47 | 50 | ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); |
48 | 51 | |
49 | 52 | void deleteAssetsByTenantId(TenantId tenantId); |
50 | 53 | |
51 | 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 | 58 | ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); |
54 | 59 | |
55 | 60 | void unassignCustomerAssets(TenantId tenantId, CustomerId customerId); |
56 | 61 | |
57 | 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 | 26 | import org.springframework.util.StringUtils; |
27 | 27 | import org.thingsboard.server.common.data.EntityType; |
28 | 28 | import org.thingsboard.server.common.data.asset.Asset; |
29 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | |
29 | 30 | import org.thingsboard.server.common.data.id.AssetId; |
30 | 31 | import org.thingsboard.server.common.data.id.CustomerId; |
31 | 32 | import org.thingsboard.server.common.data.id.EntityId; |
... | ... | @@ -36,10 +37,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; |
36 | 37 | import org.thingsboard.server.dao.customer.CustomerDao; |
37 | 38 | import org.thingsboard.server.dao.entity.BaseEntityService; |
38 | 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 | 41 | import org.thingsboard.server.dao.relation.EntitySearchDirection; |
44 | 42 | import org.thingsboard.server.dao.service.DataValidator; |
45 | 43 | import org.thingsboard.server.dao.service.PaginatedRemover; |
... | ... | @@ -132,7 +130,18 @@ public class BaseAssetService extends BaseEntityService implements AssetService |
132 | 130 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
133 | 131 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantId(tenantId.getId(), pageLink); |
134 | 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 | 147 | @Override |
... | ... | @@ -159,7 +168,19 @@ public class BaseAssetService extends BaseEntityService implements AssetService |
159 | 168 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
160 | 169 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); |
161 | 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 | 186 | @Override |
... | ... | @@ -207,6 +228,25 @@ public class BaseAssetService extends BaseEntityService implements AssetService |
207 | 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 | 250 | private DataValidator<Asset> assetValidator = |
211 | 251 | new DataValidator<Asset>() { |
212 | 252 | |
... | ... | @@ -232,6 +272,9 @@ public class BaseAssetService extends BaseEntityService implements AssetService |
232 | 272 | |
233 | 273 | @Override |
234 | 274 | protected void validateDataImpl(Asset asset) { |
275 | + if (StringUtils.isEmpty(asset.getType())) { | |
276 | + throw new DataValidationException("Asset type should be specified!"); | |
277 | + } | |
235 | 278 | if (StringUtils.isEmpty(asset.getName())) { |
236 | 279 | throw new DataValidationException("Asset name should be specified!"); |
237 | 280 | } | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device; |
24 | 24 | import org.thingsboard.server.common.data.page.TextPageLink; |
25 | 25 | import org.thingsboard.server.dao.Dao; |
26 | 26 | import org.thingsboard.server.dao.model.DeviceEntity; |
27 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | |
27 | 28 | |
28 | 29 | /** |
29 | 30 | * The Interface DeviceDao. |
... | ... | @@ -49,6 +50,16 @@ public interface DeviceDao extends Dao<DeviceEntity> { |
49 | 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 | 63 | * Find devices by tenantId and devices Ids. |
53 | 64 | * |
54 | 65 | * @param tenantId the tenantId |
... | ... | @@ -68,6 +79,18 @@ public interface DeviceDao extends Dao<DeviceEntity> { |
68 | 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 | 94 | * Find devices by tenantId, customerId and devices Ids. |
72 | 95 | * |
73 | 96 | * @param tenantId the tenantId |
... | ... | @@ -85,4 +108,11 @@ public interface DeviceDao extends Dao<DeviceEntity> { |
85 | 108 | * @return the optional device object |
86 | 109 | */ |
87 | 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 | 22 | |
23 | 23 | import java.util.*; |
24 | 24 | |
25 | +import com.datastax.driver.core.ResultSet; | |
26 | +import com.datastax.driver.core.ResultSetFuture; | |
25 | 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 | 31 | import com.google.common.util.concurrent.ListenableFuture; |
27 | 32 | import lombok.extern.slf4j.Slf4j; |
28 | 33 | import org.springframework.stereotype.Component; |
... | ... | @@ -32,6 +37,9 @@ import org.thingsboard.server.dao.AbstractSearchTextDao; |
32 | 37 | import org.thingsboard.server.dao.model.DeviceEntity; |
33 | 38 | import org.slf4j.Logger; |
34 | 39 | import org.slf4j.LoggerFactory; |
40 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | |
41 | + | |
42 | +import javax.annotation.Nullable; | |
35 | 43 | |
36 | 44 | @Component |
37 | 45 | @Slf4j |
... | ... | @@ -64,6 +72,16 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement |
64 | 72 | } |
65 | 73 | |
66 | 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 | 85 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) { |
68 | 86 | log.debug("Try to find devices by tenantId [{}] and device Ids [{}]", tenantId, deviceIds); |
69 | 87 | Select select = select().from(getColumnFamilyName()); |
... | ... | @@ -75,7 +93,7 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement |
75 | 93 | |
76 | 94 | @Override |
77 | 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 | 97 | List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, |
80 | 98 | Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId), |
81 | 99 | eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), |
... | ... | @@ -86,6 +104,19 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement |
86 | 104 | } |
87 | 105 | |
88 | 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 | 120 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) { |
90 | 121 | log.debug("Try to find devices by tenantId [{}], customerId [{}] and device Ids [{}]", tenantId, customerId, deviceIds); |
91 | 122 | Select select = select().from(getColumnFamilyName()); |
... | ... | @@ -105,4 +136,24 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement |
105 | 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 | 17 | |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import org.thingsboard.server.common.data.Device; |
20 | +import org.thingsboard.server.common.data.TenantDeviceType; | |
20 | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
22 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -44,16 +45,22 @@ public interface DeviceService { |
44 | 45 | |
45 | 46 | TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink); |
46 | 47 | |
48 | + TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | |
49 | + | |
47 | 50 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); |
48 | 51 | |
49 | 52 | void deleteDevicesByTenantId(TenantId tenantId); |
50 | 53 | |
51 | 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 | 58 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); |
54 | 59 | |
55 | 60 | void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); |
56 | 61 | |
57 | 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 | 26 | import org.springframework.util.StringUtils; |
27 | 27 | import org.thingsboard.server.common.data.Device; |
28 | 28 | import org.thingsboard.server.common.data.EntityType; |
29 | +import org.thingsboard.server.common.data.TenantDeviceType; | |
29 | 30 | import org.thingsboard.server.common.data.id.CustomerId; |
30 | 31 | import org.thingsboard.server.common.data.id.DeviceId; |
31 | 32 | import org.thingsboard.server.common.data.id.EntityId; |
... | ... | @@ -40,6 +41,7 @@ import org.thingsboard.server.dao.entity.BaseEntityService; |
40 | 41 | import org.thingsboard.server.dao.exception.DataValidationException; |
41 | 42 | import org.thingsboard.server.dao.model.CustomerEntity; |
42 | 43 | import org.thingsboard.server.dao.model.DeviceEntity; |
44 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | |
43 | 45 | import org.thingsboard.server.dao.model.TenantEntity; |
44 | 46 | import org.thingsboard.server.dao.relation.EntitySearchDirection; |
45 | 47 | import org.thingsboard.server.dao.service.DataValidator; |
... | ... | @@ -47,9 +49,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; |
47 | 49 | import org.thingsboard.server.dao.tenant.TenantDao; |
48 | 50 | |
49 | 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 | 53 | import java.util.stream.Collectors; |
54 | 54 | |
55 | 55 | import static org.thingsboard.server.dao.DaoUtil.*; |
... | ... | @@ -148,7 +148,18 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic |
148 | 148 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
149 | 149 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantId(tenantId.getId(), pageLink); |
150 | 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 | 165 | @Override |
... | ... | @@ -176,7 +187,19 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic |
176 | 187 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
177 | 188 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); |
178 | 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 | 205 | @Override |
... | ... | @@ -224,6 +247,25 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic |
224 | 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 | 269 | private DataValidator<Device> deviceValidator = |
228 | 270 | new DataValidator<Device>() { |
229 | 271 | |
... | ... | @@ -249,6 +291,9 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic |
249 | 291 | |
250 | 292 | @Override |
251 | 293 | protected void validateDataImpl(Device device) { |
294 | + if (StringUtils.isEmpty(device.getType())) { | |
295 | + throw new DataValidationException("Device type should be specified!"); | |
296 | + } | |
252 | 297 | if (StringUtils.isEmpty(device.getName())) { |
253 | 298 | throw new DataValidationException("Device name should be specified!"); |
254 | 299 | } | ... | ... |
... | ... | @@ -49,12 +49,13 @@ public final class AssetEntity implements SearchTextEntity<Asset> { |
49 | 49 | @Column(name = ASSET_CUSTOMER_ID_PROPERTY) |
50 | 50 | private UUID customerId; |
51 | 51 | |
52 | - @Column(name = ASSET_NAME_PROPERTY) | |
53 | - private String name; | |
54 | - | |
52 | + @PartitionKey(value = 3) | |
55 | 53 | @Column(name = ASSET_TYPE_PROPERTY) |
56 | 54 | private String type; |
57 | 55 | |
56 | + @Column(name = ASSET_NAME_PROPERTY) | |
57 | + private String name; | |
58 | + | |
58 | 59 | @Column(name = SEARCH_TEXT_PROPERTY) |
59 | 60 | private String searchText; |
60 | 61 | ... | ... |
... | ... | @@ -49,12 +49,13 @@ public final class DeviceEntity implements SearchTextEntity<Device> { |
49 | 49 | @Column(name = DEVICE_CUSTOMER_ID_PROPERTY) |
50 | 50 | private UUID customerId; |
51 | 51 | |
52 | - @Column(name = DEVICE_NAME_PROPERTY) | |
53 | - private String name; | |
54 | - | |
52 | + @PartitionKey(value = 3) | |
55 | 53 | @Column(name = DEVICE_TYPE_PROPERTY) |
56 | 54 | private String type; |
57 | 55 | |
56 | + @Column(name = DEVICE_NAME_PROPERTY) | |
57 | + private String name; | |
58 | + | |
58 | 59 | @Column(name = SEARCH_TEXT_PROPERTY) |
59 | 60 | private String searchText; |
60 | 61 | ... | ... |
... | ... | @@ -124,8 +124,11 @@ public class ModelConstants { |
124 | 124 | public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; |
125 | 125 | |
126 | 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 | 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 | 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 | 134 | * Cassandra asset constants. |
... | ... | @@ -138,8 +141,11 @@ public class ModelConstants { |
138 | 141 | public static final String ASSET_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; |
139 | 142 | |
140 | 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 | 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 | 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 | 151 | * Cassandra alarm 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 | +} | ... | ... |
... | ... | @@ -149,66 +149,73 @@ VALUES ( |
149 | 149 | |
150 | 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 | 153 | VALUES ( |
154 | 154 | minTimeuuid ( '2016-11-01 01:02:05+0000' ), |
155 | 155 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
156 | 156 | minTimeuuid ( '2016-11-01 01:02:03+0000' ), |
157 | + 'default', | |
157 | 158 | 'Test Device A1', |
158 | 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 | 163 | VALUES ( |
163 | 164 | minTimeuuid ( '2016-11-01 01:02:05+0001' ), |
164 | 165 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
165 | 166 | minTimeuuid ( '2016-11-01 01:02:03+0000' ), |
167 | + 'default', | |
166 | 168 | 'Test Device A2', |
167 | 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 | 173 | VALUES ( |
172 | 174 | minTimeuuid ( '2016-11-01 01:02:05+0002' ), |
173 | 175 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
174 | 176 | minTimeuuid ( '2016-11-01 01:02:03+0000' ), |
177 | + 'default', | |
175 | 178 | 'Test Device A3', |
176 | 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 | 183 | VALUES ( |
181 | 184 | minTimeuuid ( '2016-11-01 01:02:05+0003' ), |
182 | 185 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
183 | 186 | minTimeuuid ( '2016-11-01 01:02:03+0001' ), |
187 | + 'default', | |
184 | 188 | 'Test Device B1', |
185 | 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 | 193 | VALUES ( |
190 | 194 | minTimeuuid ( '2016-11-01 01:02:05+0004' ), |
191 | 195 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
192 | 196 | minTimeuuid ( '2016-11-01 01:02:03+0002' ), |
197 | + 'default', | |
193 | 198 | 'Test Device C1', |
194 | 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 | 203 | VALUES ( |
199 | 204 | c8f1a6f0-b993-11e6-8a04-9ff4e1b7933c, |
200 | 205 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
201 | 206 | minTimeuuid ( 0 ), |
207 | + 'default', | |
202 | 208 | 'DHT11 Demo Device', |
203 | 209 | 'dht11 demo device', |
204 | 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 | 214 | VALUES ( |
209 | 215 | c8f1a6f0-b993-11e6-8a04-9ff4e1b7933d, |
210 | 216 | minTimeuuid ( '2016-11-01 01:02:01+0000' ), |
211 | 217 | minTimeuuid ( 0 ), |
218 | + 'default', | |
212 | 219 | 'Raspberry Pi Demo Device', |
213 | 220 | 'raspberry pi demo device', |
214 | 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 | 152 | WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); |
153 | 153 | |
154 | 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 | 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 | 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 | 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 | 207 | CREATE TABLE IF NOT EXISTS thingsboard.device_credentials ( |
187 | 208 | id timeuuid PRIMARY KEY, |
... | ... | @@ -203,38 +224,58 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_credentials_by_credent |
203 | 224 | WHERE credentials_id IS NOT NULL AND id IS NOT NULL |
204 | 225 | PRIMARY KEY ( credentials_id, id ); |
205 | 226 | |
206 | - | |
207 | 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 | 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 | 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 | 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 | 280 | CREATE TABLE IF NOT EXISTS thingsboard.alarm ( |
240 | 281 | id timeuuid, | ... | ... |
... | ... | @@ -32,7 +32,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
32 | 32 | import org.springframework.test.context.support.AnnotationConfigContextLoader; |
33 | 33 | import org.thingsboard.server.common.data.BaseData; |
34 | 34 | import org.thingsboard.server.common.data.Event; |
35 | -import org.thingsboard.server.common.data.alarm.AlarmStatus; | |
36 | 35 | import org.thingsboard.server.common.data.id.EntityId; |
37 | 36 | import org.thingsboard.server.common.data.id.TenantId; |
38 | 37 | import org.thingsboard.server.common.data.id.UUIDBased; |
... | ... | @@ -42,6 +41,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; |
42 | 41 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
43 | 42 | import org.thingsboard.server.common.data.rule.RuleMetaData; |
44 | 43 | import org.thingsboard.server.dao.alarm.AlarmService; |
44 | +import org.thingsboard.server.dao.asset.AssetService; | |
45 | 45 | import org.thingsboard.server.dao.component.ComponentDescriptorService; |
46 | 46 | import org.thingsboard.server.dao.customer.CustomerService; |
47 | 47 | import org.thingsboard.server.dao.dashboard.DashboardService; |
... | ... | @@ -90,6 +90,9 @@ public abstract class AbstractServiceTest { |
90 | 90 | protected DeviceService deviceService; |
91 | 91 | |
92 | 92 | @Autowired |
93 | + protected AssetService assetService; | |
94 | + | |
95 | + @Autowired | |
93 | 96 | protected DeviceCredentialsService deviceCredentialsService; |
94 | 97 | |
95 | 98 | @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 | 58 | public void testSaveDeviceCredentialsWithEmptyDevice() { |
59 | 59 | Device device = new Device(); |
60 | 60 | device.setName("My device"); |
61 | + device.setType("default"); | |
61 | 62 | device.setTenantId(tenantId); |
62 | 63 | device = deviceService.saveDevice(device); |
63 | 64 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -73,6 +74,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
73 | 74 | public void testSaveDeviceCredentialsWithEmptyCredentialsType() { |
74 | 75 | Device device = new Device(); |
75 | 76 | device.setName("My device"); |
77 | + device.setType("default"); | |
76 | 78 | device.setTenantId(tenantId); |
77 | 79 | device = deviceService.saveDevice(device); |
78 | 80 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -88,6 +90,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
88 | 90 | public void testSaveDeviceCredentialsWithEmptyCredentialsId() { |
89 | 91 | Device device = new Device(); |
90 | 92 | device.setName("My device"); |
93 | + device.setType("default"); | |
91 | 94 | device.setTenantId(tenantId); |
92 | 95 | device = deviceService.saveDevice(device); |
93 | 96 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -103,6 +106,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
103 | 106 | public void testSaveNonExistentDeviceCredentials() { |
104 | 107 | Device device = new Device(); |
105 | 108 | device.setName("My device"); |
109 | + device.setType("default"); | |
106 | 110 | device.setTenantId(tenantId); |
107 | 111 | device = deviceService.saveDevice(device); |
108 | 112 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -122,6 +126,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
122 | 126 | public void testSaveDeviceCredentialsWithNonExistentDevice() { |
123 | 127 | Device device = new Device(); |
124 | 128 | device.setName("My device"); |
129 | + device.setType("default"); | |
125 | 130 | device.setTenantId(tenantId); |
126 | 131 | device = deviceService.saveDevice(device); |
127 | 132 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -137,6 +142,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
137 | 142 | public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() { |
138 | 143 | Device device = new Device(); |
139 | 144 | device.setName("My device"); |
145 | + device.setType("default"); | |
140 | 146 | device.setTenantId(tenantId); |
141 | 147 | device = deviceService.saveDevice(device); |
142 | 148 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getId()); |
... | ... | @@ -153,6 +159,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
153 | 159 | Device device = new Device(); |
154 | 160 | device.setTenantId(tenantId); |
155 | 161 | device.setName("My device"); |
162 | + device.setType("default"); | |
156 | 163 | Device savedDevice = deviceService.saveDevice(device); |
157 | 164 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); |
158 | 165 | Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); |
... | ... | @@ -166,6 +173,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
166 | 173 | Device device = new Device(); |
167 | 174 | device.setTenantId(tenantId); |
168 | 175 | device.setName("My device"); |
176 | + device.setType("default"); | |
169 | 177 | Device savedDevice = deviceService.saveDevice(device); |
170 | 178 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); |
171 | 179 | Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); |
... | ... | @@ -181,6 +189,7 @@ public class DeviceCredentialsServiceImplTest extends AbstractServiceTest { |
181 | 189 | Device device = new Device(); |
182 | 190 | device.setTenantId(tenantId); |
183 | 191 | device.setName("My device"); |
192 | + device.setType("default"); | |
184 | 193 | Device savedDevice = deviceService.saveDevice(device); |
185 | 194 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getId()); |
186 | 195 | Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.junit.Test; |
24 | 24 | import org.thingsboard.server.common.data.Customer; |
25 | 25 | import org.thingsboard.server.common.data.Device; |
26 | 26 | import org.thingsboard.server.common.data.Tenant; |
27 | +import org.thingsboard.server.common.data.TenantDeviceType; | |
27 | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
28 | 29 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; |
29 | 30 | import org.thingsboard.server.common.data.id.DeviceId; |
... | ... | @@ -37,6 +38,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; |
37 | 38 | import java.util.ArrayList; |
38 | 39 | import java.util.Collections; |
39 | 40 | import java.util.List; |
41 | +import java.util.concurrent.Executors; | |
40 | 42 | |
41 | 43 | import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; |
42 | 44 | |
... | ... | @@ -65,6 +67,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
65 | 67 | Device device = new Device(); |
66 | 68 | device.setTenantId(tenantId); |
67 | 69 | device.setName("My device"); |
70 | + device.setType("default"); | |
68 | 71 | Device savedDevice = deviceService.saveDevice(device); |
69 | 72 | |
70 | 73 | Assert.assertNotNull(savedDevice); |
... | ... | @@ -95,6 +98,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
95 | 98 | @Test(expected = DataValidationException.class) |
96 | 99 | public void testSaveDeviceWithEmptyName() { |
97 | 100 | Device device = new Device(); |
101 | + device.setType("default"); | |
98 | 102 | device.setTenantId(tenantId); |
99 | 103 | deviceService.saveDevice(device); |
100 | 104 | } |
... | ... | @@ -103,6 +107,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
103 | 107 | public void testSaveDeviceWithEmptyTenant() { |
104 | 108 | Device device = new Device(); |
105 | 109 | device.setName("My device"); |
110 | + device.setType("default"); | |
106 | 111 | deviceService.saveDevice(device); |
107 | 112 | } |
108 | 113 | |
... | ... | @@ -110,6 +115,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
110 | 115 | public void testSaveDeviceWithInvalidTenant() { |
111 | 116 | Device device = new Device(); |
112 | 117 | device.setName("My device"); |
118 | + device.setType("default"); | |
113 | 119 | device.setTenantId(new TenantId(UUIDs.timeBased())); |
114 | 120 | deviceService.saveDevice(device); |
115 | 121 | } |
... | ... | @@ -118,6 +124,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
118 | 124 | public void testAssignDeviceToNonExistentCustomer() { |
119 | 125 | Device device = new Device(); |
120 | 126 | device.setName("My device"); |
127 | + device.setType("default"); | |
121 | 128 | device.setTenantId(tenantId); |
122 | 129 | device = deviceService.saveDevice(device); |
123 | 130 | try { |
... | ... | @@ -131,6 +138,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
131 | 138 | public void testAssignDeviceToCustomerFromDifferentTenant() { |
132 | 139 | Device device = new Device(); |
133 | 140 | device.setName("My device"); |
141 | + device.setType("default"); | |
134 | 142 | device.setTenantId(tenantId); |
135 | 143 | device = deviceService.saveDevice(device); |
136 | 144 | Tenant tenant = new Tenant(); |
... | ... | @@ -153,18 +161,56 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
153 | 161 | Device device = new Device(); |
154 | 162 | device.setTenantId(tenantId); |
155 | 163 | device.setName("My device"); |
164 | + device.setType("default"); | |
156 | 165 | Device savedDevice = deviceService.saveDevice(device); |
157 | 166 | Device foundDevice = deviceService.findDeviceById(savedDevice.getId()); |
158 | 167 | Assert.assertNotNull(foundDevice); |
159 | 168 | Assert.assertEquals(savedDevice, foundDevice); |
160 | 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 | 208 | @Test |
164 | 209 | public void testDeleteDevice() { |
165 | 210 | Device device = new Device(); |
166 | 211 | device.setTenantId(tenantId); |
167 | 212 | device.setName("My device"); |
213 | + device.setType("default"); | |
168 | 214 | Device savedDevice = deviceService.saveDevice(device); |
169 | 215 | Device foundDevice = deviceService.findDeviceById(savedDevice.getId()); |
170 | 216 | Assert.assertNotNull(foundDevice); |
... | ... | @@ -188,6 +234,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
188 | 234 | Device device = new Device(); |
189 | 235 | device.setTenantId(tenantId); |
190 | 236 | device.setName("Device"+i); |
237 | + device.setType("default"); | |
191 | 238 | devices.add(deviceService.saveDevice(device)); |
192 | 239 | } |
193 | 240 | |
... | ... | @@ -216,7 +263,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
216 | 263 | |
217 | 264 | tenantService.deleteTenant(tenantId); |
218 | 265 | } |
219 | - | |
266 | + | |
220 | 267 | @Test |
221 | 268 | public void testFindDevicesByTenantIdAndName() { |
222 | 269 | String title1 = "Device title 1"; |
... | ... | @@ -228,6 +275,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
228 | 275 | String name = title1+suffix; |
229 | 276 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
230 | 277 | device.setName(name); |
278 | + device.setType("default"); | |
231 | 279 | devicesTitle1.add(deviceService.saveDevice(device)); |
232 | 280 | } |
233 | 281 | String title2 = "Device title 2"; |
... | ... | @@ -239,6 +287,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
239 | 287 | String name = title2+suffix; |
240 | 288 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
241 | 289 | device.setName(name); |
290 | + device.setType("default"); | |
242 | 291 | devicesTitle2.add(deviceService.saveDevice(device)); |
243 | 292 | } |
244 | 293 | |
... | ... | @@ -291,6 +340,85 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
291 | 340 | Assert.assertFalse(pageData.hasNext()); |
292 | 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 | 423 | @Test |
296 | 424 | public void testFindDevicesByTenantIdAndCustomerId() { |
... | ... | @@ -311,6 +439,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
311 | 439 | Device device = new Device(); |
312 | 440 | device.setTenantId(tenantId); |
313 | 441 | device.setName("Device"+i); |
442 | + device.setType("default"); | |
314 | 443 | device = deviceService.saveDevice(device); |
315 | 444 | devices.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); |
316 | 445 | } |
... | ... | @@ -359,6 +488,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
359 | 488 | String name = title1+suffix; |
360 | 489 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
361 | 490 | device.setName(name); |
491 | + device.setType("default"); | |
362 | 492 | device = deviceService.saveDevice(device); |
363 | 493 | devicesTitle1.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); |
364 | 494 | } |
... | ... | @@ -371,6 +501,7 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
371 | 501 | String name = title2+suffix; |
372 | 502 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
373 | 503 | device.setName(name); |
504 | + device.setType("default"); | |
374 | 505 | device = deviceService.saveDevice(device); |
375 | 506 | devicesTitle2.add(deviceService.assignDeviceToCustomer(device.getId(), customerId)); |
376 | 507 | } |
... | ... | @@ -425,4 +556,94 @@ public class DeviceServiceImplTest extends AbstractServiceTest { |
425 | 556 | Assert.assertEquals(0, pageData.getData().size()); |
426 | 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 | } | ... | ... |
... | ... | @@ -31,7 +31,8 @@ function AssetService($http, $q, customerService, userService) { |
31 | 31 | getTenantAssets: getTenantAssets, |
32 | 32 | getCustomerAssets: getCustomerAssets, |
33 | 33 | findByQuery: findByQuery, |
34 | - fetchAssetsByNameFilter: fetchAssetsByNameFilter | |
34 | + fetchAssetsByNameFilter: fetchAssetsByNameFilter, | |
35 | + getAssetTypes: getAssetTypes | |
35 | 36 | } |
36 | 37 | |
37 | 38 | return service; |
... | ... | @@ -152,7 +153,7 @@ function AssetService($http, $q, customerService, userService) { |
152 | 153 | return deferred.promise; |
153 | 154 | } |
154 | 155 | |
155 | - function getTenantAssets(pageLink, applyCustomersInfo, config) { | |
156 | + function getTenantAssets(pageLink, applyCustomersInfo, config, type) { | |
156 | 157 | var deferred = $q.defer(); |
157 | 158 | var url = '/api/tenant/assets?limit=' + pageLink.limit; |
158 | 159 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -164,6 +165,9 @@ function AssetService($http, $q, customerService, userService) { |
164 | 165 | if (angular.isDefined(pageLink.textOffset)) { |
165 | 166 | url += '&textOffset=' + pageLink.textOffset; |
166 | 167 | } |
168 | + if (angular.isDefined(type) && type.length) { | |
169 | + url += '&type=' + type; | |
170 | + } | |
167 | 171 | $http.get(url, config).then(function success(response) { |
168 | 172 | if (applyCustomersInfo) { |
169 | 173 | customerService.applyAssignedCustomersInfo(response.data.data).then( |
... | ... | @@ -184,7 +188,7 @@ function AssetService($http, $q, customerService, userService) { |
184 | 188 | return deferred.promise; |
185 | 189 | } |
186 | 190 | |
187 | - function getCustomerAssets(customerId, pageLink, applyCustomersInfo, config) { | |
191 | + function getCustomerAssets(customerId, pageLink, applyCustomersInfo, config, type) { | |
188 | 192 | var deferred = $q.defer(); |
189 | 193 | var url = '/api/customer/' + customerId + '/assets?limit=' + pageLink.limit; |
190 | 194 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -196,6 +200,9 @@ function AssetService($http, $q, customerService, userService) { |
196 | 200 | if (angular.isDefined(pageLink.textOffset)) { |
197 | 201 | url += '&textOffset=' + pageLink.textOffset; |
198 | 202 | } |
203 | + if (angular.isDefined(type) && type.length) { | |
204 | + url += '&type=' + type; | |
205 | + } | |
199 | 206 | $http.get(url, config).then(function success(response) { |
200 | 207 | if (applyCustomersInfo) { |
201 | 208 | customerService.applyAssignedCustomerInfo(response.data.data, customerId).then( |
... | ... | @@ -258,4 +265,15 @@ function AssetService($http, $q, customerService, userService) { |
258 | 265 | return deferred.promise; |
259 | 266 | } |
260 | 267 | |
268 | + function getAssetTypes() { | |
269 | + var deferred = $q.defer(); | |
270 | + var url = '/api/asset/types'; | |
271 | + $http.get(url).then(function success(response) { | |
272 | + deferred.resolve(response.data); | |
273 | + }, function fail() { | |
274 | + deferred.reject(); | |
275 | + }); | |
276 | + return deferred.promise; | |
277 | + } | |
278 | + | |
261 | 279 | } | ... | ... |
... | ... | @@ -41,12 +41,13 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
41 | 41 | deleteDeviceAttributes: deleteDeviceAttributes, |
42 | 42 | sendOneWayRpcCommand: sendOneWayRpcCommand, |
43 | 43 | sendTwoWayRpcCommand: sendTwoWayRpcCommand, |
44 | - findByQuery: findByQuery | |
44 | + findByQuery: findByQuery, | |
45 | + getDeviceTypes: getDeviceTypes | |
45 | 46 | } |
46 | 47 | |
47 | 48 | return service; |
48 | 49 | |
49 | - function getTenantDevices(pageLink, applyCustomersInfo, config) { | |
50 | + function getTenantDevices(pageLink, applyCustomersInfo, config, type) { | |
50 | 51 | var deferred = $q.defer(); |
51 | 52 | var url = '/api/tenant/devices?limit=' + pageLink.limit; |
52 | 53 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -58,6 +59,9 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
58 | 59 | if (angular.isDefined(pageLink.textOffset)) { |
59 | 60 | url += '&textOffset=' + pageLink.textOffset; |
60 | 61 | } |
62 | + if (angular.isDefined(type) && type.length) { | |
63 | + url += '&type=' + type; | |
64 | + } | |
61 | 65 | $http.get(url, config).then(function success(response) { |
62 | 66 | if (applyCustomersInfo) { |
63 | 67 | customerService.applyAssignedCustomersInfo(response.data.data).then( |
... | ... | @@ -78,7 +82,7 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
78 | 82 | return deferred.promise; |
79 | 83 | } |
80 | 84 | |
81 | - function getCustomerDevices(customerId, pageLink, applyCustomersInfo, config) { | |
85 | + function getCustomerDevices(customerId, pageLink, applyCustomersInfo, config, type) { | |
82 | 86 | var deferred = $q.defer(); |
83 | 87 | var url = '/api/customer/' + customerId + '/devices?limit=' + pageLink.limit; |
84 | 88 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -90,6 +94,9 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
90 | 94 | if (angular.isDefined(pageLink.textOffset)) { |
91 | 95 | url += '&textOffset=' + pageLink.textOffset; |
92 | 96 | } |
97 | + if (angular.isDefined(type) && type.length) { | |
98 | + url += '&type=' + type; | |
99 | + } | |
93 | 100 | $http.get(url, config).then(function success(response) { |
94 | 101 | if (applyCustomersInfo) { |
95 | 102 | customerService.applyAssignedCustomerInfo(response.data.data, customerId).then( |
... | ... | @@ -286,4 +293,15 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
286 | 293 | return deferred.promise; |
287 | 294 | } |
288 | 295 | |
296 | + function getDeviceTypes() { | |
297 | + var deferred = $q.defer(); | |
298 | + var url = '/api/device/types'; | |
299 | + $http.get(url).then(function success(response) { | |
300 | + deferred.resolve(response.data); | |
301 | + }, function fail() { | |
302 | + deferred.reject(); | |
303 | + }); | |
304 | + return deferred.promise; | |
305 | + } | |
306 | + | |
289 | 307 | } | ... | ... |
... | ... | @@ -36,7 +36,8 @@ function EntityService($http, $q, $filter, $translate, userService, deviceServic |
36 | 36 | saveRelatedEntity: saveRelatedEntity, |
37 | 37 | getRelatedEntity: getRelatedEntity, |
38 | 38 | deleteRelatedEntity: deleteRelatedEntity, |
39 | - moveEntity: moveEntity | |
39 | + moveEntity: moveEntity, | |
40 | + copyEntity: copyEntity | |
40 | 41 | }; |
41 | 42 | |
42 | 43 | return service; |
... | ... | @@ -626,6 +627,32 @@ function EntityService($http, $q, $filter, $translate, userService, deviceServic |
626 | 627 | return deferred.promise; |
627 | 628 | } |
628 | 629 | |
630 | + function copyEntity(entity, targetParentId, keys) { | |
631 | + var deferred = $q.defer(); | |
632 | + if (!entity.id && !entity.id.id) { | |
633 | + deferred.reject(); | |
634 | + } else { | |
635 | + getRelatedEntity(entity.id, keys).then( | |
636 | + function success(relatedEntity) { | |
637 | + delete relatedEntity.id.id; | |
638 | + relatedEntity.name = entity.name; | |
639 | + saveRelatedEntity(relatedEntity, targetParentId, keys).then( | |
640 | + function success(savedEntity) { | |
641 | + deferred.resolve(savedEntity); | |
642 | + }, | |
643 | + function fail() { | |
644 | + deferred.reject(); | |
645 | + } | |
646 | + ); | |
647 | + }, | |
648 | + function fail() { | |
649 | + deferred.reject(); | |
650 | + } | |
651 | + ); | |
652 | + } | |
653 | + return deferred.promise; | |
654 | + } | |
655 | + | |
629 | 656 | function saveEntityPromise(entity) { |
630 | 657 | var entityType = entity.id.entityType; |
631 | 658 | if (!entity.id.id) { | ... | ... |
... | ... | @@ -160,10 +160,6 @@ export default function AppConfig($provide, |
160 | 160 | indigoTheme(); |
161 | 161 | } |
162 | 162 | |
163 | - $mdThemingProvider.theme('tb-search-input', 'default') | |
164 | - .primaryPalette('tb-primary') | |
165 | - .backgroundPalette('tb-primary'); | |
166 | - | |
167 | 163 | $mdThemingProvider.setDefaultTheme('default'); |
168 | 164 | //$mdThemingProvider.alwaysWatchTheme(true); |
169 | 165 | } | ... | ... |
... | ... | @@ -15,5 +15,8 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | -<div class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'asset.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div> | |
19 | -<div class="tb-small" ng-show="vm.isPublic()">{{'asset.public' | translate}}</div> | |
18 | +<div flex layout="column" style="margin-top: -10px;"> | |
19 | + <div flex style="text-transform: uppercase; padding-bottom: 10px;">{{vm.item.type}}</div> | |
20 | + <div class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'asset.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div> | |
21 | + <div class="tb-small" ng-show="vm.isPublic()">{{'asset.public' | translate}}</div> | |
22 | +</div> | ... | ... |
... | ... | @@ -56,13 +56,13 @@ |
56 | 56 | <div translate ng-message="required">asset.name-required</div> |
57 | 57 | </div> |
58 | 58 | </md-input-container> |
59 | - <md-input-container class="md-block"> | |
60 | - <label translate>asset.type</label> | |
61 | - <input required name="type" ng-model="asset.type"> | |
62 | - <div ng-messages="theForm.name.$error"> | |
63 | - <div translate ng-message="required">asset.type-required</div> | |
64 | - </div> | |
65 | - </md-input-container> | |
59 | + <tb-entity-subtype-autocomplete | |
60 | + ng-disabled="loading || !isEdit" | |
61 | + tb-required="true" | |
62 | + the-form="theForm" | |
63 | + ng-model="asset.type" | |
64 | + entity-type="types.entityType.asset"> | |
65 | + </tb-entity-subtype-autocomplete> | |
66 | 66 | <md-input-container class="md-block"> |
67 | 67 | <label translate>asset.description</label> |
68 | 68 | <textarea ng-model="asset.additionalInfo.description" rows="2"></textarea> | ... | ... |
... | ... | @@ -47,7 +47,8 @@ export function AssetCardController(types) { |
47 | 47 | |
48 | 48 | |
49 | 49 | /*@ngInject*/ |
50 | -export function AssetController(userService, assetService, customerService, $state, $stateParams, $document, $mdDialog, $q, $translate, types) { | |
50 | +export function AssetController($rootScope, userService, assetService, customerService, $state, $stateParams, | |
51 | + $document, $mdDialog, $q, $translate, types) { | |
51 | 52 | |
52 | 53 | var customerId = $stateParams.customerId; |
53 | 54 | |
... | ... | @@ -129,8 +130,8 @@ export function AssetController(userService, assetService, customerService, $sta |
129 | 130 | } |
130 | 131 | |
131 | 132 | if (vm.assetsScope === 'tenant') { |
132 | - fetchAssetsFunction = function (pageLink) { | |
133 | - return assetService.getTenantAssets(pageLink, true); | |
133 | + fetchAssetsFunction = function (pageLink, assetType) { | |
134 | + return assetService.getTenantAssets(pageLink, true, null, assetType); | |
134 | 135 | }; |
135 | 136 | deleteAssetFunction = function (assetId) { |
136 | 137 | return assetService.deleteAsset(assetId); |
... | ... | @@ -229,8 +230,8 @@ export function AssetController(userService, assetService, customerService, $sta |
229 | 230 | |
230 | 231 | |
231 | 232 | } else if (vm.assetsScope === 'customer' || vm.assetsScope === 'customer_user') { |
232 | - fetchAssetsFunction = function (pageLink) { | |
233 | - return assetService.getCustomerAssets(customerId, pageLink, true); | |
233 | + fetchAssetsFunction = function (pageLink, assetType) { | |
234 | + return assetService.getCustomerAssets(customerId, pageLink, true, null, assetType); | |
234 | 235 | }; |
235 | 236 | deleteAssetFunction = function (assetId) { |
236 | 237 | return assetService.unassignAssetFromCustomer(assetId); |
... | ... | @@ -333,6 +334,7 @@ export function AssetController(userService, assetService, customerService, $sta |
333 | 334 | var deferred = $q.defer(); |
334 | 335 | assetService.saveAsset(asset).then( |
335 | 336 | function success(savedAsset) { |
337 | + $rootScope.$broadcast('assetSaved'); | |
336 | 338 | var assets = [ savedAsset ]; |
337 | 339 | customerService.applyAssignedCustomersInfo(assets).then( |
338 | 340 | function success(items) { | ... | ... |
... | ... | @@ -25,6 +25,7 @@ export default function AssetDirective($compile, $templateCache, toast, $transla |
25 | 25 | var template = $templateCache.get(assetFieldsetTemplate); |
26 | 26 | element.html(template); |
27 | 27 | |
28 | + scope.types = types; | |
28 | 29 | scope.isAssignedToCustomer = false; |
29 | 30 | scope.isPublic = false; |
30 | 31 | scope.assignedCustomer = null; | ... | ... |
... | ... | @@ -20,7 +20,7 @@ import assetsTemplate from './assets.tpl.html'; |
20 | 20 | /* eslint-enable import/no-unresolved, import/default */ |
21 | 21 | |
22 | 22 | /*@ngInject*/ |
23 | -export default function AssetRoutes($stateProvider) { | |
23 | +export default function AssetRoutes($stateProvider, types) { | |
24 | 24 | $stateProvider |
25 | 25 | .state('home.assets', { |
26 | 26 | url: '/assets', |
... | ... | @@ -37,6 +37,8 @@ export default function AssetRoutes($stateProvider) { |
37 | 37 | data: { |
38 | 38 | assetsType: 'tenant', |
39 | 39 | searchEnabled: true, |
40 | + searchByEntitySubtype: true, | |
41 | + searchEntityType: types.entityType.asset, | |
40 | 42 | pageTitle: 'asset.assets' |
41 | 43 | }, |
42 | 44 | ncyBreadcrumb: { |
... | ... | @@ -58,6 +60,8 @@ export default function AssetRoutes($stateProvider) { |
58 | 60 | data: { |
59 | 61 | assetsType: 'customer', |
60 | 62 | searchEnabled: true, |
63 | + searchByEntitySubtype: true, | |
64 | + searchEntityType: types.entityType.asset, | |
61 | 65 | pageTitle: 'customer.assets' |
62 | 66 | }, |
63 | 67 | ncyBreadcrumb: { | ... | ... |
... | ... | @@ -179,6 +179,7 @@ function DashboardUtils(types, utils, timeService) { |
179 | 179 | dashboard.configuration.settings.showEntitiesSelect = true; |
180 | 180 | dashboard.configuration.settings.showDashboardTimewindow = true; |
181 | 181 | dashboard.configuration.settings.showDashboardExport = true; |
182 | + dashboard.configuration.settings.toolbarAlwaysOpen = false; | |
182 | 183 | } else { |
183 | 184 | if (angular.isUndefined(dashboard.configuration.settings.stateControllerId)) { |
184 | 185 | dashboard.configuration.settings.stateControllerId = 'default'; | ... | ... |
ui/src/app/components/datasource-device.directive.js
deleted
100644 → 0
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 | -import './datasource-device.scss'; | |
17 | - | |
18 | -import 'md-color-picker'; | |
19 | -import tinycolor from 'tinycolor2'; | |
20 | -import $ from 'jquery'; | |
21 | -import thingsboardTypes from '../common/types.constant'; | |
22 | -import thingsboardDatakeyConfigDialog from './datakey-config-dialog.controller'; | |
23 | -import thingsboardTruncate from './truncate.filter'; | |
24 | - | |
25 | -/* eslint-disable import/no-unresolved, import/default */ | |
26 | - | |
27 | -import datasourceDeviceTemplate from './datasource-device.tpl.html'; | |
28 | -import datakeyConfigDialogTemplate from './datakey-config-dialog.tpl.html'; | |
29 | - | |
30 | -/* eslint-enable import/no-unresolved, import/default */ | |
31 | - | |
32 | -/* eslint-disable angular/angularelement */ | |
33 | - | |
34 | -export default angular.module('thingsboard.directives.datasourceDevice', [thingsboardTruncate, thingsboardTypes, thingsboardDatakeyConfigDialog]) | |
35 | - .directive('tbDatasourceDevice', DatasourceDevice) | |
36 | - .name; | |
37 | - | |
38 | -/*@ngInject*/ | |
39 | -function DatasourceDevice($compile, $templateCache, $q, $mdDialog, $window, $document, $mdColorPicker, $mdConstant, types) { | |
40 | - | |
41 | - var linker = function (scope, element, attrs, ngModelCtrl) { | |
42 | - var template = $templateCache.get(datasourceDeviceTemplate); | |
43 | - element.html(template); | |
44 | - | |
45 | - scope.ngModelCtrl = ngModelCtrl; | |
46 | - scope.types = types; | |
47 | - | |
48 | - scope.selectedTimeseriesDataKey = null; | |
49 | - scope.timeseriesDataKeySearchText = null; | |
50 | - | |
51 | - scope.selectedAttributeDataKey = null; | |
52 | - scope.attributeDataKeySearchText = null; | |
53 | - | |
54 | - scope.updateValidity = function () { | |
55 | - if (ngModelCtrl.$viewValue) { | |
56 | - var value = ngModelCtrl.$viewValue; | |
57 | - var dataValid = angular.isDefined(value) && value != null; | |
58 | - ngModelCtrl.$setValidity('deviceData', dataValid); | |
59 | - if (dataValid) { | |
60 | - ngModelCtrl.$setValidity('deviceAlias', | |
61 | - angular.isDefined(value.deviceAliasId) && | |
62 | - value.deviceAliasId != null); | |
63 | - ngModelCtrl.$setValidity('deviceKeys', | |
64 | - angular.isDefined(value.dataKeys) && | |
65 | - value.dataKeys != null && | |
66 | - value.dataKeys.length > 0); | |
67 | - } | |
68 | - } | |
69 | - }; | |
70 | - | |
71 | - scope.$watch('deviceAlias', function () { | |
72 | - if (ngModelCtrl.$viewValue) { | |
73 | - if (scope.deviceAlias) { | |
74 | - ngModelCtrl.$viewValue.deviceAliasId = scope.deviceAlias.id; | |
75 | - } else { | |
76 | - ngModelCtrl.$viewValue.deviceAliasId = null; | |
77 | - } | |
78 | - scope.updateValidity(); | |
79 | - scope.selectedDeviceAliasChange(); | |
80 | - } | |
81 | - }); | |
82 | - | |
83 | - scope.$watch('timeseriesDataKeys', function () { | |
84 | - if (ngModelCtrl.$viewValue) { | |
85 | - var dataKeys = []; | |
86 | - dataKeys = dataKeys.concat(scope.timeseriesDataKeys); | |
87 | - dataKeys = dataKeys.concat(scope.attributeDataKeys); | |
88 | - ngModelCtrl.$viewValue.dataKeys = dataKeys; | |
89 | - scope.updateValidity(); | |
90 | - } | |
91 | - }, true); | |
92 | - | |
93 | - scope.$watch('attributeDataKeys', function () { | |
94 | - if (ngModelCtrl.$viewValue) { | |
95 | - var dataKeys = []; | |
96 | - dataKeys = dataKeys.concat(scope.timeseriesDataKeys); | |
97 | - dataKeys = dataKeys.concat(scope.attributeDataKeys); | |
98 | - ngModelCtrl.$viewValue.dataKeys = dataKeys; | |
99 | - scope.updateValidity(); | |
100 | - } | |
101 | - }, true); | |
102 | - | |
103 | - ngModelCtrl.$render = function () { | |
104 | - if (ngModelCtrl.$viewValue) { | |
105 | - var deviceAliasId = ngModelCtrl.$viewValue.deviceAliasId; | |
106 | - if (scope.deviceAliases[deviceAliasId]) { | |
107 | - scope.deviceAlias = {id: deviceAliasId, alias: scope.deviceAliases[deviceAliasId].alias, | |
108 | - deviceId: scope.deviceAliases[deviceAliasId].deviceId}; | |
109 | - } else { | |
110 | - scope.deviceAlias = null; | |
111 | - } | |
112 | - var timeseriesDataKeys = []; | |
113 | - var attributeDataKeys = []; | |
114 | - for (var d in ngModelCtrl.$viewValue.dataKeys) { | |
115 | - var dataKey = ngModelCtrl.$viewValue.dataKeys[d]; | |
116 | - if (dataKey.type === types.dataKeyType.timeseries) { | |
117 | - timeseriesDataKeys.push(dataKey); | |
118 | - } else if (dataKey.type === types.dataKeyType.attribute) { | |
119 | - attributeDataKeys.push(dataKey); | |
120 | - } | |
121 | - } | |
122 | - scope.timeseriesDataKeys = timeseriesDataKeys; | |
123 | - scope.attributeDataKeys = attributeDataKeys; | |
124 | - } | |
125 | - }; | |
126 | - | |
127 | - scope.textIsNotEmpty = function(text) { | |
128 | - return (text && text != null && text.length > 0) ? true : false; | |
129 | - } | |
130 | - | |
131 | - scope.selectedDeviceAliasChange = function () { | |
132 | - if (!scope.timeseriesDataKeySearchText || scope.timeseriesDataKeySearchText === '') { | |
133 | - scope.timeseriesDataKeySearchText = scope.timeseriesDataKeySearchText === '' ? null : ''; | |
134 | - } | |
135 | - if (!scope.attributeDataKeySearchText || scope.attributeDataKeySearchText === '') { | |
136 | - scope.attributeDataKeySearchText = scope.attributeDataKeySearchText === '' ? null : ''; | |
137 | - } | |
138 | - }; | |
139 | - | |
140 | - scope.transformTimeseriesDataKeyChip = function (chip) { | |
141 | - return scope.generateDataKey({chip: chip, type: types.dataKeyType.timeseries}); | |
142 | - }; | |
143 | - | |
144 | - scope.transformAttributeDataKeyChip = function (chip) { | |
145 | - return scope.generateDataKey({chip: chip, type: types.dataKeyType.attribute}); | |
146 | - }; | |
147 | - | |
148 | - scope.showColorPicker = function (event, dataKey) { | |
149 | - $mdColorPicker.show({ | |
150 | - value: dataKey.color, | |
151 | - defaultValue: '#fff', | |
152 | - random: tinycolor.random(), | |
153 | - clickOutsideToClose: false, | |
154 | - hasBackdrop: false, | |
155 | - skipHide: true, | |
156 | - preserveScope: false, | |
157 | - | |
158 | - mdColorAlphaChannel: true, | |
159 | - mdColorSpectrum: true, | |
160 | - mdColorSliders: true, | |
161 | - mdColorGenericPalette: false, | |
162 | - mdColorMaterialPalette: true, | |
163 | - mdColorHistory: false, | |
164 | - mdColorDefaultTab: 2, | |
165 | - | |
166 | - $event: event | |
167 | - | |
168 | - }).then(function (color) { | |
169 | - dataKey.color = color; | |
170 | - ngModelCtrl.$setDirty(); | |
171 | - }); | |
172 | - } | |
173 | - | |
174 | - scope.editDataKey = function (event, dataKey, index) { | |
175 | - | |
176 | - $mdDialog.show({ | |
177 | - controller: 'DatakeyConfigDialogController', | |
178 | - controllerAs: 'vm', | |
179 | - templateUrl: datakeyConfigDialogTemplate, | |
180 | - locals: { | |
181 | - dataKey: angular.copy(dataKey), | |
182 | - dataKeySettingsSchema: scope.datakeySettingsSchema, | |
183 | - deviceAlias: scope.deviceAlias, | |
184 | - deviceAliases: scope.deviceAliases | |
185 | - }, | |
186 | - parent: angular.element($document[0].body), | |
187 | - fullscreen: true, | |
188 | - targetEvent: event, | |
189 | - skipHide: true, | |
190 | - onComplete: function () { | |
191 | - var w = angular.element($window); | |
192 | - w.triggerHandler('resize'); | |
193 | - } | |
194 | - }).then(function (dataKey) { | |
195 | - if (dataKey.type === types.dataKeyType.timeseries) { | |
196 | - scope.timeseriesDataKeys[index] = dataKey; | |
197 | - } else if (dataKey.type === types.dataKeyType.attribute) { | |
198 | - scope.attributeDataKeys[index] = dataKey; | |
199 | - } | |
200 | - ngModelCtrl.$setDirty(); | |
201 | - }, function () { | |
202 | - }); | |
203 | - }; | |
204 | - | |
205 | - scope.dataKeysSearch = function (searchText, type) { | |
206 | - if (scope.deviceAlias) { | |
207 | - var deferred = $q.defer(); | |
208 | - scope.fetchDeviceKeys({deviceAliasId: scope.deviceAlias.id, query: searchText, type: type}) | |
209 | - .then(function (dataKeys) { | |
210 | - deferred.resolve(dataKeys); | |
211 | - }, function (e) { | |
212 | - deferred.reject(e); | |
213 | - }); | |
214 | - return deferred.promise; | |
215 | - } else { | |
216 | - return $q.when([]); | |
217 | - } | |
218 | - }; | |
219 | - | |
220 | - scope.createKey = function (event, chipsId) { | |
221 | - var chipsChild = $(chipsId, element)[0].firstElementChild; | |
222 | - var el = angular.element(chipsChild); | |
223 | - var chipBuffer = el.scope().$mdChipsCtrl.getChipBuffer(); | |
224 | - event.preventDefault(); | |
225 | - event.stopPropagation(); | |
226 | - el.scope().$mdChipsCtrl.appendChip(chipBuffer.trim()); | |
227 | - el.scope().$mdChipsCtrl.resetChipBuffer(); | |
228 | - } | |
229 | - | |
230 | - $compile(element.contents())(scope); | |
231 | - } | |
232 | - | |
233 | - return { | |
234 | - restrict: "E", | |
235 | - require: "^ngModel", | |
236 | - scope: { | |
237 | - widgetType: '=', | |
238 | - deviceAliases: '=', | |
239 | - datakeySettingsSchema: '=', | |
240 | - generateDataKey: '&', | |
241 | - fetchDeviceKeys: '&', | |
242 | - onCreateDeviceAlias: '&' | |
243 | - }, | |
244 | - link: linker | |
245 | - }; | |
246 | -} | |
247 | - | |
248 | -/* eslint-enable angular/angularelement */ |
ui/src/app/components/datasource-device.scss
deleted
100644 → 0
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 | -@import '../../scss/constants'; | |
17 | - | |
18 | -.tb-device-alias-autocomplete, .tb-timeseries-datakey-autocomplete, .tb-attribute-datakey-autocomplete { | |
19 | - .tb-not-found { | |
20 | - display: block; | |
21 | - line-height: 1.5; | |
22 | - height: 48px; | |
23 | - .tb-no-entries { | |
24 | - line-height: 48px; | |
25 | - } | |
26 | - } | |
27 | - li { | |
28 | - height: auto !important; | |
29 | - white-space: normal !important; | |
30 | - } | |
31 | -} | |
32 | - | |
33 | -tb-datasource-device { | |
34 | - @media (min-width: $layout-breakpoint-gt-sm) { | |
35 | - padding-left: 4px; | |
36 | - padding-right: 4px; | |
37 | - } | |
38 | - tb-device-alias-select { | |
39 | - @media (min-width: $layout-breakpoint-gt-sm) { | |
40 | - width: 200px; | |
41 | - max-width: 200px; | |
42 | - } | |
43 | - } | |
44 | -} | |
\ No newline at end of file |
ui/src/app/components/datasource-device.tpl.html
deleted
100644 → 0
1 | -<!-- | |
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 | -<section flex layout='column' layout-align="center" layout-gt-sm='row' layout-align-gt-sm="start center"> | |
19 | - <tb-device-alias-select | |
20 | - tb-required="true" | |
21 | - device-aliases="deviceAliases" | |
22 | - ng-model="deviceAlias" | |
23 | - on-create-device-alias="onCreateDeviceAlias({event: event, alias: alias})"> | |
24 | - </tb-device-alias-select> | |
25 | - <section flex layout='column'> | |
26 | - <section flex layout='column' layout-align="center" style="padding-left: 4px;"> | |
27 | - <md-chips flex | |
28 | - id="timeseries_datakey_chips" | |
29 | - ng-required="true" | |
30 | - ng-model="timeseriesDataKeys" md-autocomplete-snap | |
31 | - md-transform-chip="transformTimeseriesDataKeyChip($chip)" | |
32 | - md-require-match="false"> | |
33 | - <md-autocomplete | |
34 | - md-no-cache="true" | |
35 | - id="timeseries_datakey" | |
36 | - md-selected-item="selectedTimeseriesDataKey" | |
37 | - md-search-text="timeseriesDataKeySearchText" | |
38 | - md-items="item in dataKeysSearch(timeseriesDataKeySearchText, types.dataKeyType.timeseries)" | |
39 | - md-item-text="item.name" | |
40 | - md-min-length="0" | |
41 | - placeholder="{{'datakey.timeseries' | translate }}" | |
42 | - md-menu-class="tb-timeseries-datakey-autocomplete"> | |
43 | - <span md-highlight-text="timeseriesDataKeySearchText" md-highlight-flags="^i">{{item}}</span> | |
44 | - <md-not-found> | |
45 | - <div class="tb-not-found"> | |
46 | - <div class="tb-no-entries" ng-if="!textIsNotEmpty(timeseriesDataKeySearchText)"> | |
47 | - <span translate>device.no-keys-found</span> | |
48 | - </div> | |
49 | - <div ng-if="textIsNotEmpty(timeseriesDataKeySearchText)"> | |
50 | - <span translate translate-values='{ key: "{{timeseriesDataKeySearchText | truncate:true:6:'...'}}" }'>device.no-key-matching</span> | |
51 | - <span> | |
52 | - <a translate ng-click="createKey($event, '#timeseries_datakey_chips')">device.create-new-key</a> | |
53 | - </span> | |
54 | - </div> | |
55 | - </div> | |
56 | - </md-not-found> | |
57 | - </md-autocomplete> | |
58 | - <md-chip-template> | |
59 | - <div layout="row" layout-align="start center" class="tb-attribute-chip"> | |
60 | - <div class="tb-color-preview" ng-click="showColorPicker($event, $chip, $index)" style="margin-right: 5px;"> | |
61 | - <div class="tb-color-result" ng-style="{background: $chip.color}"></div> | |
62 | - </div> | |
63 | - <div layout="row" flex> | |
64 | - <div class="tb-chip-label"> | |
65 | - {{$chip.label}} | |
66 | - </div> | |
67 | - <div class="tb-chip-separator">: </div> | |
68 | - <div class="tb-chip-label"> | |
69 | - <strong ng-if="!$chip.postFuncBody">{{$chip.name}}</strong> | |
70 | - <strong ng-if="$chip.postFuncBody">f({{$chip.name}})</strong> | |
71 | - </div> | |
72 | - </div> | |
73 | - <md-button ng-click="editDataKey($event, $chip, $index)" class="md-icon-button tb-md-32"> | |
74 | - <md-icon aria-label="edit" class="material-icons tb-md-20">edit</md-icon> | |
75 | - </md-button> | |
76 | - </div> | |
77 | - </md-chip-template> | |
78 | - </md-chips> | |
79 | - <md-chips flex ng-if="widgetType === types.widgetType.latest.value" | |
80 | - id="attribute_datakey_chips" | |
81 | - ng-required="true" | |
82 | - ng-model="attributeDataKeys" md-autocomplete-snap | |
83 | - md-transform-chip="transformAttributeDataKeyChip($chip)" | |
84 | - md-require-match="false"> | |
85 | - <md-autocomplete | |
86 | - md-no-cache="true" | |
87 | - id="attribute_datakey" | |
88 | - md-selected-item="selectedAttributeDataKey" | |
89 | - md-search-text="attributeDataKeySearchText" | |
90 | - md-items="item in dataKeysSearch(attributeDataKeySearchText, types.dataKeyType.attribute)" | |
91 | - md-item-text="item.name" | |
92 | - md-min-length="0" | |
93 | - placeholder="{{'datakey.attributes' | translate }}" | |
94 | - md-menu-class="tb-attribute-datakey-autocomplete"> | |
95 | - <span md-highlight-text="attributeDataKeySearchText" md-highlight-flags="^i">{{item}}</span> | |
96 | - <md-not-found> | |
97 | - <div class="tb-not-found"> | |
98 | - <div class="tb-no-entries" ng-if="!textIsNotEmpty(attributeDataKeySearchText)"> | |
99 | - <span translate>device.no-keys-found</span> | |
100 | - </div> | |
101 | - <div ng-if="textIsNotEmpty(attributeDataKeySearchText)"> | |
102 | - <span translate translate-values='{ key: "{{attributeDataKeySearchText | truncate:true:6:'...'}}" }'>device.no-key-matching</span> | |
103 | - <span> | |
104 | - <a translate ng-click="createKey($event, '#attribute_datakey_chips')">device.create-new-key</a> | |
105 | - </span> | |
106 | - </div> | |
107 | - </div> | |
108 | - </md-not-found> | |
109 | - </md-autocomplete> | |
110 | - <md-chip-template> | |
111 | - <div layout="row" layout-align="start center" class="tb-attribute-chip"> | |
112 | - <div class="tb-color-preview" ng-click="showColorPicker($event, $chip, $index)" style="margin-right: 5px;"> | |
113 | - <div class="tb-color-result" ng-style="{background: $chip.color}"></div> | |
114 | - </div> | |
115 | - <div layout="row" flex> | |
116 | - <div class="tb-chip-label"> | |
117 | - {{$chip.label}} | |
118 | - </div> | |
119 | - <div class="tb-chip-separator">: </div> | |
120 | - <div class="tb-chip-label"> | |
121 | - <strong ng-if="!$chip.postFuncBody">{{$chip.name}}</strong> | |
122 | - <strong ng-if="$chip.postFuncBody">f({{$chip.name}})</strong> | |
123 | - </div> | |
124 | - </div> | |
125 | - <md-button ng-click="editDataKey($event, $chip, $index)" class="md-icon-button tb-md-32"> | |
126 | - <md-icon aria-label="edit" class="material-icons tb-md-20">edit</md-icon> | |
127 | - </md-button> | |
128 | - </div> | |
129 | - </md-chip-template> | |
130 | - </md-chips> | |
131 | - </section> | |
132 | - <div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert"> | |
133 | - <div translate ng-message="deviceKeys" ng-if="widgetType === types.widgetType.timeseries.value" class="tb-error-message">datakey.timeseries-required</div> | |
134 | - <div translate ng-message="deviceKeys" ng-if="widgetType === types.widgetType.latest.value" class="tb-error-message">datakey.timeseries-or-attributes-required</div> | |
135 | - </div> | |
136 | - </section> | |
137 | -</section> |
ui/src/app/components/device-alias-select.directive.js
deleted
100644 → 0
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 | -import $ from 'jquery'; | |
17 | - | |
18 | -import './device-alias-select.scss'; | |
19 | - | |
20 | -/* eslint-disable import/no-unresolved, import/default */ | |
21 | - | |
22 | -import deviceAliasSelectTemplate from './device-alias-select.tpl.html'; | |
23 | - | |
24 | -/* eslint-enable import/no-unresolved, import/default */ | |
25 | - | |
26 | - | |
27 | -/* eslint-disable angular/angularelement */ | |
28 | - | |
29 | -export default angular.module('thingsboard.directives.deviceAliasSelect', []) | |
30 | - .directive('tbDeviceAliasSelect', DeviceAliasSelect) | |
31 | - .name; | |
32 | - | |
33 | -/*@ngInject*/ | |
34 | -function DeviceAliasSelect($compile, $templateCache, $mdConstant) { | |
35 | - | |
36 | - var linker = function (scope, element, attrs, ngModelCtrl) { | |
37 | - var template = $templateCache.get(deviceAliasSelectTemplate); | |
38 | - element.html(template); | |
39 | - | |
40 | - scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false; | |
41 | - | |
42 | - scope.ngModelCtrl = ngModelCtrl; | |
43 | - scope.deviceAliasList = []; | |
44 | - scope.deviceAlias = null; | |
45 | - | |
46 | - scope.updateValidity = function () { | |
47 | - var value = ngModelCtrl.$viewValue; | |
48 | - var valid = angular.isDefined(value) && value != null || !scope.tbRequired; | |
49 | - ngModelCtrl.$setValidity('deviceAlias', valid); | |
50 | - }; | |
51 | - | |
52 | - scope.$watch('deviceAliases', function () { | |
53 | - scope.deviceAliasList = []; | |
54 | - for (var aliasId in scope.deviceAliases) { | |
55 | - var deviceAlias = {id: aliasId, alias: scope.deviceAliases[aliasId].alias, deviceId: scope.deviceAliases[aliasId].deviceId}; | |
56 | - scope.deviceAliasList.push(deviceAlias); | |
57 | - } | |
58 | - }, true); | |
59 | - | |
60 | - scope.$watch('deviceAlias', function () { | |
61 | - scope.updateView(); | |
62 | - }); | |
63 | - | |
64 | - scope.deviceAliasSearch = function (deviceAliasSearchText) { | |
65 | - return deviceAliasSearchText ? scope.deviceAliasList.filter( | |
66 | - scope.createFilterForDeviceAlias(deviceAliasSearchText)) : scope.deviceAliasList; | |
67 | - }; | |
68 | - | |
69 | - scope.createFilterForDeviceAlias = function (query) { | |
70 | - var lowercaseQuery = angular.lowercase(query); | |
71 | - return function filterFn(deviceAlias) { | |
72 | - return (angular.lowercase(deviceAlias.alias).indexOf(lowercaseQuery) === 0); | |
73 | - }; | |
74 | - }; | |
75 | - | |
76 | - scope.updateView = function () { | |
77 | - ngModelCtrl.$setViewValue(scope.deviceAlias); | |
78 | - scope.updateValidity(); | |
79 | - } | |
80 | - | |
81 | - ngModelCtrl.$render = function () { | |
82 | - if (ngModelCtrl.$viewValue) { | |
83 | - scope.deviceAlias = ngModelCtrl.$viewValue; | |
84 | - } | |
85 | - } | |
86 | - | |
87 | - scope.textIsNotEmpty = function(text) { | |
88 | - return (text && text != null && text.length > 0) ? true : false; | |
89 | - } | |
90 | - | |
91 | - scope.deviceAliasEnter = function($event) { | |
92 | - if ($event.keyCode === $mdConstant.KEY_CODE.ENTER) { | |
93 | - $event.preventDefault(); | |
94 | - if (!scope.deviceAlias) { | |
95 | - var found = scope.deviceAliasSearch(scope.deviceAliasSearchText); | |
96 | - found = found.length > 0; | |
97 | - if (!found) { | |
98 | - scope.createDeviceAlias($event, scope.deviceAliasSearchText); | |
99 | - } | |
100 | - } | |
101 | - } | |
102 | - } | |
103 | - | |
104 | - scope.createDeviceAlias = function (event, alias) { | |
105 | - var autoChild = $('#device-autocomplete', element)[0].firstElementChild; | |
106 | - var el = angular.element(autoChild); | |
107 | - el.scope().$mdAutocompleteCtrl.hidden = true; | |
108 | - el.scope().$mdAutocompleteCtrl.hasNotFound = false; | |
109 | - event.preventDefault(); | |
110 | - var promise = scope.onCreateDeviceAlias({event: event, alias: alias}); | |
111 | - if (promise) { | |
112 | - promise.then( | |
113 | - function success(newAlias) { | |
114 | - el.scope().$mdAutocompleteCtrl.hasNotFound = true; | |
115 | - if (newAlias) { | |
116 | - scope.deviceAliasList.push(newAlias); | |
117 | - scope.deviceAlias = newAlias; | |
118 | - } | |
119 | - }, | |
120 | - function fail() { | |
121 | - el.scope().$mdAutocompleteCtrl.hasNotFound = true; | |
122 | - } | |
123 | - ); | |
124 | - } else { | |
125 | - el.scope().$mdAutocompleteCtrl.hasNotFound = true; | |
126 | - } | |
127 | - }; | |
128 | - | |
129 | - $compile(element.contents())(scope); | |
130 | - } | |
131 | - | |
132 | - return { | |
133 | - restrict: "E", | |
134 | - require: "^ngModel", | |
135 | - link: linker, | |
136 | - scope: { | |
137 | - tbRequired: '=?', | |
138 | - deviceAliases: '=', | |
139 | - onCreateDeviceAlias: '&' | |
140 | - } | |
141 | - }; | |
142 | -} | |
143 | - | |
144 | -/* eslint-enable angular/angularelement */ |
ui/src/app/components/device-alias-select.tpl.html
deleted
100644 → 0
1 | -<!-- | |
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 | -<section layout='column'> | |
19 | - <md-autocomplete id="device-autocomplete" | |
20 | - md-input-name="device_alias" | |
21 | - ng-required="tbRequired" | |
22 | - ng-model="deviceAlias" | |
23 | - md-selected-item="deviceAlias" | |
24 | - md-search-text="deviceAliasSearchText" | |
25 | - md-items="item in deviceAliasSearch(deviceAliasSearchText)" | |
26 | - md-item-text="item.alias" | |
27 | - tb-keydown="deviceAliasEnter($event)" | |
28 | - tb-keypress="deviceAliasEnter($event)" | |
29 | - md-min-length="0" | |
30 | - placeholder="{{ 'device.device-alias' | translate }}" | |
31 | - md-menu-class="tb-device-alias-autocomplete"> | |
32 | - <md-item-template> | |
33 | - <span md-highlight-text="deviceAliasSearchText" md-highlight-flags="^i">{{item.alias}}</span> | |
34 | - </md-item-template> | |
35 | - <md-not-found> | |
36 | - <div class="tb-not-found"> | |
37 | - <div class="tb-no-entries" ng-if="!textIsNotEmpty(deviceAliasSearchText)"> | |
38 | - <span translate>device.no-aliases-found</span> | |
39 | - </div> | |
40 | - <div ng-if="textIsNotEmpty(deviceAliasSearchText)"> | |
41 | - <span translate translate-values='{ alias: "{{deviceAliasSearchText | truncate:true:6:'...'}}" }'>device.no-alias-matching</span> | |
42 | - <span> | |
43 | - <a translate ng-click="createDeviceAlias($event, deviceAliasSearchText)">device.create-new-alias</a> | |
44 | - </span> | |
45 | - </div> | |
46 | - </div> | |
47 | - </md-not-found> | |
48 | - </md-autocomplete> | |
49 | - <div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert"> | |
50 | - <div translate ng-message="deviceAlias" class="tb-error-message">device.alias-required</div> | |
51 | - </div> | |
52 | -</section> |
ui/src/app/components/device-filter.directive.js
deleted
100644 → 0
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 | -/* eslint-disable import/no-unresolved, import/default */ | |
18 | - | |
19 | -import deviceFilterTemplate from './device-filter.tpl.html'; | |
20 | - | |
21 | -/* eslint-enable import/no-unresolved, import/default */ | |
22 | - | |
23 | -import './device-filter.scss'; | |
24 | - | |
25 | -export default angular.module('thingsboard.directives.deviceFilter', []) | |
26 | - .directive('tbDeviceFilter', DeviceFilter) | |
27 | - .name; | |
28 | - | |
29 | -/*@ngInject*/ | |
30 | -function DeviceFilter($compile, $templateCache, $q, deviceService) { | |
31 | - | |
32 | - var linker = function (scope, element, attrs, ngModelCtrl) { | |
33 | - | |
34 | - var template = $templateCache.get(deviceFilterTemplate); | |
35 | - element.html(template); | |
36 | - | |
37 | - scope.ngModelCtrl = ngModelCtrl; | |
38 | - | |
39 | - scope.fetchDevices = function(searchText, limit) { | |
40 | - var pageLink = {limit: limit, textSearch: searchText}; | |
41 | - | |
42 | - var deferred = $q.defer(); | |
43 | - | |
44 | - deviceService.getTenantDevices(pageLink, false).then(function success(result) { | |
45 | - deferred.resolve(result.data); | |
46 | - }, function fail() { | |
47 | - deferred.reject(); | |
48 | - }); | |
49 | - | |
50 | - return deferred.promise; | |
51 | - } | |
52 | - | |
53 | - scope.updateValidity = function() { | |
54 | - if (ngModelCtrl.$viewValue) { | |
55 | - var value = ngModelCtrl.$viewValue; | |
56 | - var valid; | |
57 | - if (value.useFilter) { | |
58 | - ngModelCtrl.$setValidity('deviceList', true); | |
59 | - if (angular.isDefined(value.deviceNameFilter) && value.deviceNameFilter.length > 0) { | |
60 | - ngModelCtrl.$setValidity('deviceNameFilter', true); | |
61 | - valid = angular.isDefined(scope.model.matchingFilterDevice) && scope.model.matchingFilterDevice != null; | |
62 | - ngModelCtrl.$setValidity('deviceNameFilterDeviceMatch', valid); | |
63 | - } else { | |
64 | - ngModelCtrl.$setValidity('deviceNameFilter', false); | |
65 | - } | |
66 | - } else { | |
67 | - ngModelCtrl.$setValidity('deviceNameFilter', true); | |
68 | - ngModelCtrl.$setValidity('deviceNameFilterDeviceMatch', true); | |
69 | - valid = angular.isDefined(value.deviceList) && value.deviceList.length > 0; | |
70 | - ngModelCtrl.$setValidity('deviceList', valid); | |
71 | - } | |
72 | - } | |
73 | - } | |
74 | - | |
75 | - ngModelCtrl.$render = function () { | |
76 | - destroyWatchers(); | |
77 | - scope.model = { | |
78 | - useFilter: false, | |
79 | - deviceList: [], | |
80 | - deviceNameFilter: '' | |
81 | - } | |
82 | - if (ngModelCtrl.$viewValue) { | |
83 | - var value = ngModelCtrl.$viewValue; | |
84 | - var model = scope.model; | |
85 | - model.useFilter = value.useFilter === true ? true: false; | |
86 | - model.deviceList = []; | |
87 | - model.deviceNameFilter = value.deviceNameFilter || ''; | |
88 | - processDeviceNameFilter(model.deviceNameFilter).then( | |
89 | - function(device) { | |
90 | - scope.model.matchingFilterDevice = device; | |
91 | - if (value.deviceList && value.deviceList.length > 0) { | |
92 | - deviceService.getDevices(value.deviceList).then(function (devices) { | |
93 | - model.deviceList = devices; | |
94 | - updateMatchingDevice(); | |
95 | - initWatchers(); | |
96 | - }); | |
97 | - } else { | |
98 | - updateMatchingDevice(); | |
99 | - initWatchers(); | |
100 | - } | |
101 | - } | |
102 | - ) | |
103 | - } | |
104 | - } | |
105 | - | |
106 | - function updateMatchingDevice() { | |
107 | - if (scope.model.useFilter) { | |
108 | - scope.model.matchingDevice = scope.model.matchingFilterDevice; | |
109 | - } else { | |
110 | - if (scope.model.deviceList && scope.model.deviceList.length > 0) { | |
111 | - scope.model.matchingDevice = scope.model.deviceList[0]; | |
112 | - } else { | |
113 | - scope.model.matchingDevice = null; | |
114 | - } | |
115 | - } | |
116 | - } | |
117 | - | |
118 | - function processDeviceNameFilter(deviceNameFilter) { | |
119 | - var deferred = $q.defer(); | |
120 | - if (angular.isDefined(deviceNameFilter) && deviceNameFilter.length > 0) { | |
121 | - scope.fetchDevices(deviceNameFilter, 1).then(function (devices) { | |
122 | - if (devices && devices.length > 0) { | |
123 | - deferred.resolve(devices[0]); | |
124 | - } else { | |
125 | - deferred.resolve(null); | |
126 | - } | |
127 | - }); | |
128 | - } else { | |
129 | - deferred.resolve(null); | |
130 | - } | |
131 | - return deferred.promise; | |
132 | - } | |
133 | - | |
134 | - function destroyWatchers() { | |
135 | - if (scope.deviceListDeregistration) { | |
136 | - scope.deviceListDeregistration(); | |
137 | - scope.deviceListDeregistration = null; | |
138 | - } | |
139 | - if (scope.useFilterDeregistration) { | |
140 | - scope.useFilterDeregistration(); | |
141 | - scope.useFilterDeregistration = null; | |
142 | - } | |
143 | - if (scope.deviceNameFilterDeregistration) { | |
144 | - scope.deviceNameFilterDeregistration(); | |
145 | - scope.deviceNameFilterDeregistration = null; | |
146 | - } | |
147 | - if (scope.matchingDeviceDeregistration) { | |
148 | - scope.matchingDeviceDeregistration(); | |
149 | - scope.matchingDeviceDeregistration = null; | |
150 | - } | |
151 | - } | |
152 | - | |
153 | - function initWatchers() { | |
154 | - scope.deviceListDeregistration = scope.$watch('model.deviceList', function () { | |
155 | - if (ngModelCtrl.$viewValue) { | |
156 | - var value = ngModelCtrl.$viewValue; | |
157 | - value.deviceList = []; | |
158 | - if (scope.model.deviceList && scope.model.deviceList.length > 0) { | |
159 | - for (var i in scope.model.deviceList) { | |
160 | - value.deviceList.push(scope.model.deviceList[i].id.id); | |
161 | - } | |
162 | - } | |
163 | - updateMatchingDevice(); | |
164 | - ngModelCtrl.$setViewValue(value); | |
165 | - scope.updateValidity(); | |
166 | - } | |
167 | - }, true); | |
168 | - scope.useFilterDeregistration = scope.$watch('model.useFilter', function () { | |
169 | - if (ngModelCtrl.$viewValue) { | |
170 | - var value = ngModelCtrl.$viewValue; | |
171 | - value.useFilter = scope.model.useFilter; | |
172 | - updateMatchingDevice(); | |
173 | - ngModelCtrl.$setViewValue(value); | |
174 | - scope.updateValidity(); | |
175 | - } | |
176 | - }); | |
177 | - scope.deviceNameFilterDeregistration = scope.$watch('model.deviceNameFilter', function (newNameFilter, prevNameFilter) { | |
178 | - if (ngModelCtrl.$viewValue) { | |
179 | - if (!angular.equals(newNameFilter, prevNameFilter)) { | |
180 | - var value = ngModelCtrl.$viewValue; | |
181 | - value.deviceNameFilter = scope.model.deviceNameFilter; | |
182 | - processDeviceNameFilter(value.deviceNameFilter).then( | |
183 | - function(device) { | |
184 | - scope.model.matchingFilterDevice = device; | |
185 | - updateMatchingDevice(); | |
186 | - ngModelCtrl.$setViewValue(value); | |
187 | - scope.updateValidity(); | |
188 | - } | |
189 | - ); | |
190 | - } | |
191 | - } | |
192 | - }); | |
193 | - | |
194 | - scope.matchingDeviceDeregistration = scope.$watch('model.matchingDevice', function (newMatchingDevice, prevMatchingDevice) { | |
195 | - if (!angular.equals(newMatchingDevice, prevMatchingDevice)) { | |
196 | - if (scope.onMatchingDeviceChange) { | |
197 | - scope.onMatchingDeviceChange({device: newMatchingDevice}); | |
198 | - } | |
199 | - } | |
200 | - }); | |
201 | - } | |
202 | - | |
203 | - $compile(element.contents())(scope); | |
204 | - | |
205 | - } | |
206 | - | |
207 | - return { | |
208 | - restrict: "E", | |
209 | - require: "^ngModel", | |
210 | - link: linker, | |
211 | - scope: { | |
212 | - isEdit: '=', | |
213 | - onMatchingDeviceChange: '&' | |
214 | - } | |
215 | - }; | |
216 | - | |
217 | -} |
ui/src/app/components/device-filter.scss
deleted
100644 → 0
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 | -.tb-device-filter { | |
17 | - #device_list_chips { | |
18 | - .md-chips { | |
19 | - padding-bottom: 1px; | |
20 | - } | |
21 | - } | |
22 | - .device-name-filter-input { | |
23 | - margin-top: 10px; | |
24 | - margin-bottom: 0px; | |
25 | - .md-errors-spacer { | |
26 | - min-height: 0px; | |
27 | - } | |
28 | - } | |
29 | - .tb-filter-switch { | |
30 | - padding-left: 10px; | |
31 | - .filter-switch { | |
32 | - margin: 0; | |
33 | - } | |
34 | - .filter-label { | |
35 | - margin: 5px 0; | |
36 | - } | |
37 | - } | |
38 | - .tb-error-messages { | |
39 | - margin-top: -11px; | |
40 | - height: 35px; | |
41 | - .tb-error-message { | |
42 | - padding-left: 1px; | |
43 | - } | |
44 | - } | |
45 | -} | |
\ No newline at end of file |
ui/src/app/components/device-filter.tpl.html
deleted
100644 → 0
1 | -<!-- | |
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 | -<section layout='column' class="tb-device-filter"> | |
19 | - <section layout='row'> | |
20 | - <section layout="column" flex ng-show="!model.useFilter"> | |
21 | - <md-chips flex | |
22 | - id="device_list_chips" | |
23 | - ng-required="!useFilter" | |
24 | - ng-model="model.deviceList" md-autocomplete-snap | |
25 | - md-require-match="true"> | |
26 | - <md-autocomplete | |
27 | - md-no-cache="true" | |
28 | - id="device" | |
29 | - md-selected-item="selectedDevice" | |
30 | - md-search-text="deviceSearchText" | |
31 | - md-items="item in fetchDevices(deviceSearchText, 10)" | |
32 | - md-item-text="item.name" | |
33 | - md-min-length="0" | |
34 | - placeholder="{{ 'device.device-list' | translate }}"> | |
35 | - <md-item-template> | |
36 | - <span md-highlight-text="deviceSearchText" md-highlight-flags="^i">{{item.name}}</span> | |
37 | - </md-item-template> | |
38 | - <md-not-found> | |
39 | - <span translate translate-values='{ device: deviceSearchText }'>device.no-devices-matching</span> | |
40 | - </md-not-found> | |
41 | - </md-autocomplete> | |
42 | - <md-chip-template> | |
43 | - <span> | |
44 | - <strong>{{$chip.name}}</strong> | |
45 | - </span> | |
46 | - </md-chip-template> | |
47 | - </md-chips> | |
48 | - </section> | |
49 | - <section layout="row" flex ng-show="model.useFilter"> | |
50 | - <md-input-container flex class="device-name-filter-input"> | |
51 | - <label translate>device.name-starts-with</label> | |
52 | - <input ng-model="model.deviceNameFilter" aria-label="{{ 'device.name-starts-with' | translate }}"> | |
53 | - </md-input-container> | |
54 | - </section> | |
55 | - <section class="tb-filter-switch" layout="column" layout-align="center center"> | |
56 | - <label class="tb-small filter-label" translate>device.use-device-name-filter</label> | |
57 | - <md-switch class="filter-switch" ng-model="model.useFilter" aria-label="use-filter-switcher"> | |
58 | - </md-switch> | |
59 | - </section> | |
60 | - </section> | |
61 | - <div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert"> | |
62 | - <div translate ng-message="deviceList" class="tb-error-message">device.device-list-empty</div> | |
63 | - <div translate ng-message="deviceNameFilter" class="tb-error-message">device.device-name-filter-required</div> | |
64 | - <div translate translate-values='{ device: model.deviceNameFilter }' ng-message="deviceNameFilterDeviceMatch" | |
65 | - class="tb-error-message">device.device-name-filter-no-device-matched</div> | |
66 | - </div> | |
67 | -</section> | |
\ No newline at end of file |