Commit 9f38981b9d9f5dc3c66518746c9705dcb897c7bb
Merge remote-tracking branch 'upstream/master' into feature/mqtt-plugin
Showing
62 changed files
with
3199 additions
and
204 deletions
Too many changes to show.
To preserve performance only 62 of 202 files are displayed.
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 com.google.common.util.concurrent.ListenableFuture; | ||
19 | +import org.apache.commons.lang3.StringUtils; | ||
20 | +import org.springframework.http.HttpStatus; | ||
21 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
22 | +import org.springframework.web.bind.annotation.*; | ||
23 | +import org.thingsboard.server.common.data.Customer; | ||
24 | +import org.thingsboard.server.common.data.Event; | ||
25 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
26 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
27 | +import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
28 | +import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
29 | +import org.thingsboard.server.common.data.asset.Asset; | ||
30 | +import org.thingsboard.server.common.data.id.*; | ||
31 | +import org.thingsboard.server.common.data.page.TextPageData; | ||
32 | +import org.thingsboard.server.common.data.page.TextPageLink; | ||
33 | +import org.thingsboard.server.common.data.page.TimePageData; | ||
34 | +import org.thingsboard.server.common.data.page.TimePageLink; | ||
35 | +import org.thingsboard.server.dao.asset.AssetSearchQuery; | ||
36 | +import org.thingsboard.server.dao.exception.IncorrectParameterException; | ||
37 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
38 | +import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
39 | +import org.thingsboard.server.exception.ThingsboardException; | ||
40 | +import org.thingsboard.server.service.security.model.SecurityUser; | ||
41 | + | ||
42 | +import java.util.ArrayList; | ||
43 | +import java.util.List; | ||
44 | +import java.util.stream.Collectors; | ||
45 | + | ||
46 | +@RestController | ||
47 | +@RequestMapping("/api") | ||
48 | +public class AlarmController extends BaseController { | ||
49 | + | ||
50 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
51 | + @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) | ||
52 | + @ResponseBody | ||
53 | + public Alarm getAlarmById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | ||
54 | + checkParameter("alarmId", strAlarmId); | ||
55 | + try { | ||
56 | + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); | ||
57 | + return checkAlarmId(alarmId); | ||
58 | + } catch (Exception e) { | ||
59 | + throw handleException(e); | ||
60 | + } | ||
61 | + } | ||
62 | + | ||
63 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
64 | + @RequestMapping(value = "/alarm", method = RequestMethod.POST) | ||
65 | + @ResponseBody | ||
66 | + public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { | ||
67 | + try { | ||
68 | + alarm.setTenantId(getCurrentUser().getTenantId()); | ||
69 | + return checkNotNull(alarmService.createOrUpdateAlarm(alarm)); | ||
70 | + } catch (Exception e) { | ||
71 | + throw handleException(e); | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
76 | + @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) | ||
77 | + @ResponseStatus(value = HttpStatus.OK) | ||
78 | + public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | ||
79 | + checkParameter("alarmId", strAlarmId); | ||
80 | + try { | ||
81 | + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); | ||
82 | + checkAlarmId(alarmId); | ||
83 | + alarmService.ackAlarm(alarmId, System.currentTimeMillis()).get(); | ||
84 | + } catch (Exception e) { | ||
85 | + throw handleException(e); | ||
86 | + } | ||
87 | + } | ||
88 | + | ||
89 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
90 | + @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) | ||
91 | + @ResponseStatus(value = HttpStatus.OK) | ||
92 | + public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | ||
93 | + checkParameter("alarmId", strAlarmId); | ||
94 | + try { | ||
95 | + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); | ||
96 | + checkAlarmId(alarmId); | ||
97 | + alarmService.clearAlarm(alarmId, System.currentTimeMillis()).get(); | ||
98 | + } catch (Exception e) { | ||
99 | + throw handleException(e); | ||
100 | + } | ||
101 | + } | ||
102 | + | ||
103 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
104 | + @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) | ||
105 | + @ResponseBody | ||
106 | + public TimePageData<Alarm> getAlarms( | ||
107 | + @PathVariable("entityType") String strEntityType, | ||
108 | + @PathVariable("entityId") String strEntityId, | ||
109 | + @RequestParam(required = false) String status, | ||
110 | + @RequestParam int limit, | ||
111 | + @RequestParam(required = false) Long startTime, | ||
112 | + @RequestParam(required = false) Long endTime, | ||
113 | + @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
114 | + @RequestParam(required = false) String offset | ||
115 | + ) throws ThingsboardException { | ||
116 | + checkParameter("EntityId", strEntityId); | ||
117 | + checkParameter("EntityType", strEntityType); | ||
118 | + EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); | ||
119 | + AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); | ||
120 | + checkEntityId(entityId); | ||
121 | + try { | ||
122 | + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | ||
123 | + return checkNotNull(alarmService.findAlarms(new AlarmQuery(entityId, pageLink, alarmStatus)).get()); | ||
124 | + } catch (Exception e) { | ||
125 | + throw handleException(e); | ||
126 | + } | ||
127 | + } | ||
128 | + | ||
129 | +} |
@@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; | @@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; | ||
21 | import org.springframework.web.bind.annotation.*; | 21 | import org.springframework.web.bind.annotation.*; |
22 | import org.thingsboard.server.common.data.Customer; | 22 | import org.thingsboard.server.common.data.Customer; |
23 | import org.thingsboard.server.common.data.asset.Asset; | 23 | import org.thingsboard.server.common.data.asset.Asset; |
24 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | ||
24 | import org.thingsboard.server.common.data.id.AssetId; | 25 | import org.thingsboard.server.common.data.id.AssetId; |
25 | import org.thingsboard.server.common.data.id.CustomerId; | 26 | import org.thingsboard.server.common.data.id.CustomerId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -136,13 +137,18 @@ public class AssetController extends BaseController { | @@ -136,13 +137,18 @@ public class AssetController extends BaseController { | ||
136 | @ResponseBody | 137 | @ResponseBody |
137 | public TextPageData<Asset> getTenantAssets( | 138 | public TextPageData<Asset> getTenantAssets( |
138 | @RequestParam int limit, | 139 | @RequestParam int limit, |
140 | + @RequestParam(required = false) String type, | ||
139 | @RequestParam(required = false) String textSearch, | 141 | @RequestParam(required = false) String textSearch, |
140 | @RequestParam(required = false) String idOffset, | 142 | @RequestParam(required = false) String idOffset, |
141 | @RequestParam(required = false) String textOffset) throws ThingsboardException { | 143 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
142 | try { | 144 | try { |
143 | TenantId tenantId = getCurrentUser().getTenantId(); | 145 | TenantId tenantId = getCurrentUser().getTenantId(); |
144 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 146 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
145 | - return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink)); | 147 | + if (type != null && type.trim().length()>0) { |
148 | + return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); | ||
149 | + } else { | ||
150 | + return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink)); | ||
151 | + } | ||
146 | } catch (Exception e) { | 152 | } catch (Exception e) { |
147 | throw handleException(e); | 153 | throw handleException(e); |
148 | } | 154 | } |
@@ -167,6 +173,7 @@ public class AssetController extends BaseController { | @@ -167,6 +173,7 @@ public class AssetController extends BaseController { | ||
167 | public TextPageData<Asset> getCustomerAssets( | 173 | public TextPageData<Asset> getCustomerAssets( |
168 | @PathVariable("customerId") String strCustomerId, | 174 | @PathVariable("customerId") String strCustomerId, |
169 | @RequestParam int limit, | 175 | @RequestParam int limit, |
176 | + @RequestParam(required = false) String type, | ||
170 | @RequestParam(required = false) String textSearch, | 177 | @RequestParam(required = false) String textSearch, |
171 | @RequestParam(required = false) String idOffset, | 178 | @RequestParam(required = false) String idOffset, |
172 | @RequestParam(required = false) String textOffset) throws ThingsboardException { | 179 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
@@ -176,7 +183,11 @@ public class AssetController extends BaseController { | @@ -176,7 +183,11 @@ public class AssetController extends BaseController { | ||
176 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 183 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
177 | checkCustomerId(customerId); | 184 | checkCustomerId(customerId); |
178 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 185 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
179 | - return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | 186 | + if (type != null && type.trim().length()>0) { |
187 | + return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | ||
188 | + } else { | ||
189 | + return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
190 | + } | ||
180 | } catch (Exception e) { | 191 | } catch (Exception e) { |
181 | throw handleException(e); | 192 | throw handleException(e); |
182 | } | 193 | } |
@@ -231,4 +242,18 @@ public class AssetController extends BaseController { | @@ -231,4 +242,18 @@ public class AssetController extends BaseController { | ||
231 | throw handleException(e); | 242 | throw handleException(e); |
232 | } | 243 | } |
233 | } | 244 | } |
245 | + | ||
246 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
247 | + @RequestMapping(value = "/asset/types", method = RequestMethod.GET) | ||
248 | + @ResponseBody | ||
249 | + public List<TenantAssetType> getAssetTypes() throws ThingsboardException { | ||
250 | + try { | ||
251 | + SecurityUser user = getCurrentUser(); | ||
252 | + TenantId tenantId = user.getTenantId(); | ||
253 | + ListenableFuture<List<TenantAssetType>> assetTypes = assetService.findAssetTypesByTenantId(tenantId); | ||
254 | + return checkNotNull(assetTypes.get()); | ||
255 | + } catch (Exception e) { | ||
256 | + throw handleException(e); | ||
257 | + } | ||
258 | + } | ||
234 | } | 259 | } |
@@ -25,6 +25,8 @@ import org.springframework.security.core.context.SecurityContextHolder; | @@ -25,6 +25,8 @@ import org.springframework.security.core.context.SecurityContextHolder; | ||
25 | import org.springframework.web.bind.annotation.ExceptionHandler; | 25 | import org.springframework.web.bind.annotation.ExceptionHandler; |
26 | import org.thingsboard.server.actors.service.ActorService; | 26 | import org.thingsboard.server.actors.service.ActorService; |
27 | import org.thingsboard.server.common.data.*; | 27 | import org.thingsboard.server.common.data.*; |
28 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
29 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
28 | import org.thingsboard.server.common.data.asset.Asset; | 30 | import org.thingsboard.server.common.data.asset.Asset; |
29 | import org.thingsboard.server.common.data.id.*; | 31 | import org.thingsboard.server.common.data.id.*; |
30 | import org.thingsboard.server.common.data.page.TextPageLink; | 32 | import org.thingsboard.server.common.data.page.TextPageLink; |
@@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.rule.RuleMetaData; | @@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.rule.RuleMetaData; | ||
36 | import org.thingsboard.server.common.data.security.Authority; | 38 | import org.thingsboard.server.common.data.security.Authority; |
37 | import org.thingsboard.server.common.data.widget.WidgetType; | 39 | import org.thingsboard.server.common.data.widget.WidgetType; |
38 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 40 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
41 | +import org.thingsboard.server.dao.alarm.AlarmService; | ||
39 | import org.thingsboard.server.dao.asset.AssetService; | 42 | import org.thingsboard.server.dao.asset.AssetService; |
40 | import org.thingsboard.server.dao.customer.CustomerService; | 43 | import org.thingsboard.server.dao.customer.CustomerService; |
41 | import org.thingsboard.server.dao.dashboard.DashboardService; | 44 | import org.thingsboard.server.dao.dashboard.DashboardService; |
@@ -84,6 +87,9 @@ public abstract class BaseController { | @@ -84,6 +87,9 @@ public abstract class BaseController { | ||
84 | protected AssetService assetService; | 87 | protected AssetService assetService; |
85 | 88 | ||
86 | @Autowired | 89 | @Autowired |
90 | + protected AlarmService alarmService; | ||
91 | + | ||
92 | + @Autowired | ||
87 | protected DeviceCredentialsService deviceCredentialsService; | 93 | protected DeviceCredentialsService deviceCredentialsService; |
88 | 94 | ||
89 | @Autowired | 95 | @Autowired |
@@ -334,6 +340,22 @@ public abstract class BaseController { | @@ -334,6 +340,22 @@ public abstract class BaseController { | ||
334 | } | 340 | } |
335 | } | 341 | } |
336 | 342 | ||
343 | + Alarm checkAlarmId(AlarmId alarmId) throws ThingsboardException { | ||
344 | + try { | ||
345 | + validateId(alarmId, "Incorrect alarmId " + alarmId); | ||
346 | + Alarm alarm = alarmService.findAlarmByIdAsync(alarmId).get(); | ||
347 | + checkAlarm(alarm); | ||
348 | + return alarm; | ||
349 | + } catch (Exception e) { | ||
350 | + throw handleException(e, false); | ||
351 | + } | ||
352 | + } | ||
353 | + | ||
354 | + protected void checkAlarm(Alarm alarm) throws ThingsboardException { | ||
355 | + checkNotNull(alarm); | ||
356 | + checkTenantId(alarm.getTenantId()); | ||
357 | + } | ||
358 | + | ||
337 | WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, boolean modify) throws ThingsboardException { | 359 | WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, boolean modify) throws ThingsboardException { |
338 | try { | 360 | try { |
339 | validateId(widgetsBundleId, "Incorrect widgetsBundleId " + widgetsBundleId); | 361 | validateId(widgetsBundleId, "Incorrect widgetsBundleId " + widgetsBundleId); |
@@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; | @@ -21,6 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; | ||
21 | import org.springframework.web.bind.annotation.*; | 21 | import org.springframework.web.bind.annotation.*; |
22 | import org.thingsboard.server.common.data.Customer; | 22 | import org.thingsboard.server.common.data.Customer; |
23 | import org.thingsboard.server.common.data.Device; | 23 | import org.thingsboard.server.common.data.Device; |
24 | +import org.thingsboard.server.common.data.TenantDeviceType; | ||
24 | import org.thingsboard.server.common.data.id.CustomerId; | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
25 | import org.thingsboard.server.common.data.id.DeviceId; | 26 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -166,13 +167,18 @@ public class DeviceController extends BaseController { | @@ -166,13 +167,18 @@ public class DeviceController extends BaseController { | ||
166 | @ResponseBody | 167 | @ResponseBody |
167 | public TextPageData<Device> getTenantDevices( | 168 | public TextPageData<Device> getTenantDevices( |
168 | @RequestParam int limit, | 169 | @RequestParam int limit, |
170 | + @RequestParam(required = false) String type, | ||
169 | @RequestParam(required = false) String textSearch, | 171 | @RequestParam(required = false) String textSearch, |
170 | @RequestParam(required = false) String idOffset, | 172 | @RequestParam(required = false) String idOffset, |
171 | @RequestParam(required = false) String textOffset) throws ThingsboardException { | 173 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
172 | try { | 174 | try { |
173 | TenantId tenantId = getCurrentUser().getTenantId(); | 175 | TenantId tenantId = getCurrentUser().getTenantId(); |
174 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 176 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
175 | - return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink)); | 177 | + if (type != null && type.trim().length()>0) { |
178 | + return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink)); | ||
179 | + } else { | ||
180 | + return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink)); | ||
181 | + } | ||
176 | } catch (Exception e) { | 182 | } catch (Exception e) { |
177 | throw handleException(e); | 183 | throw handleException(e); |
178 | } | 184 | } |
@@ -197,6 +203,7 @@ public class DeviceController extends BaseController { | @@ -197,6 +203,7 @@ public class DeviceController extends BaseController { | ||
197 | public TextPageData<Device> getCustomerDevices( | 203 | public TextPageData<Device> getCustomerDevices( |
198 | @PathVariable("customerId") String strCustomerId, | 204 | @PathVariable("customerId") String strCustomerId, |
199 | @RequestParam int limit, | 205 | @RequestParam int limit, |
206 | + @RequestParam(required = false) String type, | ||
200 | @RequestParam(required = false) String textSearch, | 207 | @RequestParam(required = false) String textSearch, |
201 | @RequestParam(required = false) String idOffset, | 208 | @RequestParam(required = false) String idOffset, |
202 | @RequestParam(required = false) String textOffset) throws ThingsboardException { | 209 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
@@ -206,7 +213,11 @@ public class DeviceController extends BaseController { | @@ -206,7 +213,11 @@ public class DeviceController extends BaseController { | ||
206 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 213 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
207 | checkCustomerId(customerId); | 214 | checkCustomerId(customerId); |
208 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 215 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
209 | - return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | 216 | + if (type != null && type.trim().length()>0) { |
217 | + return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | ||
218 | + } else { | ||
219 | + return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
220 | + } | ||
210 | } catch (Exception e) { | 221 | } catch (Exception e) { |
211 | throw handleException(e); | 222 | throw handleException(e); |
212 | } | 223 | } |
@@ -261,4 +272,19 @@ public class DeviceController extends BaseController { | @@ -261,4 +272,19 @@ public class DeviceController extends BaseController { | ||
261 | throw handleException(e); | 272 | throw handleException(e); |
262 | } | 273 | } |
263 | } | 274 | } |
275 | + | ||
276 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
277 | + @RequestMapping(value = "/device/types", method = RequestMethod.GET) | ||
278 | + @ResponseBody | ||
279 | + public List<TenantDeviceType> getDeviceTypes() throws ThingsboardException { | ||
280 | + try { | ||
281 | + SecurityUser user = getCurrentUser(); | ||
282 | + TenantId tenantId = user.getTenantId(); | ||
283 | + ListenableFuture<List<TenantDeviceType>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId); | ||
284 | + return checkNotNull(deviceTypes.get()); | ||
285 | + } catch (Exception e) { | ||
286 | + throw handleException(e); | ||
287 | + } | ||
288 | + } | ||
289 | + | ||
264 | } | 290 | } |
@@ -21,6 +21,8 @@ import org.springframework.web.bind.annotation.*; | @@ -21,6 +21,8 @@ import org.springframework.web.bind.annotation.*; | ||
21 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 22 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
23 | import org.thingsboard.server.common.data.relation.EntityRelation; | 23 | import org.thingsboard.server.common.data.relation.EntityRelation; |
24 | +import org.thingsboard.server.common.data.relation.EntityRelationInfo; | ||
25 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
24 | import org.thingsboard.server.dao.relation.EntityRelationsQuery; | 26 | import org.thingsboard.server.dao.relation.EntityRelationsQuery; |
25 | import org.thingsboard.server.exception.ThingsboardErrorCode; | 27 | import org.thingsboard.server.exception.ThingsboardErrorCode; |
26 | import org.thingsboard.server.exception.ThingsboardException; | 28 | import org.thingsboard.server.exception.ThingsboardException; |
@@ -32,7 +34,7 @@ import java.util.List; | @@ -32,7 +34,7 @@ import java.util.List; | ||
32 | @RequestMapping("/api") | 34 | @RequestMapping("/api") |
33 | public class EntityRelationController extends BaseController { | 35 | public class EntityRelationController extends BaseController { |
34 | 36 | ||
35 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 37 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
36 | @RequestMapping(value = "/relation", method = RequestMethod.POST) | 38 | @RequestMapping(value = "/relation", method = RequestMethod.POST) |
37 | @ResponseStatus(value = HttpStatus.OK) | 39 | @ResponseStatus(value = HttpStatus.OK) |
38 | public void saveRelation(@RequestBody EntityRelation relation) throws ThingsboardException { | 40 | public void saveRelation(@RequestBody EntityRelation relation) throws ThingsboardException { |
@@ -40,17 +42,22 @@ public class EntityRelationController extends BaseController { | @@ -40,17 +42,22 @@ public class EntityRelationController extends BaseController { | ||
40 | checkNotNull(relation); | 42 | checkNotNull(relation); |
41 | checkEntityId(relation.getFrom()); | 43 | checkEntityId(relation.getFrom()); |
42 | checkEntityId(relation.getTo()); | 44 | checkEntityId(relation.getTo()); |
45 | + if (relation.getTypeGroup() == null) { | ||
46 | + relation.setTypeGroup(RelationTypeGroup.COMMON); | ||
47 | + } | ||
43 | relationService.saveRelation(relation).get(); | 48 | relationService.saveRelation(relation).get(); |
44 | } catch (Exception e) { | 49 | } catch (Exception e) { |
45 | throw handleException(e); | 50 | throw handleException(e); |
46 | } | 51 | } |
47 | } | 52 | } |
48 | 53 | ||
49 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 54 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
50 | @RequestMapping(value = "/relation", method = RequestMethod.DELETE, params = {"fromId", "fromType", "relationType", "toId", "toType"}) | 55 | @RequestMapping(value = "/relation", method = RequestMethod.DELETE, params = {"fromId", "fromType", "relationType", "toId", "toType"}) |
51 | @ResponseStatus(value = HttpStatus.OK) | 56 | @ResponseStatus(value = HttpStatus.OK) |
52 | public void deleteRelation(@RequestParam("fromId") String strFromId, | 57 | public void deleteRelation(@RequestParam("fromId") String strFromId, |
53 | - @RequestParam("fromType") String strFromType, @RequestParam("relationType") String strRelationType, | 58 | + @RequestParam("fromType") String strFromType, |
59 | + @RequestParam("relationType") String strRelationType, | ||
60 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, | ||
54 | @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { | 61 | @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { |
55 | checkParameter("fromId", strFromId); | 62 | checkParameter("fromId", strFromId); |
56 | checkParameter("fromType", strFromType); | 63 | checkParameter("fromType", strFromType); |
@@ -61,8 +68,9 @@ public class EntityRelationController extends BaseController { | @@ -61,8 +68,9 @@ public class EntityRelationController extends BaseController { | ||
61 | EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); | 68 | EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); |
62 | checkEntityId(fromId); | 69 | checkEntityId(fromId); |
63 | checkEntityId(toId); | 70 | checkEntityId(toId); |
71 | + RelationTypeGroup relationTypeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
64 | try { | 72 | try { |
65 | - Boolean found = relationService.deleteRelation(fromId, toId, strRelationType).get(); | 73 | + Boolean found = relationService.deleteRelation(fromId, toId, strRelationType, relationTypeGroup).get(); |
66 | if (!found) { | 74 | if (!found) { |
67 | throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); | 75 | throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); |
68 | } | 76 | } |
@@ -71,7 +79,7 @@ public class EntityRelationController extends BaseController { | @@ -71,7 +79,7 @@ public class EntityRelationController extends BaseController { | ||
71 | } | 79 | } |
72 | } | 80 | } |
73 | 81 | ||
74 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 82 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN', 'CUSTOMER_USER')") |
75 | @RequestMapping(value = "/relations", method = RequestMethod.DELETE, params = {"id", "type"}) | 83 | @RequestMapping(value = "/relations", method = RequestMethod.DELETE, params = {"id", "type"}) |
76 | @ResponseStatus(value = HttpStatus.OK) | 84 | @ResponseStatus(value = HttpStatus.OK) |
77 | public void deleteRelations(@RequestParam("entityId") String strId, | 85 | public void deleteRelations(@RequestParam("entityId") String strId, |
@@ -87,11 +95,13 @@ public class EntityRelationController extends BaseController { | @@ -87,11 +95,13 @@ public class EntityRelationController extends BaseController { | ||
87 | } | 95 | } |
88 | } | 96 | } |
89 | 97 | ||
90 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 98 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
91 | @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType", "toId", "toType"}) | 99 | @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType", "toId", "toType"}) |
92 | @ResponseStatus(value = HttpStatus.OK) | 100 | @ResponseStatus(value = HttpStatus.OK) |
93 | public void checkRelation(@RequestParam("fromId") String strFromId, | 101 | public void checkRelation(@RequestParam("fromId") String strFromId, |
94 | - @RequestParam("fromType") String strFromType, @RequestParam("relationType") String strRelationType, | 102 | + @RequestParam("fromType") String strFromType, |
103 | + @RequestParam("relationType") String strRelationType, | ||
104 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, | ||
95 | @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { | 105 | @RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { |
96 | try { | 106 | try { |
97 | checkParameter("fromId", strFromId); | 107 | checkParameter("fromId", strFromId); |
@@ -103,7 +113,8 @@ public class EntityRelationController extends BaseController { | @@ -103,7 +113,8 @@ public class EntityRelationController extends BaseController { | ||
103 | EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); | 113 | EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); |
104 | checkEntityId(fromId); | 114 | checkEntityId(fromId); |
105 | checkEntityId(toId); | 115 | checkEntityId(toId); |
106 | - Boolean found = relationService.checkRelation(fromId, toId, strRelationType).get(); | 116 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
117 | + Boolean found = relationService.checkRelation(fromId, toId, strRelationType, typeGroup).get(); | ||
107 | if (!found) { | 118 | if (!found) { |
108 | throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); | 119 | throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); |
109 | } | 120 | } |
@@ -112,71 +123,119 @@ public class EntityRelationController extends BaseController { | @@ -112,71 +123,119 @@ public class EntityRelationController extends BaseController { | ||
112 | } | 123 | } |
113 | } | 124 | } |
114 | 125 | ||
115 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 126 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
116 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType"}) | 127 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType"}) |
117 | @ResponseBody | 128 | @ResponseBody |
118 | - public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType) throws ThingsboardException { | 129 | + public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, |
130 | + @RequestParam("fromType") String strFromType, | ||
131 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
132 | + checkParameter("fromId", strFromId); | ||
133 | + checkParameter("fromType", strFromType); | ||
134 | + EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); | ||
135 | + checkEntityId(entityId); | ||
136 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
137 | + try { | ||
138 | + return checkNotNull(relationService.findByFrom(entityId, typeGroup).get()); | ||
139 | + } catch (Exception e) { | ||
140 | + throw handleException(e); | ||
141 | + } | ||
142 | + } | ||
143 | + | ||
144 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
145 | + @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {"fromId", "fromType"}) | ||
146 | + @ResponseBody | ||
147 | + public List<EntityRelationInfo> findInfoByFrom(@RequestParam("fromId") String strFromId, | ||
148 | + @RequestParam("fromType") String strFromType, | ||
149 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
119 | checkParameter("fromId", strFromId); | 150 | checkParameter("fromId", strFromId); |
120 | checkParameter("fromType", strFromType); | 151 | checkParameter("fromType", strFromType); |
121 | EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); | 152 | EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); |
122 | checkEntityId(entityId); | 153 | checkEntityId(entityId); |
154 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
123 | try { | 155 | try { |
124 | - return checkNotNull(relationService.findByFrom(entityId).get()); | 156 | + return checkNotNull(relationService.findInfoByFrom(entityId, typeGroup).get()); |
125 | } catch (Exception e) { | 157 | } catch (Exception e) { |
126 | throw handleException(e); | 158 | throw handleException(e); |
127 | } | 159 | } |
128 | } | 160 | } |
129 | 161 | ||
130 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 162 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
131 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType"}) | 163 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"fromId", "fromType", "relationType"}) |
132 | @ResponseBody | 164 | @ResponseBody |
133 | - public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, @RequestParam("fromType") String strFromType | ||
134 | - , @RequestParam("relationType") String strRelationType) throws ThingsboardException { | 165 | + public List<EntityRelation> findByFrom(@RequestParam("fromId") String strFromId, |
166 | + @RequestParam("fromType") String strFromType, | ||
167 | + @RequestParam("relationType") String strRelationType, | ||
168 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
135 | checkParameter("fromId", strFromId); | 169 | checkParameter("fromId", strFromId); |
136 | checkParameter("fromType", strFromType); | 170 | checkParameter("fromType", strFromType); |
137 | checkParameter("relationType", strRelationType); | 171 | checkParameter("relationType", strRelationType); |
138 | EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); | 172 | EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); |
139 | checkEntityId(entityId); | 173 | checkEntityId(entityId); |
174 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
140 | try { | 175 | try { |
141 | - return checkNotNull(relationService.findByFromAndType(entityId, strRelationType).get()); | 176 | + return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup).get()); |
142 | } catch (Exception e) { | 177 | } catch (Exception e) { |
143 | throw handleException(e); | 178 | throw handleException(e); |
144 | } | 179 | } |
145 | } | 180 | } |
146 | 181 | ||
147 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 182 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
148 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType"}) | 183 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType"}) |
149 | @ResponseBody | 184 | @ResponseBody |
150 | - public List<EntityRelation> findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType) throws ThingsboardException { | 185 | + public List<EntityRelation> findByTo(@RequestParam("toId") String strToId, |
186 | + @RequestParam("toType") String strToType, | ||
187 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
151 | checkParameter("toId", strToId); | 188 | checkParameter("toId", strToId); |
152 | checkParameter("toType", strToType); | 189 | checkParameter("toType", strToType); |
153 | EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); | 190 | EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); |
154 | checkEntityId(entityId); | 191 | checkEntityId(entityId); |
192 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
155 | try { | 193 | try { |
156 | - return checkNotNull(relationService.findByTo(entityId).get()); | 194 | + return checkNotNull(relationService.findByTo(entityId, typeGroup).get()); |
157 | } catch (Exception e) { | 195 | } catch (Exception e) { |
158 | throw handleException(e); | 196 | throw handleException(e); |
159 | } | 197 | } |
160 | } | 198 | } |
161 | 199 | ||
162 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 200 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
201 | + @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {"toId", "toType"}) | ||
202 | + @ResponseBody | ||
203 | + public List<EntityRelationInfo> findInfoByTo(@RequestParam("toId") String strToId, | ||
204 | + @RequestParam("toType") String strToType, | ||
205 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
206 | + checkParameter("toId", strToId); | ||
207 | + checkParameter("toType", strToType); | ||
208 | + EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); | ||
209 | + checkEntityId(entityId); | ||
210 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
211 | + try { | ||
212 | + return checkNotNull(relationService.findInfoByTo(entityId, typeGroup).get()); | ||
213 | + } catch (Exception e) { | ||
214 | + throw handleException(e); | ||
215 | + } | ||
216 | + } | ||
217 | + | ||
218 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
163 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType", "relationType"}) | 219 | @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {"toId", "toType", "relationType"}) |
164 | @ResponseBody | 220 | @ResponseBody |
165 | - public List<EntityRelation> findByTo(@RequestParam("toId") String strToId, @RequestParam("toType") String strToType | ||
166 | - , @RequestParam("relationType") String strRelationType) throws ThingsboardException { | 221 | + public List<EntityRelation> findByTo(@RequestParam("toId") String strToId, |
222 | + @RequestParam("toType") String strToType, | ||
223 | + @RequestParam("relationType") String strRelationType, | ||
224 | + @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { | ||
167 | checkParameter("toId", strToId); | 225 | checkParameter("toId", strToId); |
168 | checkParameter("toType", strToType); | 226 | checkParameter("toType", strToType); |
169 | checkParameter("relationType", strRelationType); | 227 | checkParameter("relationType", strRelationType); |
170 | EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); | 228 | EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); |
171 | checkEntityId(entityId); | 229 | checkEntityId(entityId); |
230 | + RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); | ||
172 | try { | 231 | try { |
173 | - return checkNotNull(relationService.findByToAndType(entityId, strRelationType).get()); | 232 | + return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup).get()); |
174 | } catch (Exception e) { | 233 | } catch (Exception e) { |
175 | throw handleException(e); | 234 | throw handleException(e); |
176 | } | 235 | } |
177 | } | 236 | } |
178 | 237 | ||
179 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 238 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
180 | @RequestMapping(value = "/relations", method = RequestMethod.POST) | 239 | @RequestMapping(value = "/relations", method = RequestMethod.POST) |
181 | @ResponseBody | 240 | @ResponseBody |
182 | public List<EntityRelation> findByQuery(@RequestBody EntityRelationsQuery query) throws ThingsboardException { | 241 | public List<EntityRelation> findByQuery(@RequestBody EntityRelationsQuery query) throws ThingsboardException { |
@@ -191,4 +250,16 @@ public class EntityRelationController extends BaseController { | @@ -191,4 +250,16 @@ public class EntityRelationController extends BaseController { | ||
191 | } | 250 | } |
192 | } | 251 | } |
193 | 252 | ||
253 | + private RelationTypeGroup parseRelationTypeGroup(String strRelationTypeGroup, RelationTypeGroup defaultValue) { | ||
254 | + RelationTypeGroup result = defaultValue; | ||
255 | + if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length()>0) { | ||
256 | + try { | ||
257 | + result = RelationTypeGroup.valueOf(strRelationTypeGroup); | ||
258 | + } catch (IllegalArgumentException e) { | ||
259 | + result = defaultValue; | ||
260 | + } | ||
261 | + } | ||
262 | + return result; | ||
263 | + } | ||
264 | + | ||
194 | } | 265 | } |
@@ -19,12 +19,18 @@ server: | @@ -19,12 +19,18 @@ server: | ||
19 | address: "${HTTP_BIND_ADDRESS:0.0.0.0}" | 19 | address: "${HTTP_BIND_ADDRESS:0.0.0.0}" |
20 | # Server bind port | 20 | # Server bind port |
21 | port: "${HTTP_BIND_PORT:8080}" | 21 | port: "${HTTP_BIND_PORT:8080}" |
22 | -# Uncomment the following section to enable ssl | ||
23 | -# ssl: | ||
24 | -# key-store: classpath:keystore/keystore.p12 | ||
25 | -# key-store-password: thingsboard | ||
26 | -# keyStoreType: PKCS12 | ||
27 | -# keyAlias: tomcat | 22 | + # Server SSL configuration |
23 | + ssl: | ||
24 | + # Enable/disable SSL support | ||
25 | + enabled: "${SSL_ENABLED:false}" | ||
26 | + # Path to the key store that holds the SSL certificate | ||
27 | + key-store: "${SSL_KEY_STORE:classpath:keystore/keystore.p12}" | ||
28 | + # Password used to access the key store | ||
29 | + key-store-password: "${SSL_KEY_STORE_PASSWORD:thingsboard}" | ||
30 | + # Type of the key store | ||
31 | + key-store-type: "${SSL_KEY_STORE_TYPE:PKCS12}" | ||
32 | + # Alias that identifies the key in the key store | ||
33 | + key-alias: "${SSL_KEY_ALIAS:tomcat}" | ||
28 | 34 | ||
29 | # Zookeeper connection parameters. Used for service discovery. | 35 | # Zookeeper connection parameters. Used for service discovery. |
30 | zk: | 36 | zk: |
@@ -79,12 +85,18 @@ mqtt: | @@ -79,12 +85,18 @@ mqtt: | ||
79 | leak_detector_level: "${NETTY_LEASK_DETECTOR_LVL:DISABLED}" | 85 | leak_detector_level: "${NETTY_LEASK_DETECTOR_LVL:DISABLED}" |
80 | boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}" | 86 | boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}" |
81 | worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}" | 87 | worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}" |
82 | -# Uncomment the following lines to enable ssl for MQTT | ||
83 | -# ssl: | ||
84 | -# key_store: mqttserver.jks | ||
85 | -# key_store_password: server_ks_password | ||
86 | -# key_password: server_key_password | ||
87 | -# key_store_type: JKS | 88 | + # MQTT SSL configuration |
89 | + ssl: | ||
90 | + # Enable/disable SSL support | ||
91 | + enabled: "${MQTT_SSL_ENABLED:false}" | ||
92 | + # Path to the key store that holds the SSL certificate | ||
93 | + key_store: "${MQTT_SSL_KEY_STORE:mqttserver.jks}" | ||
94 | + # Password used to access the key store | ||
95 | + key_store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}" | ||
96 | + # Password used to access the key | ||
97 | + key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}" | ||
98 | + # Type of the key store | ||
99 | + key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}" | ||
88 | 100 | ||
89 | # CoAP server parameters | 101 | # CoAP server parameters |
90 | coap: | 102 | coap: |
@@ -98,13 +98,15 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC | @@ -98,13 +98,15 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC | ||
98 | @IntegrationTest("server.port:0") | 98 | @IntegrationTest("server.port:0") |
99 | public abstract class AbstractControllerTest { | 99 | public abstract class AbstractControllerTest { |
100 | 100 | ||
101 | + protected static final String TEST_TENANT_NAME = "TEST TENANT"; | ||
102 | + | ||
101 | protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; | 103 | protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; |
102 | private static final String SYS_ADMIN_PASSWORD = "sysadmin"; | 104 | private static final String SYS_ADMIN_PASSWORD = "sysadmin"; |
103 | 105 | ||
104 | - protected static final String TENANT_ADMIN_EMAIL = "tenant@thingsboard.org"; | 106 | + protected static final String TENANT_ADMIN_EMAIL = "testtenant@thingsboard.org"; |
105 | private static final String TENANT_ADMIN_PASSWORD = "tenant"; | 107 | private static final String TENANT_ADMIN_PASSWORD = "tenant"; |
106 | 108 | ||
107 | - protected static final String CUSTOMER_USER_EMAIL = "customer@thingsboard.org"; | 109 | + protected static final String CUSTOMER_USER_EMAIL = "testcustomer@thingsboard.org"; |
108 | private static final String CUSTOMER_USER_PASSWORD = "customer"; | 110 | private static final String CUSTOMER_USER_PASSWORD = "customer"; |
109 | 111 | ||
110 | protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), | 112 | protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), |
@@ -147,7 +149,7 @@ public abstract class AbstractControllerTest { | @@ -147,7 +149,7 @@ public abstract class AbstractControllerTest { | ||
147 | loginSysAdmin(); | 149 | loginSysAdmin(); |
148 | 150 | ||
149 | Tenant tenant = new Tenant(); | 151 | Tenant tenant = new Tenant(); |
150 | - tenant.setTitle("Tenant"); | 152 | + tenant.setTitle(TEST_TENANT_NAME); |
151 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 153 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
152 | Assert.assertNotNull(savedTenant); | 154 | Assert.assertNotNull(savedTenant); |
153 | tenantId = savedTenant.getId(); | 155 | tenantId = savedTenant.getId(); |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.controller; | ||
17 | + | ||
18 | +import static org.hamcrest.Matchers.containsString; | ||
19 | +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; | ||
20 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
21 | + | ||
22 | +import java.util.ArrayList; | ||
23 | +import java.util.Collections; | ||
24 | +import java.util.List; | ||
25 | + | ||
26 | +import org.apache.commons.lang3.RandomStringUtils; | ||
27 | +import org.thingsboard.server.common.data.*; | ||
28 | +import org.thingsboard.server.common.data.asset.Asset; | ||
29 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | ||
30 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
31 | +import org.thingsboard.server.common.data.id.AssetId; | ||
32 | +import org.thingsboard.server.common.data.page.TextPageData; | ||
33 | +import org.thingsboard.server.common.data.page.TextPageLink; | ||
34 | +import org.thingsboard.server.common.data.security.Authority; | ||
35 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
36 | +import org.junit.After; | ||
37 | +import org.junit.Assert; | ||
38 | +import org.junit.Before; | ||
39 | +import org.junit.Test; | ||
40 | + | ||
41 | +import com.datastax.driver.core.utils.UUIDs; | ||
42 | +import com.fasterxml.jackson.core.type.TypeReference; | ||
43 | + | ||
44 | +public class AssetControllerTest extends AbstractControllerTest { | ||
45 | + | ||
46 | + private IdComparator<Asset> idComparator = new IdComparator<>(); | ||
47 | + | ||
48 | + private Tenant savedTenant; | ||
49 | + private User tenantAdmin; | ||
50 | + | ||
51 | + @Before | ||
52 | + public void beforeTest() throws Exception { | ||
53 | + loginSysAdmin(); | ||
54 | + | ||
55 | + Tenant tenant = new Tenant(); | ||
56 | + tenant.setTitle("My tenant"); | ||
57 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
58 | + Assert.assertNotNull(savedTenant); | ||
59 | + | ||
60 | + tenantAdmin = new User(); | ||
61 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
62 | + tenantAdmin.setTenantId(savedTenant.getId()); | ||
63 | + tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
64 | + tenantAdmin.setFirstName("Joe"); | ||
65 | + tenantAdmin.setLastName("Downs"); | ||
66 | + | ||
67 | + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
68 | + } | ||
69 | + | ||
70 | + @After | ||
71 | + public void afterTest() throws Exception { | ||
72 | + loginSysAdmin(); | ||
73 | + | ||
74 | + doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
75 | + .andExpect(status().isOk()); | ||
76 | + } | ||
77 | + | ||
78 | + @Test | ||
79 | + public void testSaveAsset() throws Exception { | ||
80 | + Asset asset = new Asset(); | ||
81 | + asset.setName("My asset"); | ||
82 | + asset.setType("default"); | ||
83 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
84 | + | ||
85 | + Assert.assertNotNull(savedAsset); | ||
86 | + Assert.assertNotNull(savedAsset.getId()); | ||
87 | + Assert.assertTrue(savedAsset.getCreatedTime() > 0); | ||
88 | + Assert.assertEquals(savedTenant.getId(), savedAsset.getTenantId()); | ||
89 | + Assert.assertNotNull(savedAsset.getCustomerId()); | ||
90 | + Assert.assertEquals(NULL_UUID, savedAsset.getCustomerId().getId()); | ||
91 | + Assert.assertEquals(asset.getName(), savedAsset.getName()); | ||
92 | + | ||
93 | + savedAsset.setName("My new asset"); | ||
94 | + doPost("/api/asset", savedAsset, Asset.class); | ||
95 | + | ||
96 | + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
97 | + Assert.assertEquals(foundAsset.getName(), savedAsset.getName()); | ||
98 | + } | ||
99 | + | ||
100 | + @Test | ||
101 | + public void testFindAssetById() throws Exception { | ||
102 | + Asset asset = new Asset(); | ||
103 | + asset.setName("My asset"); | ||
104 | + asset.setType("default"); | ||
105 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
106 | + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
107 | + Assert.assertNotNull(foundAsset); | ||
108 | + Assert.assertEquals(savedAsset, foundAsset); | ||
109 | + } | ||
110 | + | ||
111 | + @Test | ||
112 | + public void testFindAssetTypesByTenantId() throws Exception { | ||
113 | + List<Asset> assets = new ArrayList<>(); | ||
114 | + for (int i=0;i<3;i++) { | ||
115 | + Asset asset = new Asset(); | ||
116 | + asset.setName("My asset B"+i); | ||
117 | + asset.setType("typeB"); | ||
118 | + assets.add(doPost("/api/asset", asset, Asset.class)); | ||
119 | + } | ||
120 | + for (int i=0;i<7;i++) { | ||
121 | + Asset asset = new Asset(); | ||
122 | + asset.setName("My asset C"+i); | ||
123 | + asset.setType("typeC"); | ||
124 | + assets.add(doPost("/api/asset", asset, Asset.class)); | ||
125 | + } | ||
126 | + for (int i=0;i<9;i++) { | ||
127 | + Asset asset = new Asset(); | ||
128 | + asset.setName("My asset A"+i); | ||
129 | + asset.setType("typeA"); | ||
130 | + assets.add(doPost("/api/asset", asset, Asset.class)); | ||
131 | + } | ||
132 | + List<TenantAssetType> assetTypes = doGetTyped("/api/asset/types", | ||
133 | + new TypeReference<List<TenantAssetType>>(){}); | ||
134 | + | ||
135 | + Assert.assertNotNull(assetTypes); | ||
136 | + Assert.assertEquals(3, assetTypes.size()); | ||
137 | + Assert.assertEquals("typeA", assetTypes.get(0).getType()); | ||
138 | + Assert.assertEquals("typeB", assetTypes.get(1).getType()); | ||
139 | + Assert.assertEquals("typeC", assetTypes.get(2).getType()); | ||
140 | + } | ||
141 | + | ||
142 | + @Test | ||
143 | + public void testDeleteAsset() throws Exception { | ||
144 | + Asset asset = new Asset(); | ||
145 | + asset.setName("My asset"); | ||
146 | + asset.setType("default"); | ||
147 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
148 | + | ||
149 | + doDelete("/api/asset/"+savedAsset.getId().getId().toString()) | ||
150 | + .andExpect(status().isOk()); | ||
151 | + | ||
152 | + doGet("/api/asset/"+savedAsset.getId().getId().toString()) | ||
153 | + .andExpect(status().isNotFound()); | ||
154 | + } | ||
155 | + | ||
156 | + @Test | ||
157 | + public void testSaveAssetWithEmptyType() throws Exception { | ||
158 | + Asset asset = new Asset(); | ||
159 | + asset.setName("My asset"); | ||
160 | + doPost("/api/asset", asset) | ||
161 | + .andExpect(status().isBadRequest()) | ||
162 | + .andExpect(statusReason(containsString("Asset type should be specified"))); | ||
163 | + } | ||
164 | + | ||
165 | + @Test | ||
166 | + public void testSaveAssetWithEmptyName() throws Exception { | ||
167 | + Asset asset = new Asset(); | ||
168 | + asset.setType("default"); | ||
169 | + doPost("/api/asset", asset) | ||
170 | + .andExpect(status().isBadRequest()) | ||
171 | + .andExpect(statusReason(containsString("Asset name should be specified"))); | ||
172 | + } | ||
173 | + | ||
174 | + @Test | ||
175 | + public void testAssignUnassignAssetToCustomer() throws Exception { | ||
176 | + Asset asset = new Asset(); | ||
177 | + asset.setName("My asset"); | ||
178 | + asset.setType("default"); | ||
179 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
180 | + | ||
181 | + Customer customer = new Customer(); | ||
182 | + customer.setTitle("My customer"); | ||
183 | + Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | ||
184 | + | ||
185 | + Asset assignedAsset = doPost("/api/customer/" + savedCustomer.getId().getId().toString() | ||
186 | + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
187 | + Assert.assertEquals(savedCustomer.getId(), assignedAsset.getCustomerId()); | ||
188 | + | ||
189 | + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
190 | + Assert.assertEquals(savedCustomer.getId(), foundAsset.getCustomerId()); | ||
191 | + | ||
192 | + Asset unassignedAsset = | ||
193 | + doDelete("/api/customer/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
194 | + Assert.assertEquals(ModelConstants.NULL_UUID, unassignedAsset.getCustomerId().getId()); | ||
195 | + | ||
196 | + foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); | ||
197 | + Assert.assertEquals(ModelConstants.NULL_UUID, foundAsset.getCustomerId().getId()); | ||
198 | + } | ||
199 | + | ||
200 | + @Test | ||
201 | + public void testAssignAssetToNonExistentCustomer() throws Exception { | ||
202 | + Asset asset = new Asset(); | ||
203 | + asset.setName("My asset"); | ||
204 | + asset.setType("default"); | ||
205 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
206 | + | ||
207 | + doPost("/api/customer/" + UUIDs.timeBased().toString() | ||
208 | + + "/asset/" + savedAsset.getId().getId().toString()) | ||
209 | + .andExpect(status().isNotFound()); | ||
210 | + } | ||
211 | + | ||
212 | + @Test | ||
213 | + public void testAssignAssetToCustomerFromDifferentTenant() throws Exception { | ||
214 | + loginSysAdmin(); | ||
215 | + | ||
216 | + Tenant tenant2 = new Tenant(); | ||
217 | + tenant2.setTitle("Different tenant"); | ||
218 | + Tenant savedTenant2 = doPost("/api/tenant", tenant2, Tenant.class); | ||
219 | + Assert.assertNotNull(savedTenant2); | ||
220 | + | ||
221 | + User tenantAdmin2 = new User(); | ||
222 | + tenantAdmin2.setAuthority(Authority.TENANT_ADMIN); | ||
223 | + tenantAdmin2.setTenantId(savedTenant2.getId()); | ||
224 | + tenantAdmin2.setEmail("tenant3@thingsboard.org"); | ||
225 | + tenantAdmin2.setFirstName("Joe"); | ||
226 | + tenantAdmin2.setLastName("Downs"); | ||
227 | + | ||
228 | + tenantAdmin2 = createUserAndLogin(tenantAdmin2, "testPassword1"); | ||
229 | + | ||
230 | + Customer customer = new Customer(); | ||
231 | + customer.setTitle("Different customer"); | ||
232 | + Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | ||
233 | + | ||
234 | + login(tenantAdmin.getEmail(), "testPassword1"); | ||
235 | + | ||
236 | + Asset asset = new Asset(); | ||
237 | + asset.setName("My asset"); | ||
238 | + asset.setType("default"); | ||
239 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
240 | + | ||
241 | + doPost("/api/customer/" + savedCustomer.getId().getId().toString() | ||
242 | + + "/asset/" + savedAsset.getId().getId().toString()) | ||
243 | + .andExpect(status().isForbidden()); | ||
244 | + | ||
245 | + loginSysAdmin(); | ||
246 | + | ||
247 | + doDelete("/api/tenant/"+savedTenant2.getId().getId().toString()) | ||
248 | + .andExpect(status().isOk()); | ||
249 | + } | ||
250 | + | ||
251 | + @Test | ||
252 | + public void testFindTenantAssets() throws Exception { | ||
253 | + List<Asset> assets = new ArrayList<>(); | ||
254 | + for (int i=0;i<178;i++) { | ||
255 | + Asset asset = new Asset(); | ||
256 | + asset.setName("Asset"+i); | ||
257 | + asset.setType("default"); | ||
258 | + assets.add(doPost("/api/asset", asset, Asset.class)); | ||
259 | + } | ||
260 | + List<Asset> loadedAssets = new ArrayList<>(); | ||
261 | + TextPageLink pageLink = new TextPageLink(23); | ||
262 | + TextPageData<Asset> pageData = null; | ||
263 | + do { | ||
264 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?", | ||
265 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
266 | + loadedAssets.addAll(pageData.getData()); | ||
267 | + if (pageData.hasNext()) { | ||
268 | + pageLink = pageData.getNextPageLink(); | ||
269 | + } | ||
270 | + } while (pageData.hasNext()); | ||
271 | + | ||
272 | + Collections.sort(assets, idComparator); | ||
273 | + Collections.sort(loadedAssets, idComparator); | ||
274 | + | ||
275 | + Assert.assertEquals(assets, loadedAssets); | ||
276 | + } | ||
277 | + | ||
278 | + @Test | ||
279 | + public void testFindTenantAssetsByName() throws Exception { | ||
280 | + String title1 = "Asset title 1"; | ||
281 | + List<Asset> assetsTitle1 = new ArrayList<>(); | ||
282 | + for (int i=0;i<143;i++) { | ||
283 | + Asset asset = new Asset(); | ||
284 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
285 | + String name = title1+suffix; | ||
286 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
287 | + asset.setName(name); | ||
288 | + asset.setType("default"); | ||
289 | + assetsTitle1.add(doPost("/api/asset", asset, Asset.class)); | ||
290 | + } | ||
291 | + String title2 = "Asset title 2"; | ||
292 | + List<Asset> assetsTitle2 = new ArrayList<>(); | ||
293 | + for (int i=0;i<75;i++) { | ||
294 | + Asset asset = new Asset(); | ||
295 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
296 | + String name = title2+suffix; | ||
297 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
298 | + asset.setName(name); | ||
299 | + asset.setType("default"); | ||
300 | + assetsTitle2.add(doPost("/api/asset", asset, Asset.class)); | ||
301 | + } | ||
302 | + | ||
303 | + List<Asset> loadedAssetsTitle1 = new ArrayList<>(); | ||
304 | + TextPageLink pageLink = new TextPageLink(15, title1); | ||
305 | + TextPageData<Asset> pageData = null; | ||
306 | + do { | ||
307 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?", | ||
308 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
309 | + loadedAssetsTitle1.addAll(pageData.getData()); | ||
310 | + if (pageData.hasNext()) { | ||
311 | + pageLink = pageData.getNextPageLink(); | ||
312 | + } | ||
313 | + } while (pageData.hasNext()); | ||
314 | + | ||
315 | + Collections.sort(assetsTitle1, idComparator); | ||
316 | + Collections.sort(loadedAssetsTitle1, idComparator); | ||
317 | + | ||
318 | + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); | ||
319 | + | ||
320 | + List<Asset> loadedAssetsTitle2 = new ArrayList<>(); | ||
321 | + pageLink = new TextPageLink(4, title2); | ||
322 | + do { | ||
323 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?", | ||
324 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
325 | + loadedAssetsTitle2.addAll(pageData.getData()); | ||
326 | + if (pageData.hasNext()) { | ||
327 | + pageLink = pageData.getNextPageLink(); | ||
328 | + } | ||
329 | + } while (pageData.hasNext()); | ||
330 | + | ||
331 | + Collections.sort(assetsTitle2, idComparator); | ||
332 | + Collections.sort(loadedAssetsTitle2, idComparator); | ||
333 | + | ||
334 | + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2); | ||
335 | + | ||
336 | + for (Asset asset : loadedAssetsTitle1) { | ||
337 | + doDelete("/api/asset/"+asset.getId().getId().toString()) | ||
338 | + .andExpect(status().isOk()); | ||
339 | + } | ||
340 | + | ||
341 | + pageLink = new TextPageLink(4, title1); | ||
342 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?", | ||
343 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
344 | + Assert.assertFalse(pageData.hasNext()); | ||
345 | + Assert.assertEquals(0, pageData.getData().size()); | ||
346 | + | ||
347 | + for (Asset asset : loadedAssetsTitle2) { | ||
348 | + doDelete("/api/asset/"+asset.getId().getId().toString()) | ||
349 | + .andExpect(status().isOk()); | ||
350 | + } | ||
351 | + | ||
352 | + pageLink = new TextPageLink(4, title2); | ||
353 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?", | ||
354 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
355 | + Assert.assertFalse(pageData.hasNext()); | ||
356 | + Assert.assertEquals(0, pageData.getData().size()); | ||
357 | + } | ||
358 | + | ||
359 | + @Test | ||
360 | + public void testFindTenantAssetsByType() throws Exception { | ||
361 | + String title1 = "Asset title 1"; | ||
362 | + String type1 = "typeA"; | ||
363 | + List<Asset> assetsType1 = new ArrayList<>(); | ||
364 | + for (int i=0;i<143;i++) { | ||
365 | + Asset asset = new Asset(); | ||
366 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
367 | + String name = title1+suffix; | ||
368 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
369 | + asset.setName(name); | ||
370 | + asset.setType(type1); | ||
371 | + assetsType1.add(doPost("/api/asset", asset, Asset.class)); | ||
372 | + } | ||
373 | + String title2 = "Asset title 2"; | ||
374 | + String type2 = "typeB"; | ||
375 | + List<Asset> assetsType2 = new ArrayList<>(); | ||
376 | + for (int i=0;i<75;i++) { | ||
377 | + Asset asset = new Asset(); | ||
378 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
379 | + String name = title2+suffix; | ||
380 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
381 | + asset.setName(name); | ||
382 | + asset.setType(type2); | ||
383 | + assetsType2.add(doPost("/api/asset", asset, Asset.class)); | ||
384 | + } | ||
385 | + | ||
386 | + List<Asset> loadedAssetsType1 = new ArrayList<>(); | ||
387 | + TextPageLink pageLink = new TextPageLink(15); | ||
388 | + TextPageData<Asset> pageData = null; | ||
389 | + do { | ||
390 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | ||
391 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | ||
392 | + loadedAssetsType1.addAll(pageData.getData()); | ||
393 | + if (pageData.hasNext()) { | ||
394 | + pageLink = pageData.getNextPageLink(); | ||
395 | + } | ||
396 | + } while (pageData.hasNext()); | ||
397 | + | ||
398 | + Collections.sort(assetsType1, idComparator); | ||
399 | + Collections.sort(loadedAssetsType1, idComparator); | ||
400 | + | ||
401 | + Assert.assertEquals(assetsType1, loadedAssetsType1); | ||
402 | + | ||
403 | + List<Asset> loadedAssetsType2 = new ArrayList<>(); | ||
404 | + pageLink = new TextPageLink(4); | ||
405 | + do { | ||
406 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | ||
407 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | ||
408 | + loadedAssetsType2.addAll(pageData.getData()); | ||
409 | + if (pageData.hasNext()) { | ||
410 | + pageLink = pageData.getNextPageLink(); | ||
411 | + } | ||
412 | + } while (pageData.hasNext()); | ||
413 | + | ||
414 | + Collections.sort(assetsType2, idComparator); | ||
415 | + Collections.sort(loadedAssetsType2, idComparator); | ||
416 | + | ||
417 | + Assert.assertEquals(assetsType2, loadedAssetsType2); | ||
418 | + | ||
419 | + for (Asset asset : loadedAssetsType1) { | ||
420 | + doDelete("/api/asset/"+asset.getId().getId().toString()) | ||
421 | + .andExpect(status().isOk()); | ||
422 | + } | ||
423 | + | ||
424 | + pageLink = new TextPageLink(4); | ||
425 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | ||
426 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | ||
427 | + Assert.assertFalse(pageData.hasNext()); | ||
428 | + Assert.assertEquals(0, pageData.getData().size()); | ||
429 | + | ||
430 | + for (Asset asset : loadedAssetsType2) { | ||
431 | + doDelete("/api/asset/"+asset.getId().getId().toString()) | ||
432 | + .andExpect(status().isOk()); | ||
433 | + } | ||
434 | + | ||
435 | + pageLink = new TextPageLink(4); | ||
436 | + pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | ||
437 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | ||
438 | + Assert.assertFalse(pageData.hasNext()); | ||
439 | + Assert.assertEquals(0, pageData.getData().size()); | ||
440 | + } | ||
441 | + | ||
442 | + @Test | ||
443 | + public void testFindCustomerAssets() throws Exception { | ||
444 | + Customer customer = new Customer(); | ||
445 | + customer.setTitle("Test customer"); | ||
446 | + customer = doPost("/api/customer", customer, Customer.class); | ||
447 | + CustomerId customerId = customer.getId(); | ||
448 | + | ||
449 | + List<Asset> assets = new ArrayList<>(); | ||
450 | + for (int i=0;i<128;i++) { | ||
451 | + Asset asset = new Asset(); | ||
452 | + asset.setName("Asset"+i); | ||
453 | + asset.setType("default"); | ||
454 | + asset = doPost("/api/asset", asset, Asset.class); | ||
455 | + assets.add(doPost("/api/customer/" + customerId.getId().toString() | ||
456 | + + "/asset/" + asset.getId().getId().toString(), Asset.class)); | ||
457 | + } | ||
458 | + | ||
459 | + List<Asset> loadedAssets = new ArrayList<>(); | ||
460 | + TextPageLink pageLink = new TextPageLink(23); | ||
461 | + TextPageData<Asset> pageData = null; | ||
462 | + do { | ||
463 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | ||
464 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
465 | + loadedAssets.addAll(pageData.getData()); | ||
466 | + if (pageData.hasNext()) { | ||
467 | + pageLink = pageData.getNextPageLink(); | ||
468 | + } | ||
469 | + } while (pageData.hasNext()); | ||
470 | + | ||
471 | + Collections.sort(assets, idComparator); | ||
472 | + Collections.sort(loadedAssets, idComparator); | ||
473 | + | ||
474 | + Assert.assertEquals(assets, loadedAssets); | ||
475 | + } | ||
476 | + | ||
477 | + @Test | ||
478 | + public void testFindCustomerAssetsByName() throws Exception { | ||
479 | + Customer customer = new Customer(); | ||
480 | + customer.setTitle("Test customer"); | ||
481 | + customer = doPost("/api/customer", customer, Customer.class); | ||
482 | + CustomerId customerId = customer.getId(); | ||
483 | + | ||
484 | + String title1 = "Asset title 1"; | ||
485 | + List<Asset> assetsTitle1 = new ArrayList<>(); | ||
486 | + for (int i=0;i<125;i++) { | ||
487 | + Asset asset = new Asset(); | ||
488 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
489 | + String name = title1+suffix; | ||
490 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
491 | + asset.setName(name); | ||
492 | + asset.setType("default"); | ||
493 | + asset = doPost("/api/asset", asset, Asset.class); | ||
494 | + assetsTitle1.add(doPost("/api/customer/" + customerId.getId().toString() | ||
495 | + + "/asset/" + asset.getId().getId().toString(), Asset.class)); | ||
496 | + } | ||
497 | + String title2 = "Asset title 2"; | ||
498 | + List<Asset> assetsTitle2 = new ArrayList<>(); | ||
499 | + for (int i=0;i<143;i++) { | ||
500 | + Asset asset = new Asset(); | ||
501 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
502 | + String name = title2+suffix; | ||
503 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
504 | + asset.setName(name); | ||
505 | + asset.setType("default"); | ||
506 | + asset = doPost("/api/asset", asset, Asset.class); | ||
507 | + assetsTitle2.add(doPost("/api/customer/" + customerId.getId().toString() | ||
508 | + + "/asset/" + asset.getId().getId().toString(), Asset.class)); | ||
509 | + } | ||
510 | + | ||
511 | + List<Asset> loadedAssetsTitle1 = new ArrayList<>(); | ||
512 | + TextPageLink pageLink = new TextPageLink(15, title1); | ||
513 | + TextPageData<Asset> pageData = null; | ||
514 | + do { | ||
515 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | ||
516 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
517 | + loadedAssetsTitle1.addAll(pageData.getData()); | ||
518 | + if (pageData.hasNext()) { | ||
519 | + pageLink = pageData.getNextPageLink(); | ||
520 | + } | ||
521 | + } while (pageData.hasNext()); | ||
522 | + | ||
523 | + Collections.sort(assetsTitle1, idComparator); | ||
524 | + Collections.sort(loadedAssetsTitle1, idComparator); | ||
525 | + | ||
526 | + Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); | ||
527 | + | ||
528 | + List<Asset> loadedAssetsTitle2 = new ArrayList<>(); | ||
529 | + pageLink = new TextPageLink(4, title2); | ||
530 | + do { | ||
531 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | ||
532 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
533 | + loadedAssetsTitle2.addAll(pageData.getData()); | ||
534 | + if (pageData.hasNext()) { | ||
535 | + pageLink = pageData.getNextPageLink(); | ||
536 | + } | ||
537 | + } while (pageData.hasNext()); | ||
538 | + | ||
539 | + Collections.sort(assetsTitle2, idComparator); | ||
540 | + Collections.sort(loadedAssetsTitle2, idComparator); | ||
541 | + | ||
542 | + Assert.assertEquals(assetsTitle2, loadedAssetsTitle2); | ||
543 | + | ||
544 | + for (Asset asset : loadedAssetsTitle1) { | ||
545 | + doDelete("/api/customer/asset/" + asset.getId().getId().toString()) | ||
546 | + .andExpect(status().isOk()); | ||
547 | + } | ||
548 | + | ||
549 | + pageLink = new TextPageLink(4, title1); | ||
550 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | ||
551 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
552 | + Assert.assertFalse(pageData.hasNext()); | ||
553 | + Assert.assertEquals(0, pageData.getData().size()); | ||
554 | + | ||
555 | + for (Asset asset : loadedAssetsTitle2) { | ||
556 | + doDelete("/api/customer/asset/" + asset.getId().getId().toString()) | ||
557 | + .andExpect(status().isOk()); | ||
558 | + } | ||
559 | + | ||
560 | + pageLink = new TextPageLink(4, title2); | ||
561 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | ||
562 | + new TypeReference<TextPageData<Asset>>(){}, pageLink); | ||
563 | + Assert.assertFalse(pageData.hasNext()); | ||
564 | + Assert.assertEquals(0, pageData.getData().size()); | ||
565 | + } | ||
566 | + | ||
567 | + @Test | ||
568 | + public void testFindCustomerAssetsByType() throws Exception { | ||
569 | + Customer customer = new Customer(); | ||
570 | + customer.setTitle("Test customer"); | ||
571 | + customer = doPost("/api/customer", customer, Customer.class); | ||
572 | + CustomerId customerId = customer.getId(); | ||
573 | + | ||
574 | + String title1 = "Asset title 1"; | ||
575 | + String type1 = "typeC"; | ||
576 | + List<Asset> assetsType1 = new ArrayList<>(); | ||
577 | + for (int i=0;i<125;i++) { | ||
578 | + Asset asset = new Asset(); | ||
579 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
580 | + String name = title1+suffix; | ||
581 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
582 | + asset.setName(name); | ||
583 | + asset.setType(type1); | ||
584 | + asset = doPost("/api/asset", asset, Asset.class); | ||
585 | + assetsType1.add(doPost("/api/customer/" + customerId.getId().toString() | ||
586 | + + "/asset/" + asset.getId().getId().toString(), Asset.class)); | ||
587 | + } | ||
588 | + String title2 = "Asset title 2"; | ||
589 | + String type2 = "typeD"; | ||
590 | + List<Asset> assetsType2 = new ArrayList<>(); | ||
591 | + for (int i=0;i<143;i++) { | ||
592 | + Asset asset = new Asset(); | ||
593 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
594 | + String name = title2+suffix; | ||
595 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
596 | + asset.setName(name); | ||
597 | + asset.setType(type2); | ||
598 | + asset = doPost("/api/asset", asset, Asset.class); | ||
599 | + assetsType2.add(doPost("/api/customer/" + customerId.getId().toString() | ||
600 | + + "/asset/" + asset.getId().getId().toString(), Asset.class)); | ||
601 | + } | ||
602 | + | ||
603 | + List<Asset> loadedAssetsType1 = new ArrayList<>(); | ||
604 | + TextPageLink pageLink = new TextPageLink(15); | ||
605 | + TextPageData<Asset> pageData = null; | ||
606 | + do { | ||
607 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | ||
608 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | ||
609 | + loadedAssetsType1.addAll(pageData.getData()); | ||
610 | + if (pageData.hasNext()) { | ||
611 | + pageLink = pageData.getNextPageLink(); | ||
612 | + } | ||
613 | + } while (pageData.hasNext()); | ||
614 | + | ||
615 | + Collections.sort(assetsType1, idComparator); | ||
616 | + Collections.sort(loadedAssetsType1, idComparator); | ||
617 | + | ||
618 | + Assert.assertEquals(assetsType1, loadedAssetsType1); | ||
619 | + | ||
620 | + List<Asset> loadedAssetsType2 = new ArrayList<>(); | ||
621 | + pageLink = new TextPageLink(4); | ||
622 | + do { | ||
623 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | ||
624 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | ||
625 | + loadedAssetsType2.addAll(pageData.getData()); | ||
626 | + if (pageData.hasNext()) { | ||
627 | + pageLink = pageData.getNextPageLink(); | ||
628 | + } | ||
629 | + } while (pageData.hasNext()); | ||
630 | + | ||
631 | + Collections.sort(assetsType2, idComparator); | ||
632 | + Collections.sort(loadedAssetsType2, idComparator); | ||
633 | + | ||
634 | + Assert.assertEquals(assetsType2, loadedAssetsType2); | ||
635 | + | ||
636 | + for (Asset asset : loadedAssetsType1) { | ||
637 | + doDelete("/api/customer/asset/" + asset.getId().getId().toString()) | ||
638 | + .andExpect(status().isOk()); | ||
639 | + } | ||
640 | + | ||
641 | + pageLink = new TextPageLink(4); | ||
642 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | ||
643 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | ||
644 | + Assert.assertFalse(pageData.hasNext()); | ||
645 | + Assert.assertEquals(0, pageData.getData().size()); | ||
646 | + | ||
647 | + for (Asset asset : loadedAssetsType2) { | ||
648 | + doDelete("/api/customer/asset/" + asset.getId().getId().toString()) | ||
649 | + .andExpect(status().isOk()); | ||
650 | + } | ||
651 | + | ||
652 | + pageLink = new TextPageLink(4); | ||
653 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | ||
654 | + new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | ||
655 | + Assert.assertFalse(pageData.hasNext()); | ||
656 | + Assert.assertEquals(0, pageData.getData().size()); | ||
657 | + } | ||
658 | + | ||
659 | +} |
@@ -24,10 +24,7 @@ import java.util.Collections; | @@ -24,10 +24,7 @@ import java.util.Collections; | ||
24 | import java.util.List; | 24 | import java.util.List; |
25 | 25 | ||
26 | import org.apache.commons.lang3.RandomStringUtils; | 26 | import org.apache.commons.lang3.RandomStringUtils; |
27 | -import org.thingsboard.server.common.data.Customer; | ||
28 | -import org.thingsboard.server.common.data.Device; | ||
29 | -import org.thingsboard.server.common.data.Tenant; | ||
30 | -import org.thingsboard.server.common.data.User; | 27 | +import org.thingsboard.server.common.data.*; |
31 | import org.thingsboard.server.common.data.id.CustomerId; | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
32 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; | 29 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; |
33 | import org.thingsboard.server.common.data.id.DeviceId; | 30 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -83,6 +80,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -83,6 +80,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
83 | public void testSaveDevice() throws Exception { | 80 | public void testSaveDevice() throws Exception { |
84 | Device device = new Device(); | 81 | Device device = new Device(); |
85 | device.setName("My device"); | 82 | device.setName("My device"); |
83 | + device.setType("default"); | ||
86 | Device savedDevice = doPost("/api/device", device, Device.class); | 84 | Device savedDevice = doPost("/api/device", device, Device.class); |
87 | 85 | ||
88 | Assert.assertNotNull(savedDevice); | 86 | Assert.assertNotNull(savedDevice); |
@@ -114,16 +112,49 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -114,16 +112,49 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
114 | public void testFindDeviceById() throws Exception { | 112 | public void testFindDeviceById() throws Exception { |
115 | Device device = new Device(); | 113 | Device device = new Device(); |
116 | device.setName("My device"); | 114 | device.setName("My device"); |
115 | + device.setType("default"); | ||
117 | Device savedDevice = doPost("/api/device", device, Device.class); | 116 | Device savedDevice = doPost("/api/device", device, Device.class); |
118 | Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); | 117 | Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); |
119 | Assert.assertNotNull(foundDevice); | 118 | Assert.assertNotNull(foundDevice); |
120 | Assert.assertEquals(savedDevice, foundDevice); | 119 | Assert.assertEquals(savedDevice, foundDevice); |
121 | } | 120 | } |
121 | + | ||
122 | + @Test | ||
123 | + public void testFindDeviceTypesByTenantId() throws Exception { | ||
124 | + List<Device> devices = new ArrayList<>(); | ||
125 | + for (int i=0;i<3;i++) { | ||
126 | + Device device = new Device(); | ||
127 | + device.setName("My device B"+i); | ||
128 | + device.setType("typeB"); | ||
129 | + devices.add(doPost("/api/device", device, Device.class)); | ||
130 | + } | ||
131 | + for (int i=0;i<7;i++) { | ||
132 | + Device device = new Device(); | ||
133 | + device.setName("My device C"+i); | ||
134 | + device.setType("typeC"); | ||
135 | + devices.add(doPost("/api/device", device, Device.class)); | ||
136 | + } | ||
137 | + for (int i=0;i<9;i++) { | ||
138 | + Device device = new Device(); | ||
139 | + device.setName("My device A"+i); | ||
140 | + device.setType("typeA"); | ||
141 | + devices.add(doPost("/api/device", device, Device.class)); | ||
142 | + } | ||
143 | + List<TenantDeviceType> deviceTypes = doGetTyped("/api/device/types", | ||
144 | + new TypeReference<List<TenantDeviceType>>(){}); | ||
145 | + | ||
146 | + Assert.assertNotNull(deviceTypes); | ||
147 | + Assert.assertEquals(3, deviceTypes.size()); | ||
148 | + Assert.assertEquals("typeA", deviceTypes.get(0).getType()); | ||
149 | + Assert.assertEquals("typeB", deviceTypes.get(1).getType()); | ||
150 | + Assert.assertEquals("typeC", deviceTypes.get(2).getType()); | ||
151 | + } | ||
122 | 152 | ||
123 | @Test | 153 | @Test |
124 | public void testDeleteDevice() throws Exception { | 154 | public void testDeleteDevice() throws Exception { |
125 | Device device = new Device(); | 155 | Device device = new Device(); |
126 | device.setName("My device"); | 156 | device.setName("My device"); |
157 | + device.setType("default"); | ||
127 | Device savedDevice = doPost("/api/device", device, Device.class); | 158 | Device savedDevice = doPost("/api/device", device, Device.class); |
128 | 159 | ||
129 | doDelete("/api/device/"+savedDevice.getId().getId().toString()) | 160 | doDelete("/api/device/"+savedDevice.getId().getId().toString()) |
@@ -132,10 +163,20 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -132,10 +163,20 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
132 | doGet("/api/device/"+savedDevice.getId().getId().toString()) | 163 | doGet("/api/device/"+savedDevice.getId().getId().toString()) |
133 | .andExpect(status().isNotFound()); | 164 | .andExpect(status().isNotFound()); |
134 | } | 165 | } |
135 | - | 166 | + |
167 | + @Test | ||
168 | + public void testSaveDeviceWithEmptyType() throws Exception { | ||
169 | + Device device = new Device(); | ||
170 | + device.setName("My device"); | ||
171 | + doPost("/api/device", device) | ||
172 | + .andExpect(status().isBadRequest()) | ||
173 | + .andExpect(statusReason(containsString("Device type should be specified"))); | ||
174 | + } | ||
175 | + | ||
136 | @Test | 176 | @Test |
137 | public void testSaveDeviceWithEmptyName() throws Exception { | 177 | public void testSaveDeviceWithEmptyName() throws Exception { |
138 | Device device = new Device(); | 178 | Device device = new Device(); |
179 | + device.setType("default"); | ||
139 | doPost("/api/device", device) | 180 | doPost("/api/device", device) |
140 | .andExpect(status().isBadRequest()) | 181 | .andExpect(status().isBadRequest()) |
141 | .andExpect(statusReason(containsString("Device name should be specified"))); | 182 | .andExpect(statusReason(containsString("Device name should be specified"))); |
@@ -145,6 +186,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -145,6 +186,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
145 | public void testAssignUnassignDeviceToCustomer() throws Exception { | 186 | public void testAssignUnassignDeviceToCustomer() throws Exception { |
146 | Device device = new Device(); | 187 | Device device = new Device(); |
147 | device.setName("My device"); | 188 | device.setName("My device"); |
189 | + device.setType("default"); | ||
148 | Device savedDevice = doPost("/api/device", device, Device.class); | 190 | Device savedDevice = doPost("/api/device", device, Device.class); |
149 | 191 | ||
150 | Customer customer = new Customer(); | 192 | Customer customer = new Customer(); |
@@ -170,6 +212,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -170,6 +212,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
170 | public void testAssignDeviceToNonExistentCustomer() throws Exception { | 212 | public void testAssignDeviceToNonExistentCustomer() throws Exception { |
171 | Device device = new Device(); | 213 | Device device = new Device(); |
172 | device.setName("My device"); | 214 | device.setName("My device"); |
215 | + device.setType("default"); | ||
173 | Device savedDevice = doPost("/api/device", device, Device.class); | 216 | Device savedDevice = doPost("/api/device", device, Device.class); |
174 | 217 | ||
175 | doPost("/api/customer/" + UUIDs.timeBased().toString() | 218 | doPost("/api/customer/" + UUIDs.timeBased().toString() |
@@ -203,6 +246,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -203,6 +246,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
203 | 246 | ||
204 | Device device = new Device(); | 247 | Device device = new Device(); |
205 | device.setName("My device"); | 248 | device.setName("My device"); |
249 | + device.setType("default"); | ||
206 | Device savedDevice = doPost("/api/device", device, Device.class); | 250 | Device savedDevice = doPost("/api/device", device, Device.class); |
207 | 251 | ||
208 | doPost("/api/customer/" + savedCustomer.getId().getId().toString() | 252 | doPost("/api/customer/" + savedCustomer.getId().getId().toString() |
@@ -219,6 +263,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -219,6 +263,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
219 | public void testFindDeviceCredentialsByDeviceId() throws Exception { | 263 | public void testFindDeviceCredentialsByDeviceId() throws Exception { |
220 | Device device = new Device(); | 264 | Device device = new Device(); |
221 | device.setName("My device"); | 265 | device.setName("My device"); |
266 | + device.setType("default"); | ||
222 | Device savedDevice = doPost("/api/device", device, Device.class); | 267 | Device savedDevice = doPost("/api/device", device, Device.class); |
223 | DeviceCredentials deviceCredentials = | 268 | DeviceCredentials deviceCredentials = |
224 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 269 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -229,6 +274,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -229,6 +274,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
229 | public void testSaveDeviceCredentials() throws Exception { | 274 | public void testSaveDeviceCredentials() throws Exception { |
230 | Device device = new Device(); | 275 | Device device = new Device(); |
231 | device.setName("My device"); | 276 | device.setName("My device"); |
277 | + device.setType("default"); | ||
232 | Device savedDevice = doPost("/api/device", device, Device.class); | 278 | Device savedDevice = doPost("/api/device", device, Device.class); |
233 | DeviceCredentials deviceCredentials = | 279 | DeviceCredentials deviceCredentials = |
234 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 280 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -255,6 +301,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -255,6 +301,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
255 | public void testSaveDeviceCredentialsWithEmptyCredentialsType() throws Exception { | 301 | public void testSaveDeviceCredentialsWithEmptyCredentialsType() throws Exception { |
256 | Device device = new Device(); | 302 | Device device = new Device(); |
257 | device.setName("My device"); | 303 | device.setName("My device"); |
304 | + device.setType("default"); | ||
258 | Device savedDevice = doPost("/api/device", device, Device.class); | 305 | Device savedDevice = doPost("/api/device", device, Device.class); |
259 | DeviceCredentials deviceCredentials = | 306 | DeviceCredentials deviceCredentials = |
260 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 307 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -268,6 +315,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -268,6 +315,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
268 | public void testSaveDeviceCredentialsWithEmptyCredentialsId() throws Exception { | 315 | public void testSaveDeviceCredentialsWithEmptyCredentialsId() throws Exception { |
269 | Device device = new Device(); | 316 | Device device = new Device(); |
270 | device.setName("My device"); | 317 | device.setName("My device"); |
318 | + device.setType("default"); | ||
271 | Device savedDevice = doPost("/api/device", device, Device.class); | 319 | Device savedDevice = doPost("/api/device", device, Device.class); |
272 | DeviceCredentials deviceCredentials = | 320 | DeviceCredentials deviceCredentials = |
273 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 321 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -281,6 +329,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -281,6 +329,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
281 | public void testSaveNonExistentDeviceCredentials() throws Exception { | 329 | public void testSaveNonExistentDeviceCredentials() throws Exception { |
282 | Device device = new Device(); | 330 | Device device = new Device(); |
283 | device.setName("My device"); | 331 | device.setName("My device"); |
332 | + device.setType("default"); | ||
284 | Device savedDevice = doPost("/api/device", device, Device.class); | 333 | Device savedDevice = doPost("/api/device", device, Device.class); |
285 | DeviceCredentials deviceCredentials = | 334 | DeviceCredentials deviceCredentials = |
286 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 335 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -298,6 +347,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -298,6 +347,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
298 | public void testSaveDeviceCredentialsWithNonExistentDevice() throws Exception { | 347 | public void testSaveDeviceCredentialsWithNonExistentDevice() throws Exception { |
299 | Device device = new Device(); | 348 | Device device = new Device(); |
300 | device.setName("My device"); | 349 | device.setName("My device"); |
350 | + device.setType("default"); | ||
301 | Device savedDevice = doPost("/api/device", device, Device.class); | 351 | Device savedDevice = doPost("/api/device", device, Device.class); |
302 | DeviceCredentials deviceCredentials = | 352 | DeviceCredentials deviceCredentials = |
303 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 353 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -307,9 +357,10 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -307,9 +357,10 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
307 | } | 357 | } |
308 | 358 | ||
309 | @Test | 359 | @Test |
310 | - public void testSaveDeviceCredentialsWithInvalidCredemtialsIdLength() throws Exception { | 360 | + public void testSaveDeviceCredentialsWithInvalidCredentialsIdLength() throws Exception { |
311 | Device device = new Device(); | 361 | Device device = new Device(); |
312 | device.setName("My device"); | 362 | device.setName("My device"); |
363 | + device.setType("default"); | ||
313 | Device savedDevice = doPost("/api/device", device, Device.class); | 364 | Device savedDevice = doPost("/api/device", device, Device.class); |
314 | DeviceCredentials deviceCredentials = | 365 | DeviceCredentials deviceCredentials = |
315 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | 366 | doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
@@ -325,6 +376,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -325,6 +376,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
325 | for (int i=0;i<178;i++) { | 376 | for (int i=0;i<178;i++) { |
326 | Device device = new Device(); | 377 | Device device = new Device(); |
327 | device.setName("Device"+i); | 378 | device.setName("Device"+i); |
379 | + device.setType("default"); | ||
328 | devices.add(doPost("/api/device", device, Device.class)); | 380 | devices.add(doPost("/api/device", device, Device.class)); |
329 | } | 381 | } |
330 | List<Device> loadedDevices = new ArrayList<>(); | 382 | List<Device> loadedDevices = new ArrayList<>(); |
@@ -355,6 +407,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -355,6 +407,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
355 | String name = title1+suffix; | 407 | String name = title1+suffix; |
356 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | 408 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
357 | device.setName(name); | 409 | device.setName(name); |
410 | + device.setType("default"); | ||
358 | devicesTitle1.add(doPost("/api/device", device, Device.class)); | 411 | devicesTitle1.add(doPost("/api/device", device, Device.class)); |
359 | } | 412 | } |
360 | String title2 = "Device title 2"; | 413 | String title2 = "Device title 2"; |
@@ -365,6 +418,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -365,6 +418,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
365 | String name = title2+suffix; | 418 | String name = title2+suffix; |
366 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | 419 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
367 | device.setName(name); | 420 | device.setName(name); |
421 | + device.setType("default"); | ||
368 | devicesTitle2.add(doPost("/api/device", device, Device.class)); | 422 | devicesTitle2.add(doPost("/api/device", device, Device.class)); |
369 | } | 423 | } |
370 | 424 | ||
@@ -423,6 +477,89 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -423,6 +477,89 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
423 | Assert.assertFalse(pageData.hasNext()); | 477 | Assert.assertFalse(pageData.hasNext()); |
424 | Assert.assertEquals(0, pageData.getData().size()); | 478 | Assert.assertEquals(0, pageData.getData().size()); |
425 | } | 479 | } |
480 | + | ||
481 | + @Test | ||
482 | + public void testFindTenantDevicesByType() throws Exception { | ||
483 | + String title1 = "Device title 1"; | ||
484 | + String type1 = "typeA"; | ||
485 | + List<Device> devicesType1 = new ArrayList<>(); | ||
486 | + for (int i=0;i<143;i++) { | ||
487 | + Device device = new Device(); | ||
488 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
489 | + String name = title1+suffix; | ||
490 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
491 | + device.setName(name); | ||
492 | + device.setType(type1); | ||
493 | + devicesType1.add(doPost("/api/device", device, Device.class)); | ||
494 | + } | ||
495 | + String title2 = "Device title 2"; | ||
496 | + String type2 = "typeB"; | ||
497 | + List<Device> devicesType2 = new ArrayList<>(); | ||
498 | + for (int i=0;i<75;i++) { | ||
499 | + Device device = new Device(); | ||
500 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
501 | + String name = title2+suffix; | ||
502 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
503 | + device.setName(name); | ||
504 | + device.setType(type2); | ||
505 | + devicesType2.add(doPost("/api/device", device, Device.class)); | ||
506 | + } | ||
507 | + | ||
508 | + List<Device> loadedDevicesType1 = new ArrayList<>(); | ||
509 | + TextPageLink pageLink = new TextPageLink(15); | ||
510 | + TextPageData<Device> pageData = null; | ||
511 | + do { | ||
512 | + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | ||
513 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | ||
514 | + loadedDevicesType1.addAll(pageData.getData()); | ||
515 | + if (pageData.hasNext()) { | ||
516 | + pageLink = pageData.getNextPageLink(); | ||
517 | + } | ||
518 | + } while (pageData.hasNext()); | ||
519 | + | ||
520 | + Collections.sort(devicesType1, idComparator); | ||
521 | + Collections.sort(loadedDevicesType1, idComparator); | ||
522 | + | ||
523 | + Assert.assertEquals(devicesType1, loadedDevicesType1); | ||
524 | + | ||
525 | + List<Device> loadedDevicesType2 = new ArrayList<>(); | ||
526 | + pageLink = new TextPageLink(4); | ||
527 | + do { | ||
528 | + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | ||
529 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | ||
530 | + loadedDevicesType2.addAll(pageData.getData()); | ||
531 | + if (pageData.hasNext()) { | ||
532 | + pageLink = pageData.getNextPageLink(); | ||
533 | + } | ||
534 | + } while (pageData.hasNext()); | ||
535 | + | ||
536 | + Collections.sort(devicesType2, idComparator); | ||
537 | + Collections.sort(loadedDevicesType2, idComparator); | ||
538 | + | ||
539 | + Assert.assertEquals(devicesType2, loadedDevicesType2); | ||
540 | + | ||
541 | + for (Device device : loadedDevicesType1) { | ||
542 | + doDelete("/api/device/"+device.getId().getId().toString()) | ||
543 | + .andExpect(status().isOk()); | ||
544 | + } | ||
545 | + | ||
546 | + pageLink = new TextPageLink(4); | ||
547 | + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | ||
548 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | ||
549 | + Assert.assertFalse(pageData.hasNext()); | ||
550 | + Assert.assertEquals(0, pageData.getData().size()); | ||
551 | + | ||
552 | + for (Device device : loadedDevicesType2) { | ||
553 | + doDelete("/api/device/"+device.getId().getId().toString()) | ||
554 | + .andExpect(status().isOk()); | ||
555 | + } | ||
556 | + | ||
557 | + pageLink = new TextPageLink(4); | ||
558 | + pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | ||
559 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | ||
560 | + Assert.assertFalse(pageData.hasNext()); | ||
561 | + Assert.assertEquals(0, pageData.getData().size()); | ||
562 | + } | ||
426 | 563 | ||
427 | @Test | 564 | @Test |
428 | public void testFindCustomerDevices() throws Exception { | 565 | public void testFindCustomerDevices() throws Exception { |
@@ -435,6 +572,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -435,6 +572,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
435 | for (int i=0;i<128;i++) { | 572 | for (int i=0;i<128;i++) { |
436 | Device device = new Device(); | 573 | Device device = new Device(); |
437 | device.setName("Device"+i); | 574 | device.setName("Device"+i); |
575 | + device.setType("default"); | ||
438 | device = doPost("/api/device", device, Device.class); | 576 | device = doPost("/api/device", device, Device.class); |
439 | devices.add(doPost("/api/customer/" + customerId.getId().toString() | 577 | devices.add(doPost("/api/customer/" + customerId.getId().toString() |
440 | + "/device/" + device.getId().getId().toString(), Device.class)); | 578 | + "/device/" + device.getId().getId().toString(), Device.class)); |
@@ -473,6 +611,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -473,6 +611,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
473 | String name = title1+suffix; | 611 | String name = title1+suffix; |
474 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | 612 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
475 | device.setName(name); | 613 | device.setName(name); |
614 | + device.setType("default"); | ||
476 | device = doPost("/api/device", device, Device.class); | 615 | device = doPost("/api/device", device, Device.class); |
477 | devicesTitle1.add(doPost("/api/customer/" + customerId.getId().toString() | 616 | devicesTitle1.add(doPost("/api/customer/" + customerId.getId().toString() |
478 | + "/device/" + device.getId().getId().toString(), Device.class)); | 617 | + "/device/" + device.getId().getId().toString(), Device.class)); |
@@ -485,6 +624,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -485,6 +624,7 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
485 | String name = title2+suffix; | 624 | String name = title2+suffix; |
486 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | 625 | name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); |
487 | device.setName(name); | 626 | device.setName(name); |
627 | + device.setType("default"); | ||
488 | device = doPost("/api/device", device, Device.class); | 628 | device = doPost("/api/device", device, Device.class); |
489 | devicesTitle2.add(doPost("/api/customer/" + customerId.getId().toString() | 629 | devicesTitle2.add(doPost("/api/customer/" + customerId.getId().toString() |
490 | + "/device/" + device.getId().getId().toString(), Device.class)); | 630 | + "/device/" + device.getId().getId().toString(), Device.class)); |
@@ -546,4 +686,96 @@ public class DeviceControllerTest extends AbstractControllerTest { | @@ -546,4 +686,96 @@ public class DeviceControllerTest extends AbstractControllerTest { | ||
546 | Assert.assertEquals(0, pageData.getData().size()); | 686 | Assert.assertEquals(0, pageData.getData().size()); |
547 | } | 687 | } |
548 | 688 | ||
689 | + @Test | ||
690 | + public void testFindCustomerDevicesByType() throws Exception { | ||
691 | + Customer customer = new Customer(); | ||
692 | + customer.setTitle("Test customer"); | ||
693 | + customer = doPost("/api/customer", customer, Customer.class); | ||
694 | + CustomerId customerId = customer.getId(); | ||
695 | + | ||
696 | + String title1 = "Device title 1"; | ||
697 | + String type1 = "typeC"; | ||
698 | + List<Device> devicesType1 = new ArrayList<>(); | ||
699 | + for (int i=0;i<125;i++) { | ||
700 | + Device device = new Device(); | ||
701 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
702 | + String name = title1+suffix; | ||
703 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
704 | + device.setName(name); | ||
705 | + device.setType(type1); | ||
706 | + device = doPost("/api/device", device, Device.class); | ||
707 | + devicesType1.add(doPost("/api/customer/" + customerId.getId().toString() | ||
708 | + + "/device/" + device.getId().getId().toString(), Device.class)); | ||
709 | + } | ||
710 | + String title2 = "Device title 2"; | ||
711 | + String type2 = "typeD"; | ||
712 | + List<Device> devicesType2 = new ArrayList<>(); | ||
713 | + for (int i=0;i<143;i++) { | ||
714 | + Device device = new Device(); | ||
715 | + String suffix = RandomStringUtils.randomAlphanumeric(15); | ||
716 | + String name = title2+suffix; | ||
717 | + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); | ||
718 | + device.setName(name); | ||
719 | + device.setType(type2); | ||
720 | + device = doPost("/api/device", device, Device.class); | ||
721 | + devicesType2.add(doPost("/api/customer/" + customerId.getId().toString() | ||
722 | + + "/device/" + device.getId().getId().toString(), Device.class)); | ||
723 | + } | ||
724 | + | ||
725 | + List<Device> loadedDevicesType1 = new ArrayList<>(); | ||
726 | + TextPageLink pageLink = new TextPageLink(15); | ||
727 | + TextPageData<Device> pageData = null; | ||
728 | + do { | ||
729 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | ||
730 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | ||
731 | + loadedDevicesType1.addAll(pageData.getData()); | ||
732 | + if (pageData.hasNext()) { | ||
733 | + pageLink = pageData.getNextPageLink(); | ||
734 | + } | ||
735 | + } while (pageData.hasNext()); | ||
736 | + | ||
737 | + Collections.sort(devicesType1, idComparator); | ||
738 | + Collections.sort(loadedDevicesType1, idComparator); | ||
739 | + | ||
740 | + Assert.assertEquals(devicesType1, loadedDevicesType1); | ||
741 | + | ||
742 | + List<Device> loadedDevicesType2 = new ArrayList<>(); | ||
743 | + pageLink = new TextPageLink(4); | ||
744 | + do { | ||
745 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | ||
746 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | ||
747 | + loadedDevicesType2.addAll(pageData.getData()); | ||
748 | + if (pageData.hasNext()) { | ||
749 | + pageLink = pageData.getNextPageLink(); | ||
750 | + } | ||
751 | + } while (pageData.hasNext()); | ||
752 | + | ||
753 | + Collections.sort(devicesType2, idComparator); | ||
754 | + Collections.sort(loadedDevicesType2, idComparator); | ||
755 | + | ||
756 | + Assert.assertEquals(devicesType2, loadedDevicesType2); | ||
757 | + | ||
758 | + for (Device device : loadedDevicesType1) { | ||
759 | + doDelete("/api/customer/device/" + device.getId().getId().toString()) | ||
760 | + .andExpect(status().isOk()); | ||
761 | + } | ||
762 | + | ||
763 | + pageLink = new TextPageLink(4); | ||
764 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | ||
765 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | ||
766 | + Assert.assertFalse(pageData.hasNext()); | ||
767 | + Assert.assertEquals(0, pageData.getData().size()); | ||
768 | + | ||
769 | + for (Device device : loadedDevicesType2) { | ||
770 | + doDelete("/api/customer/device/" + device.getId().getId().toString()) | ||
771 | + .andExpect(status().isOk()); | ||
772 | + } | ||
773 | + | ||
774 | + pageLink = new TextPageLink(4); | ||
775 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | ||
776 | + new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | ||
777 | + Assert.assertFalse(pageData.hasNext()); | ||
778 | + Assert.assertEquals(0, pageData.getData().size()); | ||
779 | + } | ||
780 | + | ||
549 | } | 781 | } |
@@ -130,7 +130,7 @@ public class TenantControllerTest extends AbstractControllerTest { | @@ -130,7 +130,7 @@ public class TenantControllerTest extends AbstractControllerTest { | ||
130 | Assert.assertEquals(tenants, loadedTenants); | 130 | Assert.assertEquals(tenants, loadedTenants); |
131 | 131 | ||
132 | for (Tenant tenant : loadedTenants) { | 132 | for (Tenant tenant : loadedTenants) { |
133 | - if (!tenant.getTitle().equals("Tenant")) { | 133 | + if (!tenant.getTitle().equals(TEST_TENANT_NAME)) { |
134 | doDelete("/api/tenant/"+tenant.getId().getId().toString()) | 134 | doDelete("/api/tenant/"+tenant.getId().getId().toString()) |
135 | .andExpect(status().isOk()); | 135 | .andExpect(status().isOk()); |
136 | } | 136 | } |
@@ -182,7 +182,7 @@ public class UserControllerTest extends AbstractControllerTest { | @@ -182,7 +182,7 @@ public class UserControllerTest extends AbstractControllerTest { | ||
182 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 182 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
183 | Assert.assertNotNull(savedTenant); | 183 | Assert.assertNotNull(savedTenant); |
184 | 184 | ||
185 | - String email = "tenant@thingsboard.org"; | 185 | + String email = TENANT_ADMIN_EMAIL; |
186 | User user = new User(); | 186 | User user = new User(); |
187 | user.setAuthority(Authority.TENANT_ADMIN); | 187 | user.setAuthority(Authority.TENANT_ADMIN); |
188 | user.setTenantId(savedTenant.getId()); | 188 | user.setTenantId(savedTenant.getId()); |
@@ -47,6 +47,7 @@ public class HttpDeviceApiTest extends AbstractControllerTest { | @@ -47,6 +47,7 @@ public class HttpDeviceApiTest extends AbstractControllerTest { | ||
47 | loginTenantAdmin(); | 47 | loginTenantAdmin(); |
48 | device = new Device(); | 48 | device = new Device(); |
49 | device.setName("My device"); | 49 | device.setName("My device"); |
50 | + device.setType("default"); | ||
50 | device = doPost("/api/device", device, Device.class); | 51 | device = doPost("/api/device", device, Device.class); |
51 | 52 | ||
52 | deviceCredentials = | 53 | deviceCredentials = |
@@ -15,12 +15,14 @@ | @@ -15,12 +15,14 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data; | 16 | package org.thingsboard.server.common.data; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
19 | +import com.fasterxml.jackson.annotation.JsonProperty.Access; | ||
18 | import org.thingsboard.server.common.data.id.CustomerId; | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
19 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
20 | 22 | ||
21 | import com.fasterxml.jackson.databind.JsonNode; | 23 | import com.fasterxml.jackson.databind.JsonNode; |
22 | 24 | ||
23 | -public class Customer extends ContactBased<CustomerId>{ | 25 | +public class Customer extends ContactBased<CustomerId> implements HasName { |
24 | 26 | ||
25 | private static final long serialVersionUID = -1599722990298929275L; | 27 | private static final long serialVersionUID = -1599722990298929275L; |
26 | 28 | ||
@@ -59,6 +61,12 @@ public class Customer extends ContactBased<CustomerId>{ | @@ -59,6 +61,12 @@ public class Customer extends ContactBased<CustomerId>{ | ||
59 | this.title = title; | 61 | this.title = title; |
60 | } | 62 | } |
61 | 63 | ||
64 | + @Override | ||
65 | + @JsonProperty(access = Access.READ_ONLY) | ||
66 | + public String getName() { | ||
67 | + return title; | ||
68 | + } | ||
69 | + | ||
62 | public JsonNode getAdditionalInfo() { | 70 | public JsonNode getAdditionalInfo() { |
63 | return additionalInfo; | 71 | return additionalInfo; |
64 | } | 72 | } |
@@ -15,11 +15,12 @@ | @@ -15,11 +15,12 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data; | 16 | package org.thingsboard.server.common.data; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
18 | import org.thingsboard.server.common.data.id.CustomerId; | 19 | import org.thingsboard.server.common.data.id.CustomerId; |
19 | import org.thingsboard.server.common.data.id.DashboardId; | 20 | import org.thingsboard.server.common.data.id.DashboardId; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
21 | 22 | ||
22 | -public class DashboardInfo extends SearchTextBased<DashboardId> { | 23 | +public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName { |
23 | 24 | ||
24 | private TenantId tenantId; | 25 | private TenantId tenantId; |
25 | private CustomerId customerId; | 26 | private CustomerId customerId; |
@@ -65,6 +66,12 @@ public class DashboardInfo extends SearchTextBased<DashboardId> { | @@ -65,6 +66,12 @@ public class DashboardInfo extends SearchTextBased<DashboardId> { | ||
65 | } | 66 | } |
66 | 67 | ||
67 | @Override | 68 | @Override |
69 | + @JsonProperty(access = JsonProperty.Access.READ_ONLY) | ||
70 | + public String getName() { | ||
71 | + return title; | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
68 | public String getSearchText() { | 75 | public String getSearchText() { |
69 | return title; | 76 | return title; |
70 | } | 77 | } |
@@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
21 | 21 | ||
22 | import com.fasterxml.jackson.databind.JsonNode; | 22 | import com.fasterxml.jackson.databind.JsonNode; |
23 | 23 | ||
24 | -public class Device extends SearchTextBased<DeviceId> { | 24 | +public class Device extends SearchTextBased<DeviceId> implements HasName { |
25 | 25 | ||
26 | private static final long serialVersionUID = 2807343040519543363L; | 26 | private static final long serialVersionUID = 2807343040519543363L; |
27 | 27 | ||
@@ -64,6 +64,7 @@ public class Device extends SearchTextBased<DeviceId> { | @@ -64,6 +64,7 @@ public class Device extends SearchTextBased<DeviceId> { | ||
64 | this.customerId = customerId; | 64 | this.customerId = customerId; |
65 | } | 65 | } |
66 | 66 | ||
67 | + @Override | ||
67 | public String getName() { | 68 | public String getName() { |
68 | return name; | 69 | return name; |
69 | } | 70 | } |
common/data/src/main/java/org/thingsboard/server/common/data/HasName.java
renamed from
ui/src/app/components/device-filter.scss
@@ -13,33 +13,10 @@ | @@ -13,33 +13,10 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -.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 | -} | ||
16 | +package org.thingsboard.server.common.data; | ||
17 | + | ||
18 | +public interface HasName { | ||
19 | + | ||
20 | + String getName(); | ||
21 | + | ||
22 | +} |
@@ -15,11 +15,12 @@ | @@ -15,11 +15,12 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data; | 16 | package org.thingsboard.server.common.data; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
18 | import org.thingsboard.server.common.data.id.TenantId; | 19 | import org.thingsboard.server.common.data.id.TenantId; |
19 | 20 | ||
20 | import com.fasterxml.jackson.databind.JsonNode; | 21 | import com.fasterxml.jackson.databind.JsonNode; |
21 | 22 | ||
22 | -public class Tenant extends ContactBased<TenantId>{ | 23 | +public class Tenant extends ContactBased<TenantId> implements HasName { |
23 | 24 | ||
24 | private static final long serialVersionUID = 8057243243859922101L; | 25 | private static final long serialVersionUID = 8057243243859922101L; |
25 | 26 | ||
@@ -50,6 +51,12 @@ public class Tenant extends ContactBased<TenantId>{ | @@ -50,6 +51,12 @@ public class Tenant extends ContactBased<TenantId>{ | ||
50 | this.title = title; | 51 | this.title = title; |
51 | } | 52 | } |
52 | 53 | ||
54 | + @Override | ||
55 | + @JsonProperty(access = JsonProperty.Access.READ_ONLY) | ||
56 | + public String getName() { | ||
57 | + return title; | ||
58 | + } | ||
59 | + | ||
53 | public String getRegion() { | 60 | public String getRegion() { |
54 | return region; | 61 | return region; |
55 | } | 62 | } |
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 | +} |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data; | 16 | package org.thingsboard.server.common.data; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
18 | import org.thingsboard.server.common.data.id.CustomerId; | 19 | import org.thingsboard.server.common.data.id.CustomerId; |
19 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
20 | import org.thingsboard.server.common.data.id.UserId; | 21 | import org.thingsboard.server.common.data.id.UserId; |
@@ -22,7 +23,7 @@ import org.thingsboard.server.common.data.security.Authority; | @@ -22,7 +23,7 @@ import org.thingsboard.server.common.data.security.Authority; | ||
22 | 23 | ||
23 | import com.fasterxml.jackson.databind.JsonNode; | 24 | import com.fasterxml.jackson.databind.JsonNode; |
24 | 25 | ||
25 | -public class User extends SearchTextBased<UserId> { | 26 | +public class User extends SearchTextBased<UserId> implements HasName { |
26 | 27 | ||
27 | private static final long serialVersionUID = 8250339805336035966L; | 28 | private static final long serialVersionUID = 8250339805336035966L; |
28 | 29 | ||
@@ -77,6 +78,12 @@ public class User extends SearchTextBased<UserId> { | @@ -77,6 +78,12 @@ public class User extends SearchTextBased<UserId> { | ||
77 | this.email = email; | 78 | this.email = email; |
78 | } | 79 | } |
79 | 80 | ||
81 | + @Override | ||
82 | + @JsonProperty(access = JsonProperty.Access.READ_ONLY) | ||
83 | + public String getName() { | ||
84 | + return email; | ||
85 | + } | ||
86 | + | ||
80 | public Authority getAuthority() { | 87 | public Authority getAuthority() { |
81 | return authority; | 88 | return authority; |
82 | } | 89 | } |
@@ -15,26 +15,47 @@ | @@ -15,26 +15,47 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.alarm; | 16 | package org.thingsboard.server.common.data.alarm; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | +import lombok.AllArgsConstructor; | ||
21 | +import lombok.Builder; | ||
19 | import lombok.Data; | 22 | import lombok.Data; |
20 | import org.thingsboard.server.common.data.BaseData; | 23 | import org.thingsboard.server.common.data.BaseData; |
24 | +import org.thingsboard.server.common.data.HasName; | ||
21 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
26 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | 27 | ||
23 | /** | 28 | /** |
24 | * Created by ashvayka on 11.05.17. | 29 | * Created by ashvayka on 11.05.17. |
25 | */ | 30 | */ |
26 | @Data | 31 | @Data |
27 | -public class Alarm extends BaseData<AlarmId> { | 32 | +@Builder |
33 | +@AllArgsConstructor | ||
34 | +public class Alarm extends BaseData<AlarmId> implements HasName { | ||
28 | 35 | ||
29 | - private long startTs; | ||
30 | - private long endTs; | ||
31 | - private long ackTs; | ||
32 | - private long clearTs; | 36 | + private TenantId tenantId; |
33 | private String type; | 37 | private String type; |
34 | private EntityId originator; | 38 | private EntityId originator; |
35 | private AlarmSeverity severity; | 39 | private AlarmSeverity severity; |
36 | private AlarmStatus status; | 40 | private AlarmStatus status; |
41 | + private long startTs; | ||
42 | + private long endTs; | ||
43 | + private long ackTs; | ||
44 | + private long clearTs; | ||
37 | private JsonNode details; | 45 | private JsonNode details; |
38 | private boolean propagate; | 46 | private boolean propagate; |
39 | 47 | ||
48 | + public Alarm() { | ||
49 | + super(); | ||
50 | + } | ||
51 | + | ||
52 | + public Alarm(AlarmId id) { | ||
53 | + super(id); | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + @JsonProperty(access = JsonProperty.Access.READ_ONLY) | ||
58 | + public String getName() { | ||
59 | + return type; | ||
60 | + } | ||
40 | } | 61 | } |
@@ -15,14 +15,19 @@ | @@ -15,14 +15,19 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.alarm; | 16 | package org.thingsboard.server.common.data.alarm; |
17 | 17 | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.Builder; | ||
18 | import lombok.Data; | 20 | import lombok.Data; |
19 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | +import org.thingsboard.server.common.data.id.TenantId; | ||
20 | import org.thingsboard.server.common.data.page.TimePageLink; | 23 | import org.thingsboard.server.common.data.page.TimePageLink; |
21 | 24 | ||
22 | /** | 25 | /** |
23 | * Created by ashvayka on 11.05.17. | 26 | * Created by ashvayka on 11.05.17. |
24 | */ | 27 | */ |
25 | @Data | 28 | @Data |
29 | +@Builder | ||
30 | +@AllArgsConstructor | ||
26 | public class AlarmQuery { | 31 | public class AlarmQuery { |
27 | 32 | ||
28 | private EntityId affectedEntityId; | 33 | private EntityId affectedEntityId; |
@@ -22,4 +22,12 @@ public enum AlarmStatus { | @@ -22,4 +22,12 @@ public enum AlarmStatus { | ||
22 | 22 | ||
23 | ACTIVE_UNACK, ACTIVE_ACK, CLEARED_UNACK, CLEARED_ACK; | 23 | ACTIVE_UNACK, ACTIVE_ACK, CLEARED_UNACK, CLEARED_ACK; |
24 | 24 | ||
25 | + public boolean isAck() { | ||
26 | + return this == ACTIVE_ACK || this == CLEARED_ACK; | ||
27 | + } | ||
28 | + | ||
29 | + public boolean isCleared() { | ||
30 | + return this == CLEARED_ACK || this == CLEARED_UNACK; | ||
31 | + } | ||
32 | + | ||
25 | } | 33 | } |
@@ -16,12 +16,13 @@ | @@ -16,12 +16,13 @@ | ||
16 | package org.thingsboard.server.common.data.asset; | 16 | package org.thingsboard.server.common.data.asset; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import org.thingsboard.server.common.data.HasName; | ||
19 | import org.thingsboard.server.common.data.SearchTextBased; | 20 | import org.thingsboard.server.common.data.SearchTextBased; |
20 | import org.thingsboard.server.common.data.id.AssetId; | 21 | import org.thingsboard.server.common.data.id.AssetId; |
21 | import org.thingsboard.server.common.data.id.CustomerId; | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
23 | 24 | ||
24 | -public class Asset extends SearchTextBased<AssetId> { | 25 | +public class Asset extends SearchTextBased<AssetId> implements HasName { |
25 | 26 | ||
26 | private static final long serialVersionUID = 2807343040519543363L; | 27 | private static final long serialVersionUID = 2807343040519543363L; |
27 | 28 | ||
@@ -64,6 +65,7 @@ public class Asset extends SearchTextBased<AssetId> { | @@ -64,6 +65,7 @@ public class Asset extends SearchTextBased<AssetId> { | ||
64 | this.customerId = customerId; | 65 | this.customerId = customerId; |
65 | } | 66 | } |
66 | 67 | ||
68 | + @Override | ||
67 | public String getName() { | 69 | public String getName() { |
68 | return name; | 70 | return name; |
69 | } | 71 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.asset; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.TenantId; | ||
19 | + | ||
20 | +public class TenantAssetType { | ||
21 | + | ||
22 | + private static final long serialVersionUID = 8057290243855622101L; | ||
23 | + | ||
24 | + private String type; | ||
25 | + private TenantId tenantId; | ||
26 | + | ||
27 | + public TenantAssetType() { | ||
28 | + super(); | ||
29 | + } | ||
30 | + | ||
31 | + public TenantAssetType(String type, TenantId tenantId) { | ||
32 | + this.type = type; | ||
33 | + this.tenantId = tenantId; | ||
34 | + } | ||
35 | + | ||
36 | + public String getType() { | ||
37 | + return type; | ||
38 | + } | ||
39 | + | ||
40 | + public void setType(String type) { | ||
41 | + this.type = type; | ||
42 | + } | ||
43 | + | ||
44 | + public TenantId getTenantId() { | ||
45 | + return tenantId; | ||
46 | + } | ||
47 | + | ||
48 | + public void setTenantId(TenantId tenantId) { | ||
49 | + this.tenantId = tenantId; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public int hashCode() { | ||
54 | + int result = type != null ? type.hashCode() : 0; | ||
55 | + result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0); | ||
56 | + return result; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public boolean equals(Object o) { | ||
61 | + if (this == o) return true; | ||
62 | + if (o == null || getClass() != o.getClass()) return false; | ||
63 | + | ||
64 | + TenantAssetType that = (TenantAssetType) o; | ||
65 | + | ||
66 | + if (type != null ? !type.equals(that.type) : that.type != null) return false; | ||
67 | + return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; | ||
68 | + | ||
69 | + } | ||
70 | + | ||
71 | + @Override | ||
72 | + public String toString() { | ||
73 | + final StringBuilder sb = new StringBuilder("TenantAssetType{"); | ||
74 | + sb.append("type='").append(type).append('\''); | ||
75 | + sb.append(", tenantId=").append(tenantId); | ||
76 | + sb.append('}'); | ||
77 | + return sb.toString(); | ||
78 | + } | ||
79 | +} |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.common.data.id; | 16 | package org.thingsboard.server.common.data.id; |
17 | 17 | ||
18 | import org.thingsboard.server.common.data.EntityType; | 18 | import org.thingsboard.server.common.data.EntityType; |
19 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
19 | 20 | ||
20 | import java.util.UUID; | 21 | import java.util.UUID; |
21 | 22 | ||
@@ -50,6 +51,8 @@ public class EntityIdFactory { | @@ -50,6 +51,8 @@ public class EntityIdFactory { | ||
50 | return new DeviceId(uuid); | 51 | return new DeviceId(uuid); |
51 | case ASSET: | 52 | case ASSET: |
52 | return new AssetId(uuid); | 53 | return new AssetId(uuid); |
54 | + case ALARM: | ||
55 | + return new AlarmId(uuid); | ||
53 | } | 56 | } |
54 | throw new IllegalArgumentException("EntityType " + type + " is not supported!"); | 57 | throw new IllegalArgumentException("EntityType " + type + " is not supported!"); |
55 | } | 58 | } |
@@ -15,13 +15,14 @@ | @@ -15,13 +15,14 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.plugin; | 16 | package org.thingsboard.server.common.data.plugin; |
17 | 17 | ||
18 | +import org.thingsboard.server.common.data.HasName; | ||
18 | import org.thingsboard.server.common.data.SearchTextBased; | 19 | import org.thingsboard.server.common.data.SearchTextBased; |
19 | import org.thingsboard.server.common.data.id.PluginId; | 20 | import org.thingsboard.server.common.data.id.PluginId; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
21 | 22 | ||
22 | import com.fasterxml.jackson.databind.JsonNode; | 23 | import com.fasterxml.jackson.databind.JsonNode; |
23 | 24 | ||
24 | -public class PluginMetaData extends SearchTextBased<PluginId> { | 25 | +public class PluginMetaData extends SearchTextBased<PluginId> implements HasName { |
25 | 26 | ||
26 | private static final long serialVersionUID = 1L; | 27 | private static final long serialVersionUID = 1L; |
27 | 28 | ||
@@ -75,6 +76,7 @@ public class PluginMetaData extends SearchTextBased<PluginId> { | @@ -75,6 +76,7 @@ public class PluginMetaData extends SearchTextBased<PluginId> { | ||
75 | this.tenantId = tenantId; | 76 | this.tenantId = tenantId; |
76 | } | 77 | } |
77 | 78 | ||
79 | + @Override | ||
78 | public String getName() { | 80 | public String getName() { |
79 | return name; | 81 | return name; |
80 | } | 82 | } |
@@ -30,6 +30,7 @@ public class EntityRelation { | @@ -30,6 +30,7 @@ public class EntityRelation { | ||
30 | private EntityId from; | 30 | private EntityId from; |
31 | private EntityId to; | 31 | private EntityId to; |
32 | private String type; | 32 | private String type; |
33 | + private RelationTypeGroup typeGroup; | ||
33 | private JsonNode additionalInfo; | 34 | private JsonNode additionalInfo; |
34 | 35 | ||
35 | public EntityRelation() { | 36 | public EntityRelation() { |
@@ -37,21 +38,27 @@ public class EntityRelation { | @@ -37,21 +38,27 @@ public class EntityRelation { | ||
37 | } | 38 | } |
38 | 39 | ||
39 | public EntityRelation(EntityId from, EntityId to, String type) { | 40 | public EntityRelation(EntityId from, EntityId to, String type) { |
40 | - this(from, to, type, null); | 41 | + this(from, to, type, RelationTypeGroup.COMMON); |
41 | } | 42 | } |
42 | 43 | ||
43 | - public EntityRelation(EntityId from, EntityId to, String type, JsonNode additionalInfo) { | 44 | + public EntityRelation(EntityId from, EntityId to, String type, RelationTypeGroup typeGroup) { |
45 | + this(from, to, type, typeGroup, null); | ||
46 | + } | ||
47 | + | ||
48 | + public EntityRelation(EntityId from, EntityId to, String type, RelationTypeGroup typeGroup, JsonNode additionalInfo) { | ||
44 | this.from = from; | 49 | this.from = from; |
45 | this.to = to; | 50 | this.to = to; |
46 | this.type = type; | 51 | this.type = type; |
52 | + this.typeGroup = typeGroup; | ||
47 | this.additionalInfo = additionalInfo; | 53 | this.additionalInfo = additionalInfo; |
48 | } | 54 | } |
49 | 55 | ||
50 | - public EntityRelation(EntityRelation device) { | ||
51 | - this.from = device.getFrom(); | ||
52 | - this.to = device.getTo(); | ||
53 | - this.type = device.getType(); | ||
54 | - this.additionalInfo = device.getAdditionalInfo(); | 56 | + public EntityRelation(EntityRelation entityRelation) { |
57 | + this.from = entityRelation.getFrom(); | ||
58 | + this.to = entityRelation.getTo(); | ||
59 | + this.type = entityRelation.getType(); | ||
60 | + this.typeGroup = entityRelation.getTypeGroup(); | ||
61 | + this.additionalInfo = entityRelation.getAdditionalInfo(); | ||
55 | } | 62 | } |
56 | 63 | ||
57 | public EntityId getFrom() { | 64 | public EntityId getFrom() { |
@@ -78,6 +85,14 @@ public class EntityRelation { | @@ -78,6 +85,14 @@ public class EntityRelation { | ||
78 | this.type = type; | 85 | this.type = type; |
79 | } | 86 | } |
80 | 87 | ||
88 | + public RelationTypeGroup getTypeGroup() { | ||
89 | + return typeGroup; | ||
90 | + } | ||
91 | + | ||
92 | + public void setTypeGroup(RelationTypeGroup typeGroup) { | ||
93 | + this.typeGroup = typeGroup; | ||
94 | + } | ||
95 | + | ||
81 | public JsonNode getAdditionalInfo() { | 96 | public JsonNode getAdditionalInfo() { |
82 | return additionalInfo; | 97 | return additionalInfo; |
83 | } | 98 | } |
@@ -90,14 +105,22 @@ public class EntityRelation { | @@ -90,14 +105,22 @@ public class EntityRelation { | ||
90 | public boolean equals(Object o) { | 105 | public boolean equals(Object o) { |
91 | if (this == o) return true; | 106 | if (this == o) return true; |
92 | if (o == null || getClass() != o.getClass()) return false; | 107 | if (o == null || getClass() != o.getClass()) return false; |
93 | - EntityRelation relation = (EntityRelation) o; | ||
94 | - return Objects.equals(from, relation.from) && | ||
95 | - Objects.equals(to, relation.to) && | ||
96 | - Objects.equals(type, relation.type); | 108 | + |
109 | + EntityRelation that = (EntityRelation) o; | ||
110 | + | ||
111 | + if (from != null ? !from.equals(that.from) : that.from != null) return false; | ||
112 | + if (to != null ? !to.equals(that.to) : that.to != null) return false; | ||
113 | + if (type != null ? !type.equals(that.type) : that.type != null) return false; | ||
114 | + return typeGroup == that.typeGroup; | ||
115 | + | ||
97 | } | 116 | } |
98 | 117 | ||
99 | @Override | 118 | @Override |
100 | public int hashCode() { | 119 | public int hashCode() { |
101 | - return Objects.hash(from, to, type); | 120 | + int result = from != null ? from.hashCode() : 0; |
121 | + result = 31 * result + (to != null ? to.hashCode() : 0); | ||
122 | + result = 31 * result + (type != null ? type.hashCode() : 0); | ||
123 | + result = 31 * result + (typeGroup != null ? typeGroup.hashCode() : 0); | ||
124 | + return result; | ||
102 | } | 125 | } |
103 | } | 126 | } |
common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationInfo.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.common.data.relation; | ||
18 | + | ||
19 | +public class EntityRelationInfo extends EntityRelation { | ||
20 | + | ||
21 | + private static final long serialVersionUID = 2807343097519543363L; | ||
22 | + | ||
23 | + private String fromName; | ||
24 | + private String toName; | ||
25 | + | ||
26 | + public EntityRelationInfo() { | ||
27 | + super(); | ||
28 | + } | ||
29 | + | ||
30 | + public EntityRelationInfo(EntityRelation entityRelation) { | ||
31 | + super(entityRelation); | ||
32 | + } | ||
33 | + | ||
34 | + public String getFromName() { | ||
35 | + return fromName; | ||
36 | + } | ||
37 | + | ||
38 | + public void setFromName(String fromName) { | ||
39 | + this.fromName = fromName; | ||
40 | + } | ||
41 | + | ||
42 | + public String getToName() { | ||
43 | + return toName; | ||
44 | + } | ||
45 | + | ||
46 | + public void setToName(String toName) { | ||
47 | + this.toName = toName; | ||
48 | + } | ||
49 | + | ||
50 | + @Override | ||
51 | + public boolean equals(Object o) { | ||
52 | + if (this == o) return true; | ||
53 | + if (o == null || getClass() != o.getClass()) return false; | ||
54 | + if (!super.equals(o)) return false; | ||
55 | + | ||
56 | + EntityRelationInfo that = (EntityRelationInfo) o; | ||
57 | + | ||
58 | + return toName != null ? toName.equals(that.toName) : that.toName == null; | ||
59 | + | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public int hashCode() { | ||
64 | + int result = super.hashCode(); | ||
65 | + result = 31 * result + (toName != null ? toName.hashCode() : 0); | ||
66 | + return result; | ||
67 | + } | ||
68 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationTypeGroup.java
0 → 100644
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.relation; | ||
17 | + | ||
18 | +public enum RelationTypeGroup { | ||
19 | + | ||
20 | + COMMON, | ||
21 | + ALARM | ||
22 | + | ||
23 | +} |
@@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.rule; | @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.rule; | ||
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | import lombok.ToString; | 19 | import lombok.ToString; |
20 | +import org.thingsboard.server.common.data.HasName; | ||
20 | import org.thingsboard.server.common.data.SearchTextBased; | 21 | import org.thingsboard.server.common.data.SearchTextBased; |
21 | import org.thingsboard.server.common.data.id.CustomerId; | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.server.common.data.id.RuleId; | 23 | import org.thingsboard.server.common.data.id.RuleId; |
@@ -26,7 +27,7 @@ import com.fasterxml.jackson.databind.JsonNode; | @@ -26,7 +27,7 @@ import com.fasterxml.jackson.databind.JsonNode; | ||
26 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | 27 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
27 | 28 | ||
28 | @Data | 29 | @Data |
29 | -public class RuleMetaData extends SearchTextBased<RuleId> { | 30 | +public class RuleMetaData extends SearchTextBased<RuleId> implements HasName { |
30 | 31 | ||
31 | private static final long serialVersionUID = -5656679015122935465L; | 32 | private static final long serialVersionUID = -5656679015122935465L; |
32 | 33 | ||
@@ -66,4 +67,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> { | @@ -66,4 +67,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> { | ||
66 | return name; | 67 | return name; |
67 | } | 68 | } |
68 | 69 | ||
70 | + @Override | ||
71 | + public String getName() { | ||
72 | + return name; | ||
73 | + } | ||
74 | + | ||
69 | } | 75 | } |
@@ -127,7 +127,7 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | @@ -127,7 +127,7 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | ||
127 | log.debug("Save entity {}", entity); | 127 | log.debug("Save entity {}", entity); |
128 | if (entity.getId() == null) { | 128 | if (entity.getId() == null) { |
129 | entity.setId(UUIDs.timeBased()); | 129 | entity.setId(UUIDs.timeBased()); |
130 | - } else { | 130 | + } else if (isDeleteOnSave()) { |
131 | removeById(entity.getId()); | 131 | removeById(entity.getId()); |
132 | } | 132 | } |
133 | Statement saveStatement = getSaveQuery(entity); | 133 | Statement saveStatement = getSaveQuery(entity); |
@@ -136,6 +136,10 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | @@ -136,6 +136,10 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | ||
136 | return new EntityResultSet<>(resultSet, entity); | 136 | return new EntityResultSet<>(resultSet, entity); |
137 | } | 137 | } |
138 | 138 | ||
139 | + protected boolean isDeleteOnSave() { | ||
140 | + return true; | ||
141 | + } | ||
142 | + | ||
139 | public T save(T entity) { | 143 | public T save(T entity) { |
140 | return saveWithResult(entity).getEntity(); | 144 | return saveWithResult(entity).getEntity(); |
141 | } | 145 | } |
@@ -161,9 +165,18 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | @@ -161,9 +165,18 @@ public abstract class AbstractModelDao<T extends BaseEntity<?>> extends Abstract | ||
161 | return getSession().execute(delete); | 165 | return getSession().execute(delete); |
162 | } | 166 | } |
163 | 167 | ||
164 | - | ||
165 | public List<T> find() { | 168 | public List<T> find() { |
166 | log.debug("Get all entities from column family {}", getColumnFamilyName()); | 169 | log.debug("Get all entities from column family {}", getColumnFamilyName()); |
167 | return findListByStatement(QueryBuilder.select().all().from(getColumnFamilyName()).setConsistencyLevel(cluster.getDefaultReadConsistencyLevel())); | 170 | return findListByStatement(QueryBuilder.select().all().from(getColumnFamilyName()).setConsistencyLevel(cluster.getDefaultReadConsistencyLevel())); |
168 | } | 171 | } |
172 | + | ||
173 | + protected static <T> Function<BaseEntity<T>, T> toDataFunction() { | ||
174 | + return new Function<BaseEntity<T>, T>() { | ||
175 | + @Nullable | ||
176 | + @Override | ||
177 | + public T apply(@Nullable BaseEntity<T> entity) { | ||
178 | + return entity != null ? entity.toData() : null; | ||
179 | + } | ||
180 | + }; | ||
181 | + } | ||
169 | } | 182 | } |
@@ -47,8 +47,27 @@ public abstract class AbstractSearchTimeDao<T extends BaseEntity<?>> extends Abs | @@ -47,8 +47,27 @@ public abstract class AbstractSearchTimeDao<T extends BaseEntity<?>> extends Abs | ||
47 | return findPageWithTimeSearch(searchView, clauses, Collections.singletonList(ordering), pageLink); | 47 | return findPageWithTimeSearch(searchView, clauses, Collections.singletonList(ordering), pageLink); |
48 | } | 48 | } |
49 | 49 | ||
50 | - | ||
51 | protected List<T> findPageWithTimeSearch(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink) { | 50 | protected List<T> findPageWithTimeSearch(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink) { |
51 | + return findPageWithTimeSearch(searchView, clauses, topLevelOrderings, pageLink, ModelConstants.ID_PROPERTY); | ||
52 | + } | ||
53 | + | ||
54 | + protected List<T> findPageWithTimeSearch(String searchView, List<Clause> clauses, TimePageLink pageLink, String idColumn) { | ||
55 | + return findPageWithTimeSearch(searchView, clauses, Collections.emptyList(), pageLink, idColumn); | ||
56 | + } | ||
57 | + | ||
58 | + protected List<T> findPageWithTimeSearch(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink, String idColumn) { | ||
59 | + return findListByStatement(buildQuery(searchView, clauses, topLevelOrderings, pageLink, idColumn)); | ||
60 | + } | ||
61 | + | ||
62 | + public static Where buildQuery(String searchView, List<Clause> clauses, TimePageLink pageLink, String idColumn) { | ||
63 | + return buildQuery(searchView, clauses, Collections.emptyList(), pageLink, idColumn); | ||
64 | + } | ||
65 | + | ||
66 | + public static Where buildQuery(String searchView, List<Clause> clauses, Ordering order, TimePageLink pageLink, String idColumn) { | ||
67 | + return buildQuery(searchView, clauses, Collections.singletonList(order), pageLink, idColumn); | ||
68 | + } | ||
69 | + | ||
70 | + public static Where buildQuery(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink, String idColumn) { | ||
52 | Select select = select().from(searchView); | 71 | Select select = select().from(searchView); |
53 | Where query = select.where(); | 72 | Where query = select.where(); |
54 | for (Clause clause : clauses) { | 73 | for (Clause clause : clauses) { |
@@ -57,34 +76,35 @@ public abstract class AbstractSearchTimeDao<T extends BaseEntity<?>> extends Abs | @@ -57,34 +76,35 @@ public abstract class AbstractSearchTimeDao<T extends BaseEntity<?>> extends Abs | ||
57 | query.limit(pageLink.getLimit()); | 76 | query.limit(pageLink.getLimit()); |
58 | if (pageLink.isAscOrder()) { | 77 | if (pageLink.isAscOrder()) { |
59 | if (pageLink.getIdOffset() != null) { | 78 | if (pageLink.getIdOffset() != null) { |
60 | - query.and(QueryBuilder.gt(ModelConstants.ID_PROPERTY, pageLink.getIdOffset())); | 79 | + query.and(QueryBuilder.gt(idColumn, pageLink.getIdOffset())); |
61 | } else if (pageLink.getStartTime() != null) { | 80 | } else if (pageLink.getStartTime() != null) { |
62 | final UUID startOf = UUIDs.startOf(pageLink.getStartTime()); | 81 | final UUID startOf = UUIDs.startOf(pageLink.getStartTime()); |
63 | - query.and(QueryBuilder.gte(ModelConstants.ID_PROPERTY, startOf)); | 82 | + query.and(QueryBuilder.gte(idColumn, startOf)); |
64 | } | 83 | } |
65 | if (pageLink.getEndTime() != null) { | 84 | if (pageLink.getEndTime() != null) { |
66 | final UUID endOf = UUIDs.endOf(pageLink.getEndTime()); | 85 | final UUID endOf = UUIDs.endOf(pageLink.getEndTime()); |
67 | - query.and(QueryBuilder.lte(ModelConstants.ID_PROPERTY, endOf)); | 86 | + query.and(QueryBuilder.lte(idColumn, endOf)); |
68 | } | 87 | } |
69 | } else { | 88 | } else { |
70 | if (pageLink.getIdOffset() != null) { | 89 | if (pageLink.getIdOffset() != null) { |
71 | - query.and(QueryBuilder.lt(ModelConstants.ID_PROPERTY, pageLink.getIdOffset())); | 90 | + query.and(QueryBuilder.lt(idColumn, pageLink.getIdOffset())); |
72 | } else if (pageLink.getEndTime() != null) { | 91 | } else if (pageLink.getEndTime() != null) { |
73 | final UUID endOf = UUIDs.endOf(pageLink.getEndTime()); | 92 | final UUID endOf = UUIDs.endOf(pageLink.getEndTime()); |
74 | - query.and(QueryBuilder.lte(ModelConstants.ID_PROPERTY, endOf)); | 93 | + query.and(QueryBuilder.lte(idColumn, endOf)); |
75 | } | 94 | } |
76 | if (pageLink.getStartTime() != null) { | 95 | if (pageLink.getStartTime() != null) { |
77 | final UUID startOf = UUIDs.startOf(pageLink.getStartTime()); | 96 | final UUID startOf = UUIDs.startOf(pageLink.getStartTime()); |
78 | - query.and(QueryBuilder.gte(ModelConstants.ID_PROPERTY, startOf)); | 97 | + query.and(QueryBuilder.gte(idColumn, startOf)); |
79 | } | 98 | } |
80 | } | 99 | } |
81 | List<Ordering> orderings = new ArrayList<>(topLevelOrderings); | 100 | List<Ordering> orderings = new ArrayList<>(topLevelOrderings); |
82 | if (pageLink.isAscOrder()) { | 101 | if (pageLink.isAscOrder()) { |
83 | - orderings.add(QueryBuilder.asc(ModelConstants.ID_PROPERTY)); | 102 | + orderings.add(QueryBuilder.asc(idColumn)); |
84 | } else { | 103 | } else { |
85 | - orderings.add(QueryBuilder.desc(ModelConstants.ID_PROPERTY)); | 104 | + orderings.add(QueryBuilder.desc(idColumn)); |
86 | } | 105 | } |
87 | query.orderBy(orderings.toArray(new Ordering[orderings.size()])); | 106 | query.orderBy(orderings.toArray(new Ordering[orderings.size()])); |
88 | - return findListByStatement(query); | 107 | + return query; |
89 | } | 108 | } |
109 | + | ||
90 | } | 110 | } |
@@ -15,8 +15,27 @@ | @@ -15,8 +15,27 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.alarm; | 16 | package org.thingsboard.server.dao.alarm; |
17 | 17 | ||
18 | +import com.google.common.util.concurrent.ListenableFuture; | ||
19 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
20 | +import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
21 | +import org.thingsboard.server.common.data.id.EntityId; | ||
22 | +import org.thingsboard.server.common.data.id.TenantId; | ||
23 | +import org.thingsboard.server.dao.Dao; | ||
24 | +import org.thingsboard.server.dao.model.AlarmEntity; | ||
25 | + | ||
26 | +import java.util.List; | ||
27 | +import java.util.UUID; | ||
28 | + | ||
18 | /** | 29 | /** |
19 | * Created by ashvayka on 11.05.17. | 30 | * Created by ashvayka on 11.05.17. |
20 | */ | 31 | */ |
21 | -public interface AlarmDao { | 32 | +public interface AlarmDao extends Dao<AlarmEntity> { |
33 | + | ||
34 | + ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type); | ||
35 | + | ||
36 | + ListenableFuture<Alarm> findAlarmByIdAsync(UUID key); | ||
37 | + | ||
38 | + AlarmEntity save(Alarm alarm); | ||
39 | + | ||
40 | + ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query); | ||
22 | } | 41 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.alarm; | ||
17 | + | ||
18 | +import com.datastax.driver.core.querybuilder.QueryBuilder; | ||
19 | +import com.datastax.driver.core.querybuilder.Select; | ||
20 | +import com.google.common.util.concurrent.AsyncFunction; | ||
21 | +import com.google.common.util.concurrent.Futures; | ||
22 | +import com.google.common.util.concurrent.ListenableFuture; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
24 | +import org.springframework.beans.factory.annotation.Autowired; | ||
25 | +import org.springframework.stereotype.Component; | ||
26 | +import org.thingsboard.server.common.data.EntityType; | ||
27 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
28 | +import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
29 | +import org.thingsboard.server.common.data.id.EntityId; | ||
30 | +import org.thingsboard.server.common.data.id.TenantId; | ||
31 | +import org.thingsboard.server.common.data.relation.EntityRelation; | ||
32 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
33 | +import org.thingsboard.server.dao.AbstractModelDao; | ||
34 | +import org.thingsboard.server.dao.AbstractSearchTimeDao; | ||
35 | +import org.thingsboard.server.dao.model.AlarmEntity; | ||
36 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
37 | +import org.thingsboard.server.dao.relation.RelationDao; | ||
38 | + | ||
39 | +import java.util.ArrayList; | ||
40 | +import java.util.List; | ||
41 | +import java.util.UUID; | ||
42 | + | ||
43 | +import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; | ||
44 | +import static com.datastax.driver.core.querybuilder.QueryBuilder.select; | ||
45 | +import static org.thingsboard.server.dao.model.ModelConstants.*; | ||
46 | + | ||
47 | +@Component | ||
48 | +@Slf4j | ||
49 | +public class AlarmDaoImpl extends AbstractModelDao<AlarmEntity> implements AlarmDao { | ||
50 | + | ||
51 | + @Autowired | ||
52 | + private RelationDao relationDao; | ||
53 | + | ||
54 | + @Override | ||
55 | + protected Class<AlarmEntity> getColumnFamilyClass() { | ||
56 | + return AlarmEntity.class; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + protected String getColumnFamilyName() { | ||
61 | + return ALARM_COLUMN_FAMILY_NAME; | ||
62 | + } | ||
63 | + | ||
64 | + protected boolean isDeleteOnSave() { | ||
65 | + return false; | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public AlarmEntity save(Alarm alarm) { | ||
70 | + log.debug("Save asset [{}] ", alarm); | ||
71 | + return save(new AlarmEntity(alarm)); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type) { | ||
76 | + Select select = select().from(ALARM_COLUMN_FAMILY_NAME); | ||
77 | + Select.Where query = select.where(); | ||
78 | + query.and(eq(ALARM_TENANT_ID_PROPERTY, tenantId.getId())); | ||
79 | + query.and(eq(ALARM_ORIGINATOR_ID_PROPERTY, originator.getId())); | ||
80 | + query.and(eq(ALARM_ORIGINATOR_TYPE_PROPERTY, originator.getEntityType())); | ||
81 | + query.and(eq(ALARM_TYPE_PROPERTY, type)); | ||
82 | + query.limit(1); | ||
83 | + query.orderBy(QueryBuilder.asc(ModelConstants.ALARM_TYPE_PROPERTY), QueryBuilder.desc(ModelConstants.ID_PROPERTY)); | ||
84 | + return Futures.transform(findOneByStatementAsync(query), toDataFunction()); | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public ListenableFuture<Alarm> findAlarmByIdAsync(UUID key) { | ||
89 | + log.debug("Get alarm by id {}", key); | ||
90 | + Select.Where query = select().from(ALARM_BY_ID_VIEW_NAME).where(eq(ModelConstants.ID_PROPERTY, key)); | ||
91 | + query.limit(1); | ||
92 | + log.trace("Execute query {}", query); | ||
93 | + return Futures.transform(findOneByStatementAsync(query), toDataFunction()); | ||
94 | + } | ||
95 | + | ||
96 | + @Override | ||
97 | + public ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query) { | ||
98 | + log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); | ||
99 | + EntityId affectedEntity = query.getAffectedEntityId(); | ||
100 | + String relationType = query.getStatus() == null ? BaseAlarmService.ALARM_RELATION : BaseAlarmService.ALARM_RELATION_PREFIX + query.getStatus().name(); | ||
101 | + ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); | ||
102 | + return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<Alarm>>) input -> { | ||
103 | + List<ListenableFuture<Alarm>> alarmFutures = new ArrayList<>(input.size()); | ||
104 | + for (EntityRelation relation : input) { | ||
105 | + alarmFutures.add(findAlarmByIdAsync(relation.getTo().getId())); | ||
106 | + } | ||
107 | + return Futures.successfulAsList(alarmFutures); | ||
108 | + }); | ||
109 | + } | ||
110 | +} |
@@ -21,20 +21,18 @@ import org.thingsboard.server.common.data.alarm.AlarmId; | @@ -21,20 +21,18 @@ import org.thingsboard.server.common.data.alarm.AlarmId; | ||
21 | import org.thingsboard.server.common.data.alarm.AlarmQuery; | 21 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
22 | import org.thingsboard.server.common.data.page.TimePageData; | 22 | import org.thingsboard.server.common.data.page.TimePageData; |
23 | 23 | ||
24 | -import java.util.Optional; | ||
25 | - | ||
26 | /** | 24 | /** |
27 | * Created by ashvayka on 11.05.17. | 25 | * Created by ashvayka on 11.05.17. |
28 | */ | 26 | */ |
29 | public interface AlarmService { | 27 | public interface AlarmService { |
30 | 28 | ||
31 | - Optional<Alarm> saveIfNotExists(Alarm alarm); | 29 | + Alarm createOrUpdateAlarm(Alarm alarm); |
32 | 30 | ||
33 | - ListenableFuture<Boolean> updateAlarm(Alarm alarm); | 31 | + ListenableFuture<Boolean> ackAlarm(AlarmId alarmId, long ackTs); |
34 | 32 | ||
35 | - ListenableFuture<Boolean> ackAlarm(Alarm alarm); | 33 | + ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, long ackTs); |
36 | 34 | ||
37 | - ListenableFuture<Boolean> clearAlarm(AlarmId alarmId); | 35 | + ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId); |
38 | 36 | ||
39 | ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query); | 37 | ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query); |
40 | 38 |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.alarm; | ||
17 | + | ||
18 | + | ||
19 | +import com.google.common.base.Function; | ||
20 | +import com.google.common.util.concurrent.Futures; | ||
21 | +import com.google.common.util.concurrent.ListenableFuture; | ||
22 | +import lombok.extern.slf4j.Slf4j; | ||
23 | +import org.springframework.beans.factory.annotation.Autowired; | ||
24 | +import org.springframework.stereotype.Service; | ||
25 | +import org.springframework.util.StringUtils; | ||
26 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
27 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
28 | +import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
29 | +import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
30 | +import org.thingsboard.server.common.data.id.EntityId; | ||
31 | +import org.thingsboard.server.common.data.page.TimePageData; | ||
32 | +import org.thingsboard.server.common.data.relation.EntityRelation; | ||
33 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
34 | +import org.thingsboard.server.dao.entity.AbstractEntityService; | ||
35 | +import org.thingsboard.server.dao.entity.BaseEntityService; | ||
36 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
37 | +import org.thingsboard.server.dao.model.*; | ||
38 | +import org.thingsboard.server.dao.relation.EntityRelationsQuery; | ||
39 | +import org.thingsboard.server.dao.relation.EntitySearchDirection; | ||
40 | +import org.thingsboard.server.dao.relation.RelationService; | ||
41 | +import org.thingsboard.server.dao.relation.RelationsSearchParameters; | ||
42 | +import org.thingsboard.server.dao.service.DataValidator; | ||
43 | +import org.thingsboard.server.dao.tenant.TenantDao; | ||
44 | + | ||
45 | +import javax.annotation.Nullable; | ||
46 | +import javax.annotation.PostConstruct; | ||
47 | +import javax.annotation.PreDestroy; | ||
48 | +import java.util.List; | ||
49 | +import java.util.concurrent.ExecutionException; | ||
50 | +import java.util.concurrent.ExecutorService; | ||
51 | +import java.util.concurrent.Executors; | ||
52 | +import java.util.stream.Collectors; | ||
53 | + | ||
54 | +import static org.thingsboard.server.dao.DaoUtil.*; | ||
55 | +import static org.thingsboard.server.dao.service.Validator.*; | ||
56 | + | ||
57 | +@Service | ||
58 | +@Slf4j | ||
59 | +public class BaseAlarmService extends AbstractEntityService implements AlarmService { | ||
60 | + | ||
61 | + public static final String ALARM_RELATION_PREFIX = "ALARM_"; | ||
62 | + public static final String ALARM_RELATION = "ALARM_ANY"; | ||
63 | + | ||
64 | + @Autowired | ||
65 | + private AlarmDao alarmDao; | ||
66 | + | ||
67 | + @Autowired | ||
68 | + private TenantDao tenantDao; | ||
69 | + | ||
70 | + @Autowired | ||
71 | + private RelationService relationService; | ||
72 | + | ||
73 | + protected ExecutorService readResultsProcessingExecutor; | ||
74 | + | ||
75 | + @PostConstruct | ||
76 | + public void startExecutor() { | ||
77 | + readResultsProcessingExecutor = Executors.newCachedThreadPool(); | ||
78 | + } | ||
79 | + | ||
80 | + @PreDestroy | ||
81 | + public void stopExecutor() { | ||
82 | + if (readResultsProcessingExecutor != null) { | ||
83 | + readResultsProcessingExecutor.shutdownNow(); | ||
84 | + } | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public Alarm createOrUpdateAlarm(Alarm alarm) { | ||
89 | + alarmDataValidator.validate(alarm); | ||
90 | + try { | ||
91 | + if (alarm.getStartTs() == 0L) { | ||
92 | + alarm.setStartTs(System.currentTimeMillis()); | ||
93 | + } | ||
94 | + if (alarm.getEndTs() == 0L) { | ||
95 | + alarm.setEndTs(alarm.getStartTs()); | ||
96 | + } | ||
97 | + if (alarm.getId() == null) { | ||
98 | + Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get(); | ||
99 | + if (existing == null || existing.getStatus().isCleared()) { | ||
100 | + return createAlarm(alarm); | ||
101 | + } else { | ||
102 | + return updateAlarm(existing, alarm); | ||
103 | + } | ||
104 | + } else { | ||
105 | + return updateAlarm(alarm).get(); | ||
106 | + } | ||
107 | + } catch (ExecutionException | InterruptedException e) { | ||
108 | + throw new RuntimeException(e); | ||
109 | + } | ||
110 | + } | ||
111 | + | ||
112 | + private Alarm createAlarm(Alarm alarm) throws InterruptedException, ExecutionException { | ||
113 | + log.debug("New Alarm : {}", alarm); | ||
114 | + Alarm saved = getData(alarmDao.save(new AlarmEntity(alarm))); | ||
115 | + EntityRelationsQuery query = new EntityRelationsQuery(); | ||
116 | + query.setParameters(new RelationsSearchParameters(saved.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); | ||
117 | + List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); | ||
118 | + for (EntityId parentId : parentEntities) { | ||
119 | + createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); | ||
120 | + createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); | ||
121 | + } | ||
122 | + createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); | ||
123 | + createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); | ||
124 | + return saved; | ||
125 | + } | ||
126 | + | ||
127 | + protected ListenableFuture<Alarm> updateAlarm(Alarm update) { | ||
128 | + alarmDataValidator.validate(update); | ||
129 | + return getAndUpdate(update.getId(), new Function<Alarm, Alarm>() { | ||
130 | + @Nullable | ||
131 | + @Override | ||
132 | + public Alarm apply(@Nullable Alarm alarm) { | ||
133 | + if (alarm == null) { | ||
134 | + return null; | ||
135 | + } else { | ||
136 | + return updateAlarm(alarm, update); | ||
137 | + } | ||
138 | + } | ||
139 | + }); | ||
140 | + } | ||
141 | + | ||
142 | + private Alarm updateAlarm(Alarm oldAlarm, Alarm newAlarm) { | ||
143 | + AlarmStatus oldStatus = oldAlarm.getStatus(); | ||
144 | + AlarmStatus newStatus = newAlarm.getStatus(); | ||
145 | + AlarmEntity result = alarmDao.save(new AlarmEntity(merge(oldAlarm, newAlarm))); | ||
146 | + if (oldStatus != newStatus) { | ||
147 | + updateRelations(oldAlarm, oldStatus, newStatus); | ||
148 | + } | ||
149 | + return result.toData(); | ||
150 | + } | ||
151 | + | ||
152 | + @Override | ||
153 | + public ListenableFuture<Boolean> ackAlarm(AlarmId alarmId, long ackTime) { | ||
154 | + return getAndUpdate(alarmId, new Function<Alarm, Boolean>() { | ||
155 | + @Nullable | ||
156 | + @Override | ||
157 | + public Boolean apply(@Nullable Alarm alarm) { | ||
158 | + if (alarm == null || alarm.getStatus().isAck()) { | ||
159 | + return false; | ||
160 | + } else { | ||
161 | + AlarmStatus oldStatus = alarm.getStatus(); | ||
162 | + AlarmStatus newStatus = oldStatus.isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK; | ||
163 | + alarm.setStatus(newStatus); | ||
164 | + alarm.setAckTs(ackTime); | ||
165 | + alarmDao.save(new AlarmEntity(alarm)); | ||
166 | + updateRelations(alarm, oldStatus, newStatus); | ||
167 | + return true; | ||
168 | + } | ||
169 | + } | ||
170 | + }); | ||
171 | + } | ||
172 | + | ||
173 | + @Override | ||
174 | + public ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, long clearTime) { | ||
175 | + return getAndUpdate(alarmId, new Function<Alarm, Boolean>() { | ||
176 | + @Nullable | ||
177 | + @Override | ||
178 | + public Boolean apply(@Nullable Alarm alarm) { | ||
179 | + if (alarm == null || alarm.getStatus().isCleared()) { | ||
180 | + return false; | ||
181 | + } else { | ||
182 | + AlarmStatus oldStatus = alarm.getStatus(); | ||
183 | + AlarmStatus newStatus = oldStatus.isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK; | ||
184 | + alarm.setStatus(newStatus); | ||
185 | + alarm.setClearTs(clearTime); | ||
186 | + alarmDao.save(new AlarmEntity(alarm)); | ||
187 | + updateRelations(alarm, oldStatus, newStatus); | ||
188 | + return true; | ||
189 | + } | ||
190 | + } | ||
191 | + }); | ||
192 | + } | ||
193 | + | ||
194 | + @Override | ||
195 | + public ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId) { | ||
196 | + log.trace("Executing findAlarmById [{}]", alarmId); | ||
197 | + validateId(alarmId, "Incorrect alarmId " + alarmId); | ||
198 | + return alarmDao.findAlarmByIdAsync(alarmId.getId()); | ||
199 | + } | ||
200 | + | ||
201 | + @Override | ||
202 | + public ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query) { | ||
203 | + ListenableFuture<List<Alarm>> alarms = alarmDao.findAlarms(query); | ||
204 | + return Futures.transform(alarms, new Function<List<Alarm>, TimePageData<Alarm>>() { | ||
205 | + @Nullable | ||
206 | + @Override | ||
207 | + public TimePageData<Alarm> apply(@Nullable List<Alarm> alarms) { | ||
208 | + return new TimePageData<>(alarms, query.getPageLink()); | ||
209 | + } | ||
210 | + }); | ||
211 | + } | ||
212 | + | ||
213 | + private void deleteRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException { | ||
214 | + log.debug("Deleting Alarm relation: {}", alarmRelation); | ||
215 | + relationService.deleteRelation(alarmRelation).get(); | ||
216 | + } | ||
217 | + | ||
218 | + private void createRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException { | ||
219 | + log.debug("Creating Alarm relation: {}", alarmRelation); | ||
220 | + relationService.saveRelation(alarmRelation).get(); | ||
221 | + } | ||
222 | + | ||
223 | + private Alarm merge(Alarm existing, Alarm alarm) { | ||
224 | + if (alarm.getStartTs() > existing.getEndTs()) { | ||
225 | + existing.setEndTs(alarm.getStartTs()); | ||
226 | + } | ||
227 | + if (alarm.getEndTs() > existing.getEndTs()) { | ||
228 | + existing.setEndTs(alarm.getEndTs()); | ||
229 | + } | ||
230 | + if (alarm.getClearTs() > existing.getClearTs()) { | ||
231 | + existing.setClearTs(alarm.getClearTs()); | ||
232 | + } | ||
233 | + if (alarm.getAckTs() > existing.getAckTs()) { | ||
234 | + existing.setAckTs(alarm.getAckTs()); | ||
235 | + } | ||
236 | + existing.setStatus(alarm.getStatus()); | ||
237 | + existing.setSeverity(alarm.getSeverity()); | ||
238 | + existing.setDetails(alarm.getDetails()); | ||
239 | + return existing; | ||
240 | + } | ||
241 | + | ||
242 | + private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) { | ||
243 | + try { | ||
244 | + EntityRelationsQuery query = new EntityRelationsQuery(); | ||
245 | + query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); | ||
246 | + List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); | ||
247 | + for (EntityId parentId : parentEntities) { | ||
248 | + deleteRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); | ||
249 | + createRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); | ||
250 | + } | ||
251 | + deleteRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); | ||
252 | + createRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); | ||
253 | + } catch (ExecutionException | InterruptedException e) { | ||
254 | + log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus); | ||
255 | + throw new RuntimeException(e); | ||
256 | + } | ||
257 | + } | ||
258 | + | ||
259 | + private <T> ListenableFuture<T> getAndUpdate(AlarmId alarmId, Function<Alarm, T> function) { | ||
260 | + validateId(alarmId, "Alarm id should be specified!"); | ||
261 | + ListenableFuture<Alarm> entity = alarmDao.findAlarmByIdAsync(alarmId.getId()); | ||
262 | + return Futures.transform(entity, function, readResultsProcessingExecutor); | ||
263 | + } | ||
264 | + | ||
265 | + private DataValidator<Alarm> alarmDataValidator = | ||
266 | + new DataValidator<Alarm>() { | ||
267 | + | ||
268 | + @Override | ||
269 | + protected void validateDataImpl(Alarm alarm) { | ||
270 | + if (StringUtils.isEmpty(alarm.getType())) { | ||
271 | + throw new DataValidationException("Alarm type should be specified!"); | ||
272 | + } | ||
273 | + if (alarm.getOriginator() == null) { | ||
274 | + throw new DataValidationException("Alarm originator should be specified!"); | ||
275 | + } | ||
276 | + if (alarm.getSeverity() == null) { | ||
277 | + throw new DataValidationException("Alarm severity should be specified!"); | ||
278 | + } | ||
279 | + if (alarm.getStatus() == null) { | ||
280 | + throw new DataValidationException("Alarm status should be specified!"); | ||
281 | + } | ||
282 | + if (alarm.getTenantId() == null) { | ||
283 | + throw new DataValidationException("Alarm should be assigned to tenant!"); | ||
284 | + } else { | ||
285 | + TenantEntity tenant = tenantDao.findById(alarm.getTenantId().getId()); | ||
286 | + if (tenant == null) { | ||
287 | + throw new DataValidationException("Alarm is referencing to non-existent tenant!"); | ||
288 | + } | ||
289 | + } | ||
290 | + } | ||
291 | + }; | ||
292 | +} |
@@ -16,12 +16,11 @@ | @@ -16,12 +16,11 @@ | ||
16 | package org.thingsboard.server.dao.asset; | 16 | package org.thingsboard.server.dao.asset; |
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | -import org.thingsboard.server.common.data.Device; | ||
20 | import org.thingsboard.server.common.data.asset.Asset; | 19 | import org.thingsboard.server.common.data.asset.Asset; |
21 | import org.thingsboard.server.common.data.page.TextPageLink; | 20 | import org.thingsboard.server.common.data.page.TextPageLink; |
22 | import org.thingsboard.server.dao.Dao; | 21 | import org.thingsboard.server.dao.Dao; |
23 | import org.thingsboard.server.dao.model.AssetEntity; | 22 | import org.thingsboard.server.dao.model.AssetEntity; |
24 | -import org.thingsboard.server.dao.model.DeviceEntity; | 23 | +import org.thingsboard.server.dao.model.TenantAssetTypeEntity; |
25 | 24 | ||
26 | import java.util.List; | 25 | import java.util.List; |
27 | import java.util.Optional; | 26 | import java.util.Optional; |
@@ -51,6 +50,16 @@ public interface AssetDao extends Dao<AssetEntity> { | @@ -51,6 +50,16 @@ public interface AssetDao extends Dao<AssetEntity> { | ||
51 | List<AssetEntity> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink); | 50 | List<AssetEntity> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink); |
52 | 51 | ||
53 | /** | 52 | /** |
53 | + * Find assets by tenantId, type and page link. | ||
54 | + * | ||
55 | + * @param tenantId the tenantId | ||
56 | + * @param type the type | ||
57 | + * @param pageLink the page link | ||
58 | + * @return the list of asset objects | ||
59 | + */ | ||
60 | + List<AssetEntity> findAssetsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink); | ||
61 | + | ||
62 | + /** | ||
54 | * Find assets by tenantId and assets Ids. | 63 | * Find assets by tenantId and assets Ids. |
55 | * | 64 | * |
56 | * @param tenantId the tenantId | 65 | * @param tenantId the tenantId |
@@ -70,6 +79,17 @@ public interface AssetDao extends Dao<AssetEntity> { | @@ -70,6 +79,17 @@ public interface AssetDao extends Dao<AssetEntity> { | ||
70 | List<AssetEntity> findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); | 79 | List<AssetEntity> findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); |
71 | 80 | ||
72 | /** | 81 | /** |
82 | + * Find assets by tenantId, customerId, type and page link. | ||
83 | + * | ||
84 | + * @param tenantId the tenantId | ||
85 | + * @param customerId the customerId | ||
86 | + * @param type the type | ||
87 | + * @param pageLink the page link | ||
88 | + * @return the list of asset objects | ||
89 | + */ | ||
90 | + List<AssetEntity> findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink); | ||
91 | + | ||
92 | + /** | ||
73 | * Find assets by tenantId, customerId and assets Ids. | 93 | * Find assets by tenantId, customerId and assets Ids. |
74 | * | 94 | * |
75 | * @param tenantId the tenantId | 95 | * @param tenantId the tenantId |
@@ -87,4 +107,12 @@ public interface AssetDao extends Dao<AssetEntity> { | @@ -87,4 +107,12 @@ public interface AssetDao extends Dao<AssetEntity> { | ||
87 | * @return the optional asset object | 107 | * @return the optional asset object |
88 | */ | 108 | */ |
89 | Optional<AssetEntity> findAssetsByTenantIdAndName(UUID tenantId, String name); | 109 | Optional<AssetEntity> findAssetsByTenantIdAndName(UUID tenantId, String name); |
110 | + | ||
111 | + /** | ||
112 | + * Find tenants asset types. | ||
113 | + * | ||
114 | + * @return the list of tenant asset type objects | ||
115 | + */ | ||
116 | + ListenableFuture<List<TenantAssetTypeEntity>> findTenantAssetTypesAsync(); | ||
117 | + | ||
90 | } | 118 | } |
@@ -15,7 +15,12 @@ | @@ -15,7 +15,12 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.asset; | 16 | package org.thingsboard.server.dao.asset; |
17 | 17 | ||
18 | +import com.datastax.driver.core.ResultSet; | ||
19 | +import com.datastax.driver.core.ResultSetFuture; | ||
18 | import com.datastax.driver.core.querybuilder.Select; | 20 | import com.datastax.driver.core.querybuilder.Select; |
21 | +import com.datastax.driver.mapping.Result; | ||
22 | +import com.google.common.base.Function; | ||
23 | +import com.google.common.util.concurrent.Futures; | ||
19 | import com.google.common.util.concurrent.ListenableFuture; | 24 | import com.google.common.util.concurrent.ListenableFuture; |
20 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
21 | import org.springframework.stereotype.Component; | 26 | import org.springframework.stereotype.Component; |
@@ -23,7 +28,9 @@ import org.thingsboard.server.common.data.asset.Asset; | @@ -23,7 +28,9 @@ import org.thingsboard.server.common.data.asset.Asset; | ||
23 | import org.thingsboard.server.common.data.page.TextPageLink; | 28 | import org.thingsboard.server.common.data.page.TextPageLink; |
24 | import org.thingsboard.server.dao.AbstractSearchTextDao; | 29 | import org.thingsboard.server.dao.AbstractSearchTextDao; |
25 | import org.thingsboard.server.dao.model.AssetEntity; | 30 | import org.thingsboard.server.dao.model.AssetEntity; |
31 | +import org.thingsboard.server.dao.model.TenantAssetTypeEntity; | ||
26 | 32 | ||
33 | +import javax.annotation.Nullable; | ||
27 | import java.util.*; | 34 | import java.util.*; |
28 | 35 | ||
29 | import static com.datastax.driver.core.querybuilder.QueryBuilder.*; | 36 | import static com.datastax.driver.core.querybuilder.QueryBuilder.*; |
@@ -60,6 +67,16 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | @@ -60,6 +67,16 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | ||
60 | } | 67 | } |
61 | 68 | ||
62 | @Override | 69 | @Override |
70 | + public List<AssetEntity> findAssetsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) { | ||
71 | + log.debug("Try to find assets by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink); | ||
72 | + List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | ||
73 | + Arrays.asList(eq(ASSET_TYPE_PROPERTY, type), | ||
74 | + eq(ASSET_TENANT_ID_PROPERTY, tenantId)), pageLink); | ||
75 | + log.trace("Found assets [{}] by tenantId [{}], type [{}] and pageLink [{}]", assetEntities, tenantId, type, pageLink); | ||
76 | + return assetEntities; | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
63 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List<UUID> assetIds) { | 80 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List<UUID> assetIds) { |
64 | log.debug("Try to find assets by tenantId [{}] and asset Ids [{}]", tenantId, assetIds); | 81 | log.debug("Try to find assets by tenantId [{}] and asset Ids [{}]", tenantId, assetIds); |
65 | Select select = select().from(getColumnFamilyName()); | 82 | Select select = select().from(getColumnFamilyName()); |
@@ -82,6 +99,19 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | @@ -82,6 +99,19 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | ||
82 | } | 99 | } |
83 | 100 | ||
84 | @Override | 101 | @Override |
102 | + public List<AssetEntity> findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) { | ||
103 | + log.debug("Try to find assets by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink); | ||
104 | + List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | ||
105 | + Arrays.asList(eq(ASSET_TYPE_PROPERTY, type), | ||
106 | + eq(ASSET_CUSTOMER_ID_PROPERTY, customerId), | ||
107 | + eq(ASSET_TENANT_ID_PROPERTY, tenantId)), | ||
108 | + pageLink); | ||
109 | + | ||
110 | + log.trace("Found assets [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", assetEntities, tenantId, customerId, type, pageLink); | ||
111 | + return assetEntities; | ||
112 | + } | ||
113 | + | ||
114 | + @Override | ||
85 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> assetIds) { | 115 | public ListenableFuture<List<AssetEntity>> findAssetsByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> assetIds) { |
86 | log.debug("Try to find assets by tenantId [{}], customerId [{}] and asset Ids [{}]", tenantId, customerId, assetIds); | 116 | log.debug("Try to find assets by tenantId [{}], customerId [{}] and asset Ids [{}]", tenantId, customerId, assetIds); |
87 | Select select = select().from(getColumnFamilyName()); | 117 | Select select = select().from(getColumnFamilyName()); |
@@ -101,4 +131,24 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | @@ -101,4 +131,24 @@ public class AssetDaoImpl extends AbstractSearchTextDao<AssetEntity> implements | ||
101 | return Optional.ofNullable(findOneByStatement(query)); | 131 | return Optional.ofNullable(findOneByStatement(query)); |
102 | } | 132 | } |
103 | 133 | ||
134 | + @Override | ||
135 | + public ListenableFuture<List<TenantAssetTypeEntity>> findTenantAssetTypesAsync() { | ||
136 | + Select statement = select().distinct().column(ASSET_TYPE_PROPERTY).column(ASSET_TENANT_ID_PROPERTY).from(ASSET_TYPES_BY_TENANT_VIEW_NAME); | ||
137 | + statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); | ||
138 | + ResultSetFuture resultSetFuture = getSession().executeAsync(statement); | ||
139 | + ListenableFuture<List<TenantAssetTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantAssetTypeEntity>>() { | ||
140 | + @Nullable | ||
141 | + @Override | ||
142 | + public List<TenantAssetTypeEntity> apply(@Nullable ResultSet resultSet) { | ||
143 | + Result<TenantAssetTypeEntity> result = cluster.getMapper(TenantAssetTypeEntity.class).map(resultSet); | ||
144 | + if (result != null) { | ||
145 | + return result.all(); | ||
146 | + } else { | ||
147 | + return Collections.emptyList(); | ||
148 | + } | ||
149 | + } | ||
150 | + }); | ||
151 | + return result; | ||
152 | + } | ||
153 | + | ||
104 | } | 154 | } |
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset; | @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset; | ||
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.asset.Asset; | 19 | import org.thingsboard.server.common.data.asset.Asset; |
20 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | ||
20 | import org.thingsboard.server.common.data.id.AssetId; | 21 | import org.thingsboard.server.common.data.id.AssetId; |
21 | import org.thingsboard.server.common.data.id.CustomerId; | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -34,7 +35,7 @@ public interface AssetService { | @@ -34,7 +35,7 @@ public interface AssetService { | ||
34 | 35 | ||
35 | Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name); | 36 | Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name); |
36 | 37 | ||
37 | - Asset saveAsset(Asset device); | 38 | + Asset saveAsset(Asset asset); |
38 | 39 | ||
39 | Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId); | 40 | Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId); |
40 | 41 | ||
@@ -44,16 +45,21 @@ public interface AssetService { | @@ -44,16 +45,21 @@ public interface AssetService { | ||
44 | 45 | ||
45 | TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink); | 46 | TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink); |
46 | 47 | ||
48 | + TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | ||
49 | + | ||
47 | ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); | 50 | ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); |
48 | 51 | ||
49 | void deleteAssetsByTenantId(TenantId tenantId); | 52 | void deleteAssetsByTenantId(TenantId tenantId); |
50 | 53 | ||
51 | TextPageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 54 | TextPageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); |
52 | 55 | ||
56 | + TextPageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink); | ||
57 | + | ||
53 | ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); | 58 | ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); |
54 | 59 | ||
55 | void unassignCustomerAssets(TenantId tenantId, CustomerId customerId); | 60 | void unassignCustomerAssets(TenantId tenantId, CustomerId customerId); |
56 | 61 | ||
57 | ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query); | 62 | ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query); |
58 | 63 | ||
64 | + ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId); | ||
59 | } | 65 | } |
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; | @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; | ||
26 | import org.springframework.util.StringUtils; | 26 | import org.springframework.util.StringUtils; |
27 | import org.thingsboard.server.common.data.EntityType; | 27 | import org.thingsboard.server.common.data.EntityType; |
28 | import org.thingsboard.server.common.data.asset.Asset; | 28 | import org.thingsboard.server.common.data.asset.Asset; |
29 | +import org.thingsboard.server.common.data.asset.TenantAssetType; | ||
29 | import org.thingsboard.server.common.data.id.AssetId; | 30 | import org.thingsboard.server.common.data.id.AssetId; |
30 | import org.thingsboard.server.common.data.id.CustomerId; | 31 | import org.thingsboard.server.common.data.id.CustomerId; |
31 | import org.thingsboard.server.common.data.id.EntityId; | 32 | import org.thingsboard.server.common.data.id.EntityId; |
@@ -34,12 +35,9 @@ import org.thingsboard.server.common.data.page.TextPageData; | @@ -34,12 +35,9 @@ import org.thingsboard.server.common.data.page.TextPageData; | ||
34 | import org.thingsboard.server.common.data.page.TextPageLink; | 35 | import org.thingsboard.server.common.data.page.TextPageLink; |
35 | import org.thingsboard.server.common.data.relation.EntityRelation; | 36 | import org.thingsboard.server.common.data.relation.EntityRelation; |
36 | import org.thingsboard.server.dao.customer.CustomerDao; | 37 | import org.thingsboard.server.dao.customer.CustomerDao; |
37 | -import org.thingsboard.server.dao.entity.BaseEntityService; | 38 | +import org.thingsboard.server.dao.entity.AbstractEntityService; |
38 | import org.thingsboard.server.dao.exception.DataValidationException; | 39 | import org.thingsboard.server.dao.exception.DataValidationException; |
39 | -import org.thingsboard.server.dao.model.AssetEntity; | ||
40 | -import org.thingsboard.server.dao.model.CustomerEntity; | ||
41 | -import org.thingsboard.server.dao.model.TenantEntity; | ||
42 | -import org.thingsboard.server.dao.relation.EntityRelationsQuery; | 40 | +import org.thingsboard.server.dao.model.*; |
43 | import org.thingsboard.server.dao.relation.EntitySearchDirection; | 41 | import org.thingsboard.server.dao.relation.EntitySearchDirection; |
44 | import org.thingsboard.server.dao.service.DataValidator; | 42 | import org.thingsboard.server.dao.service.DataValidator; |
45 | import org.thingsboard.server.dao.service.PaginatedRemover; | 43 | import org.thingsboard.server.dao.service.PaginatedRemover; |
@@ -57,7 +55,7 @@ import static org.thingsboard.server.dao.service.Validator.*; | @@ -57,7 +55,7 @@ import static org.thingsboard.server.dao.service.Validator.*; | ||
57 | 55 | ||
58 | @Service | 56 | @Service |
59 | @Slf4j | 57 | @Slf4j |
60 | -public class BaseAssetService extends BaseEntityService implements AssetService { | 58 | +public class BaseAssetService extends AbstractEntityService implements AssetService { |
61 | 59 | ||
62 | @Autowired | 60 | @Autowired |
63 | private AssetDao assetDao; | 61 | private AssetDao assetDao; |
@@ -132,7 +130,18 @@ public class BaseAssetService extends BaseEntityService implements AssetService | @@ -132,7 +130,18 @@ public class BaseAssetService extends BaseEntityService implements AssetService | ||
132 | validatePageLink(pageLink, "Incorrect page link " + pageLink); | 130 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
133 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantId(tenantId.getId(), pageLink); | 131 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantId(tenantId.getId(), pageLink); |
134 | List<Asset> assets = convertDataList(assetEntities); | 132 | List<Asset> assets = convertDataList(assetEntities); |
135 | - return new TextPageData<Asset>(assets, pageLink); | 133 | + return new TextPageData<>(assets, pageLink); |
134 | + } | ||
135 | + | ||
136 | + @Override | ||
137 | + public TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink) { | ||
138 | + log.trace("Executing findAssetsByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); | ||
139 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
140 | + validateString(type, "Incorrect type " + type); | ||
141 | + validatePageLink(pageLink, "Incorrect page link " + pageLink); | ||
142 | + List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndType(tenantId.getId(), type, pageLink); | ||
143 | + List<Asset> assets = convertDataList(assetEntities); | ||
144 | + return new TextPageData<>(assets, pageLink); | ||
136 | } | 145 | } |
137 | 146 | ||
138 | @Override | 147 | @Override |
@@ -159,7 +168,19 @@ public class BaseAssetService extends BaseEntityService implements AssetService | @@ -159,7 +168,19 @@ public class BaseAssetService extends BaseEntityService implements AssetService | ||
159 | validatePageLink(pageLink, "Incorrect page link " + pageLink); | 168 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
160 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); | 169 | List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); |
161 | List<Asset> assets = convertDataList(assetEntities); | 170 | List<Asset> assets = convertDataList(assetEntities); |
162 | - return new TextPageData<Asset>(assets, pageLink); | 171 | + return new TextPageData<>(assets, pageLink); |
172 | + } | ||
173 | + | ||
174 | + @Override | ||
175 | + public TextPageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink) { | ||
176 | + log.trace("Executing findAssetsByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink); | ||
177 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
178 | + validateId(customerId, "Incorrect customerId " + customerId); | ||
179 | + validateString(type, "Incorrect type " + type); | ||
180 | + validatePageLink(pageLink, "Incorrect page link " + pageLink); | ||
181 | + List<AssetEntity> assetEntities = assetDao.findAssetsByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink); | ||
182 | + List<Asset> assets = convertDataList(assetEntities); | ||
183 | + return new TextPageData<>(assets, pageLink); | ||
163 | } | 184 | } |
164 | 185 | ||
165 | @Override | 186 | @Override |
@@ -207,6 +228,25 @@ public class BaseAssetService extends BaseEntityService implements AssetService | @@ -207,6 +228,25 @@ public class BaseAssetService extends BaseEntityService implements AssetService | ||
207 | return assets; | 228 | return assets; |
208 | } | 229 | } |
209 | 230 | ||
231 | + @Override | ||
232 | + public ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId) { | ||
233 | + log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId); | ||
234 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
235 | + ListenableFuture<List<TenantAssetTypeEntity>> tenantAssetTypeEntities = assetDao.findTenantAssetTypesAsync(); | ||
236 | + ListenableFuture<List<TenantAssetType>> tenantAssetTypes = Futures.transform(tenantAssetTypeEntities, | ||
237 | + (Function<List<TenantAssetTypeEntity>, List<TenantAssetType>>) assetTypeEntities -> { | ||
238 | + List<TenantAssetType> assetTypes = new ArrayList<>(); | ||
239 | + for (TenantAssetTypeEntity assetTypeEntity : assetTypeEntities) { | ||
240 | + if (assetTypeEntity.getTenantId().equals(tenantId.getId())) { | ||
241 | + assetTypes.add(assetTypeEntity.toTenantAssetType()); | ||
242 | + } | ||
243 | + } | ||
244 | + assetTypes.sort((TenantAssetType o1, TenantAssetType o2) -> o1.getType().compareTo(o2.getType())); | ||
245 | + return assetTypes; | ||
246 | + }); | ||
247 | + return tenantAssetTypes; | ||
248 | + } | ||
249 | + | ||
210 | private DataValidator<Asset> assetValidator = | 250 | private DataValidator<Asset> assetValidator = |
211 | new DataValidator<Asset>() { | 251 | new DataValidator<Asset>() { |
212 | 252 | ||
@@ -232,6 +272,9 @@ public class BaseAssetService extends BaseEntityService implements AssetService | @@ -232,6 +272,9 @@ public class BaseAssetService extends BaseEntityService implements AssetService | ||
232 | 272 | ||
233 | @Override | 273 | @Override |
234 | protected void validateDataImpl(Asset asset) { | 274 | protected void validateDataImpl(Asset asset) { |
275 | + if (StringUtils.isEmpty(asset.getType())) { | ||
276 | + throw new DataValidationException("Asset type should be specified!"); | ||
277 | + } | ||
235 | if (StringUtils.isEmpty(asset.getName())) { | 278 | if (StringUtils.isEmpty(asset.getName())) { |
236 | throw new DataValidationException("Asset name should be specified!"); | 279 | throw new DataValidationException("Asset name should be specified!"); |
237 | } | 280 | } |
@@ -45,7 +45,6 @@ public class ServiceCacheConfiguration { | @@ -45,7 +45,6 @@ public class ServiceCacheConfiguration { | ||
45 | @Value("${cache.device_credentials.time_to_live}") | 45 | @Value("${cache.device_credentials.time_to_live}") |
46 | private Integer cacheDeviceCredentialsTTL; | 46 | private Integer cacheDeviceCredentialsTTL; |
47 | 47 | ||
48 | - | ||
49 | @Value("${zk.enabled}") | 48 | @Value("${zk.enabled}") |
50 | private boolean zkEnabled; | 49 | private boolean zkEnabled; |
51 | @Value("${zk.url}") | 50 | @Value("${zk.url}") |
@@ -31,17 +31,15 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -31,17 +31,15 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
31 | import lombok.extern.slf4j.Slf4j; | 31 | import lombok.extern.slf4j.Slf4j; |
32 | import org.apache.commons.lang3.StringUtils; | 32 | import org.apache.commons.lang3.StringUtils; |
33 | import org.thingsboard.server.common.data.Customer; | 33 | import org.thingsboard.server.common.data.Customer; |
34 | -import org.thingsboard.server.common.data.asset.Asset; | ||
35 | import org.thingsboard.server.common.data.id.CustomerId; | 34 | import org.thingsboard.server.common.data.id.CustomerId; |
36 | import org.thingsboard.server.common.data.id.TenantId; | 35 | import org.thingsboard.server.common.data.id.TenantId; |
37 | import org.thingsboard.server.common.data.page.TextPageData; | 36 | import org.thingsboard.server.common.data.page.TextPageData; |
38 | import org.thingsboard.server.common.data.page.TextPageLink; | 37 | import org.thingsboard.server.common.data.page.TextPageLink; |
39 | import org.thingsboard.server.dao.dashboard.DashboardService; | 38 | import org.thingsboard.server.dao.dashboard.DashboardService; |
40 | import org.thingsboard.server.dao.device.DeviceService; | 39 | import org.thingsboard.server.dao.device.DeviceService; |
41 | -import org.thingsboard.server.dao.entity.BaseEntityService; | 40 | +import org.thingsboard.server.dao.entity.AbstractEntityService; |
42 | import org.thingsboard.server.dao.exception.DataValidationException; | 41 | import org.thingsboard.server.dao.exception.DataValidationException; |
43 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 42 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
44 | -import org.thingsboard.server.dao.model.AssetEntity; | ||
45 | import org.thingsboard.server.dao.model.CustomerEntity; | 43 | import org.thingsboard.server.dao.model.CustomerEntity; |
46 | import org.thingsboard.server.dao.model.TenantEntity; | 44 | import org.thingsboard.server.dao.model.TenantEntity; |
47 | import org.thingsboard.server.dao.service.DataValidator; | 45 | import org.thingsboard.server.dao.service.DataValidator; |
@@ -53,7 +51,7 @@ import org.springframework.stereotype.Service; | @@ -53,7 +51,7 @@ import org.springframework.stereotype.Service; | ||
53 | import org.thingsboard.server.dao.service.Validator; | 51 | import org.thingsboard.server.dao.service.Validator; |
54 | @Service | 52 | @Service |
55 | @Slf4j | 53 | @Slf4j |
56 | -public class CustomerServiceImpl extends BaseEntityService implements CustomerService { | 54 | +public class CustomerServiceImpl extends AbstractEntityService implements CustomerService { |
57 | 55 | ||
58 | private static final String PUBLIC_CUSTOMER_TITLE = "Public"; | 56 | private static final String PUBLIC_CUSTOMER_TITLE = "Public"; |
59 | 57 |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.dashboard; | 16 | package org.thingsboard.server.dao.dashboard; |
17 | 17 | ||
18 | +import com.google.common.util.concurrent.ListenableFuture; | ||
18 | import org.thingsboard.server.common.data.Dashboard; | 19 | import org.thingsboard.server.common.data.Dashboard; |
19 | import org.thingsboard.server.common.data.DashboardInfo; | 20 | import org.thingsboard.server.common.data.DashboardInfo; |
20 | import org.thingsboard.server.common.data.id.CustomerId; | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
@@ -27,8 +28,12 @@ public interface DashboardService { | @@ -27,8 +28,12 @@ public interface DashboardService { | ||
27 | 28 | ||
28 | public Dashboard findDashboardById(DashboardId dashboardId); | 29 | public Dashboard findDashboardById(DashboardId dashboardId); |
29 | 30 | ||
31 | + public ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId); | ||
32 | + | ||
30 | public DashboardInfo findDashboardInfoById(DashboardId dashboardId); | 33 | public DashboardInfo findDashboardInfoById(DashboardId dashboardId); |
31 | 34 | ||
35 | + public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId); | ||
36 | + | ||
32 | public Dashboard saveDashboard(Dashboard dashboard); | 37 | public Dashboard saveDashboard(Dashboard dashboard); |
33 | 38 | ||
34 | public Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId); | 39 | public Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId); |
@@ -17,9 +17,13 @@ package org.thingsboard.server.dao.dashboard; | @@ -17,9 +17,13 @@ package org.thingsboard.server.dao.dashboard; | ||
17 | 17 | ||
18 | import static org.thingsboard.server.dao.DaoUtil.convertDataList; | 18 | import static org.thingsboard.server.dao.DaoUtil.convertDataList; |
19 | import static org.thingsboard.server.dao.DaoUtil.getData; | 19 | import static org.thingsboard.server.dao.DaoUtil.getData; |
20 | +import static org.thingsboard.server.dao.service.Validator.validateId; | ||
20 | 21 | ||
21 | import java.util.List; | 22 | import java.util.List; |
22 | 23 | ||
24 | +import com.google.common.base.Function; | ||
25 | +import com.google.common.util.concurrent.Futures; | ||
26 | +import com.google.common.util.concurrent.ListenableFuture; | ||
23 | import lombok.extern.slf4j.Slf4j; | 27 | import lombok.extern.slf4j.Slf4j; |
24 | import org.apache.commons.lang3.StringUtils; | 28 | import org.apache.commons.lang3.StringUtils; |
25 | import org.thingsboard.server.common.data.Dashboard; | 29 | import org.thingsboard.server.common.data.Dashboard; |
@@ -30,7 +34,7 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -30,7 +34,7 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
30 | import org.thingsboard.server.common.data.page.TextPageData; | 34 | import org.thingsboard.server.common.data.page.TextPageData; |
31 | import org.thingsboard.server.common.data.page.TextPageLink; | 35 | import org.thingsboard.server.common.data.page.TextPageLink; |
32 | import org.thingsboard.server.dao.customer.CustomerDao; | 36 | import org.thingsboard.server.dao.customer.CustomerDao; |
33 | -import org.thingsboard.server.dao.entity.BaseEntityService; | 37 | +import org.thingsboard.server.dao.entity.AbstractEntityService; |
34 | import org.thingsboard.server.dao.exception.DataValidationException; | 38 | import org.thingsboard.server.dao.exception.DataValidationException; |
35 | import org.thingsboard.server.dao.model.*; | 39 | import org.thingsboard.server.dao.model.*; |
36 | import org.thingsboard.server.dao.service.DataValidator; | 40 | import org.thingsboard.server.dao.service.DataValidator; |
@@ -42,7 +46,7 @@ import org.thingsboard.server.dao.service.Validator; | @@ -42,7 +46,7 @@ import org.thingsboard.server.dao.service.Validator; | ||
42 | 46 | ||
43 | @Service | 47 | @Service |
44 | @Slf4j | 48 | @Slf4j |
45 | -public class DashboardServiceImpl extends BaseEntityService implements DashboardService { | 49 | +public class DashboardServiceImpl extends AbstractEntityService implements DashboardService { |
46 | 50 | ||
47 | @Autowired | 51 | @Autowired |
48 | private DashboardDao dashboardDao; | 52 | private DashboardDao dashboardDao; |
@@ -65,6 +69,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard | @@ -65,6 +69,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard | ||
65 | } | 69 | } |
66 | 70 | ||
67 | @Override | 71 | @Override |
72 | + public ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId) { | ||
73 | + log.trace("Executing findDashboardByIdAsync [{}]", dashboardId); | ||
74 | + validateId(dashboardId, "Incorrect dashboardId " + dashboardId); | ||
75 | + ListenableFuture<DashboardEntity> dashboardEntity = dashboardDao.findByIdAsync(dashboardId.getId()); | ||
76 | + return Futures.transform(dashboardEntity, (Function<? super DashboardEntity, ? extends Dashboard>) input -> getData(input)); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
68 | public DashboardInfo findDashboardInfoById(DashboardId dashboardId) { | 80 | public DashboardInfo findDashboardInfoById(DashboardId dashboardId) { |
69 | log.trace("Executing findDashboardInfoById [{}]", dashboardId); | 81 | log.trace("Executing findDashboardInfoById [{}]", dashboardId); |
70 | Validator.validateId(dashboardId, "Incorrect dashboardId " + dashboardId); | 82 | Validator.validateId(dashboardId, "Incorrect dashboardId " + dashboardId); |
@@ -73,6 +85,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard | @@ -73,6 +85,14 @@ public class DashboardServiceImpl extends BaseEntityService implements Dashboard | ||
73 | } | 85 | } |
74 | 86 | ||
75 | @Override | 87 | @Override |
88 | + public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId) { | ||
89 | + log.trace("Executing findDashboardInfoByIdAsync [{}]", dashboardId); | ||
90 | + validateId(dashboardId, "Incorrect dashboardId " + dashboardId); | ||
91 | + ListenableFuture<DashboardInfoEntity> dashboardInfoEntity = dashboardInfoDao.findByIdAsync(dashboardId.getId()); | ||
92 | + return Futures.transform(dashboardInfoEntity, (Function<? super DashboardInfoEntity, ? extends DashboardInfo>) input -> getData(input)); | ||
93 | + } | ||
94 | + | ||
95 | + @Override | ||
76 | public Dashboard saveDashboard(Dashboard dashboard) { | 96 | public Dashboard saveDashboard(Dashboard dashboard) { |
77 | log.trace("Executing saveDashboard [{}]", dashboard); | 97 | log.trace("Executing saveDashboard [{}]", dashboard); |
78 | dashboardValidator.validate(dashboard); | 98 | dashboardValidator.validate(dashboard); |
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device; | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device; | ||
24 | import org.thingsboard.server.common.data.page.TextPageLink; | 24 | import org.thingsboard.server.common.data.page.TextPageLink; |
25 | import org.thingsboard.server.dao.Dao; | 25 | import org.thingsboard.server.dao.Dao; |
26 | import org.thingsboard.server.dao.model.DeviceEntity; | 26 | import org.thingsboard.server.dao.model.DeviceEntity; |
27 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | ||
27 | 28 | ||
28 | /** | 29 | /** |
29 | * The Interface DeviceDao. | 30 | * The Interface DeviceDao. |
@@ -49,6 +50,16 @@ public interface DeviceDao extends Dao<DeviceEntity> { | @@ -49,6 +50,16 @@ public interface DeviceDao extends Dao<DeviceEntity> { | ||
49 | List<DeviceEntity> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink); | 50 | List<DeviceEntity> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink); |
50 | 51 | ||
51 | /** | 52 | /** |
53 | + * Find devices by tenantId, type and page link. | ||
54 | + * | ||
55 | + * @param tenantId the tenantId | ||
56 | + * @param type the type | ||
57 | + * @param pageLink the page link | ||
58 | + * @return the list of device objects | ||
59 | + */ | ||
60 | + List<DeviceEntity> findDevicesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink); | ||
61 | + | ||
62 | + /** | ||
52 | * Find devices by tenantId and devices Ids. | 63 | * Find devices by tenantId and devices Ids. |
53 | * | 64 | * |
54 | * @param tenantId the tenantId | 65 | * @param tenantId the tenantId |
@@ -68,6 +79,18 @@ public interface DeviceDao extends Dao<DeviceEntity> { | @@ -68,6 +79,18 @@ public interface DeviceDao extends Dao<DeviceEntity> { | ||
68 | List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); | 79 | List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink); |
69 | 80 | ||
70 | /** | 81 | /** |
82 | + * Find devices by tenantId, customerId, type and page link. | ||
83 | + * | ||
84 | + * @param tenantId the tenantId | ||
85 | + * @param customerId the customerId | ||
86 | + * @param type the type | ||
87 | + * @param pageLink the page link | ||
88 | + * @return the list of device objects | ||
89 | + */ | ||
90 | + List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink); | ||
91 | + | ||
92 | + | ||
93 | + /** | ||
71 | * Find devices by tenantId, customerId and devices Ids. | 94 | * Find devices by tenantId, customerId and devices Ids. |
72 | * | 95 | * |
73 | * @param tenantId the tenantId | 96 | * @param tenantId the tenantId |
@@ -85,4 +108,11 @@ public interface DeviceDao extends Dao<DeviceEntity> { | @@ -85,4 +108,11 @@ public interface DeviceDao extends Dao<DeviceEntity> { | ||
85 | * @return the optional device object | 108 | * @return the optional device object |
86 | */ | 109 | */ |
87 | Optional<DeviceEntity> findDevicesByTenantIdAndName(UUID tenantId, String name); | 110 | Optional<DeviceEntity> findDevicesByTenantIdAndName(UUID tenantId, String name); |
111 | + | ||
112 | + /** | ||
113 | + * Find tenants device types. | ||
114 | + * | ||
115 | + * @return the list of tenant device type objects | ||
116 | + */ | ||
117 | + ListenableFuture<List<TenantDeviceTypeEntity>> findTenantDeviceTypesAsync(); | ||
88 | } | 118 | } |
@@ -22,7 +22,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.*; | @@ -22,7 +22,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.*; | ||
22 | 22 | ||
23 | import java.util.*; | 23 | import java.util.*; |
24 | 24 | ||
25 | +import com.datastax.driver.core.ResultSet; | ||
26 | +import com.datastax.driver.core.ResultSetFuture; | ||
25 | import com.datastax.driver.core.querybuilder.Select; | 27 | import com.datastax.driver.core.querybuilder.Select; |
28 | +import com.datastax.driver.mapping.Result; | ||
29 | +import com.google.common.base.Function; | ||
30 | +import com.google.common.util.concurrent.Futures; | ||
26 | import com.google.common.util.concurrent.ListenableFuture; | 31 | import com.google.common.util.concurrent.ListenableFuture; |
27 | import lombok.extern.slf4j.Slf4j; | 32 | import lombok.extern.slf4j.Slf4j; |
28 | import org.springframework.stereotype.Component; | 33 | import org.springframework.stereotype.Component; |
@@ -32,6 +37,9 @@ import org.thingsboard.server.dao.AbstractSearchTextDao; | @@ -32,6 +37,9 @@ import org.thingsboard.server.dao.AbstractSearchTextDao; | ||
32 | import org.thingsboard.server.dao.model.DeviceEntity; | 37 | import org.thingsboard.server.dao.model.DeviceEntity; |
33 | import org.slf4j.Logger; | 38 | import org.slf4j.Logger; |
34 | import org.slf4j.LoggerFactory; | 39 | import org.slf4j.LoggerFactory; |
40 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | ||
41 | + | ||
42 | +import javax.annotation.Nullable; | ||
35 | 43 | ||
36 | @Component | 44 | @Component |
37 | @Slf4j | 45 | @Slf4j |
@@ -64,6 +72,16 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | @@ -64,6 +72,16 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | ||
64 | } | 72 | } |
65 | 73 | ||
66 | @Override | 74 | @Override |
75 | + public List<DeviceEntity> findDevicesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) { | ||
76 | + log.debug("Try to find devices by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink); | ||
77 | + List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | ||
78 | + Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type), | ||
79 | + eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), pageLink); | ||
80 | + log.trace("Found devices [{}] by tenantId [{}], type [{}] and pageLink [{}]", deviceEntities, tenantId, type, pageLink); | ||
81 | + return deviceEntities; | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
67 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) { | 85 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) { |
68 | log.debug("Try to find devices by tenantId [{}] and device Ids [{}]", tenantId, deviceIds); | 86 | log.debug("Try to find devices by tenantId [{}] and device Ids [{}]", tenantId, deviceIds); |
69 | Select select = select().from(getColumnFamilyName()); | 87 | Select select = select().from(getColumnFamilyName()); |
@@ -75,7 +93,7 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | @@ -75,7 +93,7 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | ||
75 | 93 | ||
76 | @Override | 94 | @Override |
77 | public List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) { | 95 | public List<DeviceEntity> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) { |
78 | - log.debug("Try to find devices by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink); | 96 | + log.debug("Try to find devices by tenantId [{}], customerId [{}] and pageLink [{}]", tenantId, customerId, pageLink); |
79 | List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | 97 | List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, |
80 | Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId), | 98 | Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId), |
81 | eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), | 99 | eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), |
@@ -86,6 +104,19 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | @@ -86,6 +104,19 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | ||
86 | } | 104 | } |
87 | 105 | ||
88 | @Override | 106 | @Override |
107 | + public List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) { | ||
108 | + log.debug("Try to find devices by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink); | ||
109 | + List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | ||
110 | + Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type), | ||
111 | + eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId), | ||
112 | + eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), | ||
113 | + pageLink); | ||
114 | + | ||
115 | + log.trace("Found devices [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", deviceEntities, tenantId, customerId, type, pageLink); | ||
116 | + return deviceEntities; | ||
117 | + } | ||
118 | + | ||
119 | + @Override | ||
89 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) { | 120 | public ListenableFuture<List<DeviceEntity>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) { |
90 | log.debug("Try to find devices by tenantId [{}], customerId [{}] and device Ids [{}]", tenantId, customerId, deviceIds); | 121 | log.debug("Try to find devices by tenantId [{}], customerId [{}] and device Ids [{}]", tenantId, customerId, deviceIds); |
91 | Select select = select().from(getColumnFamilyName()); | 122 | Select select = select().from(getColumnFamilyName()); |
@@ -105,4 +136,24 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | @@ -105,4 +136,24 @@ public class DeviceDaoImpl extends AbstractSearchTextDao<DeviceEntity> implement | ||
105 | return Optional.ofNullable(findOneByStatement(query)); | 136 | return Optional.ofNullable(findOneByStatement(query)); |
106 | } | 137 | } |
107 | 138 | ||
139 | + @Override | ||
140 | + public ListenableFuture<List<TenantDeviceTypeEntity>> findTenantDeviceTypesAsync() { | ||
141 | + Select statement = select().distinct().column(DEVICE_TYPE_PROPERTY).column(DEVICE_TENANT_ID_PROPERTY).from(DEVICE_TYPES_BY_TENANT_VIEW_NAME); | ||
142 | + statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); | ||
143 | + ResultSetFuture resultSetFuture = getSession().executeAsync(statement); | ||
144 | + ListenableFuture<List<TenantDeviceTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantDeviceTypeEntity>>() { | ||
145 | + @Nullable | ||
146 | + @Override | ||
147 | + public List<TenantDeviceTypeEntity> apply(@Nullable ResultSet resultSet) { | ||
148 | + Result<TenantDeviceTypeEntity> result = cluster.getMapper(TenantDeviceTypeEntity.class).map(resultSet); | ||
149 | + if (result != null) { | ||
150 | + return result.all(); | ||
151 | + } else { | ||
152 | + return Collections.emptyList(); | ||
153 | + } | ||
154 | + } | ||
155 | + }); | ||
156 | + return result; | ||
157 | + } | ||
158 | + | ||
108 | } | 159 | } |
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device; | @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device; | ||
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
20 | +import org.thingsboard.server.common.data.TenantDeviceType; | ||
20 | import org.thingsboard.server.common.data.id.CustomerId; | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | import org.thingsboard.server.common.data.id.DeviceId; | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -44,16 +45,22 @@ public interface DeviceService { | @@ -44,16 +45,22 @@ public interface DeviceService { | ||
44 | 45 | ||
45 | TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink); | 46 | TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink); |
46 | 47 | ||
48 | + TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | ||
49 | + | ||
47 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); | 50 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); |
48 | 51 | ||
49 | void deleteDevicesByTenantId(TenantId tenantId); | 52 | void deleteDevicesByTenantId(TenantId tenantId); |
50 | 53 | ||
51 | TextPageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 54 | TextPageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); |
52 | 55 | ||
56 | + TextPageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink); | ||
57 | + | ||
53 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); | 58 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); |
54 | 59 | ||
55 | void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); | 60 | void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); |
56 | 61 | ||
57 | ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query); | 62 | ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query); |
58 | 63 | ||
64 | + ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId); | ||
65 | + | ||
59 | } | 66 | } |
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; | @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; | ||
26 | import org.springframework.util.StringUtils; | 26 | import org.springframework.util.StringUtils; |
27 | import org.thingsboard.server.common.data.Device; | 27 | import org.thingsboard.server.common.data.Device; |
28 | import org.thingsboard.server.common.data.EntityType; | 28 | import org.thingsboard.server.common.data.EntityType; |
29 | +import org.thingsboard.server.common.data.TenantDeviceType; | ||
29 | import org.thingsboard.server.common.data.id.CustomerId; | 30 | import org.thingsboard.server.common.data.id.CustomerId; |
30 | import org.thingsboard.server.common.data.id.DeviceId; | 31 | import org.thingsboard.server.common.data.id.DeviceId; |
31 | import org.thingsboard.server.common.data.id.EntityId; | 32 | import org.thingsboard.server.common.data.id.EntityId; |
@@ -36,10 +37,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | @@ -36,10 +37,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | ||
36 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 37 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
37 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 38 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
38 | import org.thingsboard.server.dao.customer.CustomerDao; | 39 | import org.thingsboard.server.dao.customer.CustomerDao; |
39 | -import org.thingsboard.server.dao.entity.BaseEntityService; | 40 | +import org.thingsboard.server.dao.entity.AbstractEntityService; |
40 | import org.thingsboard.server.dao.exception.DataValidationException; | 41 | import org.thingsboard.server.dao.exception.DataValidationException; |
41 | import org.thingsboard.server.dao.model.CustomerEntity; | 42 | import org.thingsboard.server.dao.model.CustomerEntity; |
42 | import org.thingsboard.server.dao.model.DeviceEntity; | 43 | import org.thingsboard.server.dao.model.DeviceEntity; |
44 | +import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; | ||
43 | import org.thingsboard.server.dao.model.TenantEntity; | 45 | import org.thingsboard.server.dao.model.TenantEntity; |
44 | import org.thingsboard.server.dao.relation.EntitySearchDirection; | 46 | import org.thingsboard.server.dao.relation.EntitySearchDirection; |
45 | import org.thingsboard.server.dao.service.DataValidator; | 47 | import org.thingsboard.server.dao.service.DataValidator; |
@@ -47,9 +49,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | @@ -47,9 +49,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | ||
47 | import org.thingsboard.server.dao.tenant.TenantDao; | 49 | import org.thingsboard.server.dao.tenant.TenantDao; |
48 | 50 | ||
49 | import javax.annotation.Nullable; | 51 | import javax.annotation.Nullable; |
50 | -import java.util.ArrayList; | ||
51 | -import java.util.List; | ||
52 | -import java.util.Optional; | 52 | +import java.util.*; |
53 | import java.util.stream.Collectors; | 53 | import java.util.stream.Collectors; |
54 | 54 | ||
55 | import static org.thingsboard.server.dao.DaoUtil.*; | 55 | import static org.thingsboard.server.dao.DaoUtil.*; |
@@ -58,7 +58,7 @@ import static org.thingsboard.server.dao.service.Validator.*; | @@ -58,7 +58,7 @@ import static org.thingsboard.server.dao.service.Validator.*; | ||
58 | 58 | ||
59 | @Service | 59 | @Service |
60 | @Slf4j | 60 | @Slf4j |
61 | -public class DeviceServiceImpl extends BaseEntityService implements DeviceService { | 61 | +public class DeviceServiceImpl extends AbstractEntityService implements DeviceService { |
62 | 62 | ||
63 | @Autowired | 63 | @Autowired |
64 | private DeviceDao deviceDao; | 64 | private DeviceDao deviceDao; |
@@ -148,7 +148,18 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | @@ -148,7 +148,18 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | ||
148 | validatePageLink(pageLink, "Incorrect page link " + pageLink); | 148 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
149 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantId(tenantId.getId(), pageLink); | 149 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantId(tenantId.getId(), pageLink); |
150 | List<Device> devices = convertDataList(deviceEntities); | 150 | List<Device> devices = convertDataList(deviceEntities); |
151 | - return new TextPageData<Device>(devices, pageLink); | 151 | + return new TextPageData<>(devices, pageLink); |
152 | + } | ||
153 | + | ||
154 | + @Override | ||
155 | + public TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink) { | ||
156 | + log.trace("Executing findDevicesByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); | ||
157 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
158 | + validateString(type, "Incorrect type " + type); | ||
159 | + validatePageLink(pageLink, "Incorrect page link " + pageLink); | ||
160 | + List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndType(tenantId.getId(), type, pageLink); | ||
161 | + List<Device> devices = convertDataList(deviceEntities); | ||
162 | + return new TextPageData<>(devices, pageLink); | ||
152 | } | 163 | } |
153 | 164 | ||
154 | @Override | 165 | @Override |
@@ -176,7 +187,19 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | @@ -176,7 +187,19 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | ||
176 | validatePageLink(pageLink, "Incorrect page link " + pageLink); | 187 | validatePageLink(pageLink, "Incorrect page link " + pageLink); |
177 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); | 188 | List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); |
178 | List<Device> devices = convertDataList(deviceEntities); | 189 | List<Device> devices = convertDataList(deviceEntities); |
179 | - return new TextPageData<Device>(devices, pageLink); | 190 | + return new TextPageData<>(devices, pageLink); |
191 | + } | ||
192 | + | ||
193 | + @Override | ||
194 | + public TextPageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink) { | ||
195 | + log.trace("Executing findDevicesByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink); | ||
196 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
197 | + validateId(customerId, "Incorrect customerId " + customerId); | ||
198 | + validateString(type, "Incorrect type " + type); | ||
199 | + validatePageLink(pageLink, "Incorrect page link " + pageLink); | ||
200 | + List<DeviceEntity> deviceEntities = deviceDao.findDevicesByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink); | ||
201 | + List<Device> devices = convertDataList(deviceEntities); | ||
202 | + return new TextPageData<>(devices, pageLink); | ||
180 | } | 203 | } |
181 | 204 | ||
182 | @Override | 205 | @Override |
@@ -224,6 +247,25 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | @@ -224,6 +247,25 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | ||
224 | return devices; | 247 | return devices; |
225 | } | 248 | } |
226 | 249 | ||
250 | + @Override | ||
251 | + public ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId) { | ||
252 | + log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId); | ||
253 | + validateId(tenantId, "Incorrect tenantId " + tenantId); | ||
254 | + ListenableFuture<List<TenantDeviceTypeEntity>> tenantDeviceTypeEntities = deviceDao.findTenantDeviceTypesAsync(); | ||
255 | + ListenableFuture<List<TenantDeviceType>> tenantDeviceTypes = Futures.transform(tenantDeviceTypeEntities, | ||
256 | + (Function<List<TenantDeviceTypeEntity>, List<TenantDeviceType>>) deviceTypeEntities -> { | ||
257 | + List<TenantDeviceType> deviceTypes = new ArrayList<>(); | ||
258 | + for (TenantDeviceTypeEntity deviceTypeEntity : deviceTypeEntities) { | ||
259 | + if (deviceTypeEntity.getTenantId().equals(tenantId.getId())) { | ||
260 | + deviceTypes.add(deviceTypeEntity.toTenantDeviceType()); | ||
261 | + } | ||
262 | + } | ||
263 | + deviceTypes.sort((TenantDeviceType o1, TenantDeviceType o2) -> o1.getType().compareTo(o2.getType())); | ||
264 | + return deviceTypes; | ||
265 | + }); | ||
266 | + return tenantDeviceTypes; | ||
267 | + } | ||
268 | + | ||
227 | private DataValidator<Device> deviceValidator = | 269 | private DataValidator<Device> deviceValidator = |
228 | new DataValidator<Device>() { | 270 | new DataValidator<Device>() { |
229 | 271 | ||
@@ -249,6 +291,9 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | @@ -249,6 +291,9 @@ public class DeviceServiceImpl extends BaseEntityService implements DeviceServic | ||
249 | 291 | ||
250 | @Override | 292 | @Override |
251 | protected void validateDataImpl(Device device) { | 293 | protected void validateDataImpl(Device device) { |
294 | + if (StringUtils.isEmpty(device.getType())) { | ||
295 | + throw new DataValidationException("Device type should be specified!"); | ||
296 | + } | ||
252 | if (StringUtils.isEmpty(device.getName())) { | 297 | if (StringUtils.isEmpty(device.getName())) { |
253 | throw new DataValidationException("Device name should be specified!"); | 298 | throw new DataValidationException("Device name should be specified!"); |
254 | } | 299 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.dao.entity; | ||
18 | + | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.springframework.beans.factory.annotation.Autowired; | ||
21 | +import org.thingsboard.server.common.data.id.EntityId; | ||
22 | +import org.thingsboard.server.dao.relation.RelationService; | ||
23 | + | ||
24 | +@Slf4j | ||
25 | +public abstract class AbstractEntityService { | ||
26 | + | ||
27 | + @Autowired | ||
28 | + protected RelationService relationService; | ||
29 | + | ||
30 | + protected void deleteEntityRelations(EntityId entityId) { | ||
31 | + log.trace("Executing deleteEntityRelations [{}]", entityId); | ||
32 | + relationService.deleteEntityRelations(entityId); | ||
33 | + } | ||
34 | + | ||
35 | + | ||
36 | +} |
@@ -15,23 +15,102 @@ | @@ -15,23 +15,102 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.entity; | 16 | package org.thingsboard.server.dao.entity; |
17 | 17 | ||
18 | +import com.google.common.base.Function; | ||
19 | +import com.google.common.util.concurrent.Futures; | ||
20 | +import com.google.common.util.concurrent.ListenableFuture; | ||
18 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
19 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
20 | -import org.thingsboard.server.common.data.id.EntityId; | ||
21 | -import org.thingsboard.server.dao.relation.RelationService; | 23 | +import org.springframework.stereotype.Service; |
24 | +import org.thingsboard.server.common.data.*; | ||
25 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
26 | +import org.thingsboard.server.common.data.id.*; | ||
27 | +import org.thingsboard.server.dao.alarm.AlarmService; | ||
28 | +import org.thingsboard.server.dao.asset.AssetService; | ||
29 | +import org.thingsboard.server.dao.customer.CustomerService; | ||
30 | +import org.thingsboard.server.dao.dashboard.DashboardService; | ||
31 | +import org.thingsboard.server.dao.device.DeviceService; | ||
32 | +import org.thingsboard.server.dao.plugin.PluginService; | ||
33 | +import org.thingsboard.server.dao.rule.RuleService; | ||
34 | +import org.thingsboard.server.dao.tenant.TenantService; | ||
35 | +import org.thingsboard.server.dao.user.UserService; | ||
22 | 36 | ||
23 | /** | 37 | /** |
24 | * Created by ashvayka on 04.05.17. | 38 | * Created by ashvayka on 04.05.17. |
25 | */ | 39 | */ |
40 | +@Service | ||
26 | @Slf4j | 41 | @Slf4j |
27 | -public class BaseEntityService { | 42 | +public class BaseEntityService extends AbstractEntityService implements EntityService { |
28 | 43 | ||
29 | @Autowired | 44 | @Autowired |
30 | - protected RelationService relationService; | 45 | + private AssetService assetService; |
31 | 46 | ||
32 | - protected void deleteEntityRelations(EntityId entityId) { | ||
33 | - log.trace("Executing deleteEntityRelations [{}]", entityId); | ||
34 | - relationService.deleteEntityRelations(entityId); | 47 | + @Autowired |
48 | + private DeviceService deviceService; | ||
49 | + | ||
50 | + @Autowired | ||
51 | + private RuleService ruleService; | ||
52 | + | ||
53 | + @Autowired | ||
54 | + private PluginService pluginService; | ||
55 | + | ||
56 | + @Autowired | ||
57 | + private TenantService tenantService; | ||
58 | + | ||
59 | + @Autowired | ||
60 | + private CustomerService customerService; | ||
61 | + | ||
62 | + @Autowired | ||
63 | + private UserService userService; | ||
64 | + | ||
65 | + @Autowired | ||
66 | + private DashboardService dashboardService; | ||
67 | + | ||
68 | + @Autowired | ||
69 | + private AlarmService alarmService; | ||
70 | + | ||
71 | + @Override | ||
72 | + public void deleteEntityRelations(EntityId entityId) { | ||
73 | + super.deleteEntityRelations(entityId); | ||
74 | + } | ||
75 | + | ||
76 | + @Override | ||
77 | + public ListenableFuture<String> fetchEntityNameAsync(EntityId entityId) { | ||
78 | + log.trace("Executing fetchEntityNameAsync [{}]", entityId); | ||
79 | + ListenableFuture<String> entityName; | ||
80 | + ListenableFuture<? extends HasName> hasName; | ||
81 | + switch (entityId.getEntityType()) { | ||
82 | + case ASSET: | ||
83 | + hasName = assetService.findAssetByIdAsync(new AssetId(entityId.getId())); | ||
84 | + break; | ||
85 | + case DEVICE: | ||
86 | + hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId())); | ||
87 | + break; | ||
88 | + case RULE: | ||
89 | + hasName = ruleService.findRuleByIdAsync(new RuleId(entityId.getId())); | ||
90 | + break; | ||
91 | + case PLUGIN: | ||
92 | + hasName = pluginService.findPluginByIdAsync(new PluginId(entityId.getId())); | ||
93 | + break; | ||
94 | + case TENANT: | ||
95 | + hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId())); | ||
96 | + break; | ||
97 | + case CUSTOMER: | ||
98 | + hasName = customerService.findCustomerByIdAsync(new CustomerId(entityId.getId())); | ||
99 | + break; | ||
100 | + case USER: | ||
101 | + hasName = userService.findUserByIdAsync(new UserId(entityId.getId())); | ||
102 | + break; | ||
103 | + case DASHBOARD: | ||
104 | + hasName = dashboardService.findDashboardInfoByIdAsync(new DashboardId(entityId.getId())); | ||
105 | + break; | ||
106 | + case ALARM: | ||
107 | + hasName = alarmService.findAlarmByIdAsync(new AlarmId(entityId.getId())); | ||
108 | + break; | ||
109 | + default: | ||
110 | + throw new IllegalStateException("Not Implemented!"); | ||
111 | + } | ||
112 | + entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1.getName() ); | ||
113 | + return entityName; | ||
35 | } | 114 | } |
36 | 115 | ||
37 | } | 116 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.dao.entity; | ||
18 | + | ||
19 | +import com.google.common.util.concurrent.ListenableFuture; | ||
20 | +import org.thingsboard.server.common.data.id.EntityId; | ||
21 | + | ||
22 | +public interface EntityService { | ||
23 | + | ||
24 | + ListenableFuture<String> fetchEntityNameAsync(EntityId entityId); | ||
25 | + | ||
26 | + void deleteEntityRelations(EntityId entityId); | ||
27 | + | ||
28 | +} |
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.model; | ||
17 | + | ||
18 | +import com.datastax.driver.core.utils.UUIDs; | ||
19 | +import com.datastax.driver.mapping.annotations.*; | ||
20 | +import com.fasterxml.jackson.databind.JsonNode; | ||
21 | +import org.thingsboard.server.common.data.EntityType; | ||
22 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
23 | +import org.thingsboard.server.common.data.alarm.AlarmId; | ||
24 | +import org.thingsboard.server.common.data.alarm.AlarmSeverity; | ||
25 | +import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
26 | +import org.thingsboard.server.common.data.id.EntityIdFactory; | ||
27 | +import org.thingsboard.server.common.data.id.TenantId; | ||
28 | +import org.thingsboard.server.dao.model.type.AlarmSeverityCodec; | ||
29 | +import org.thingsboard.server.dao.model.type.AlarmStatusCodec; | ||
30 | +import org.thingsboard.server.dao.model.type.EntityTypeCodec; | ||
31 | +import org.thingsboard.server.dao.model.type.JsonCodec; | ||
32 | + | ||
33 | +import java.util.UUID; | ||
34 | + | ||
35 | +import static org.thingsboard.server.dao.model.ModelConstants.*; | ||
36 | + | ||
37 | +@Table(name = ALARM_COLUMN_FAMILY_NAME) | ||
38 | +public final class AlarmEntity implements BaseEntity<Alarm> { | ||
39 | + | ||
40 | + @Transient | ||
41 | + private static final long serialVersionUID = -1265181166886910152L; | ||
42 | + | ||
43 | + @ClusteringColumn(value = 1) | ||
44 | + @Column(name = ID_PROPERTY) | ||
45 | + private UUID id; | ||
46 | + | ||
47 | + @PartitionKey(value = 0) | ||
48 | + @Column(name = ALARM_TENANT_ID_PROPERTY) | ||
49 | + private UUID tenantId; | ||
50 | + | ||
51 | + @PartitionKey(value = 1) | ||
52 | + @Column(name = ALARM_ORIGINATOR_ID_PROPERTY) | ||
53 | + private UUID originatorId; | ||
54 | + | ||
55 | + @PartitionKey(value = 2) | ||
56 | + @Column(name = ALARM_ORIGINATOR_TYPE_PROPERTY, codec = EntityTypeCodec.class) | ||
57 | + private EntityType originatorType; | ||
58 | + | ||
59 | + @ClusteringColumn(value = 0) | ||
60 | + @Column(name = ALARM_TYPE_PROPERTY) | ||
61 | + private String type; | ||
62 | + | ||
63 | + @Column(name = ALARM_SEVERITY_PROPERTY, codec = AlarmSeverityCodec.class) | ||
64 | + private AlarmSeverity severity; | ||
65 | + | ||
66 | + @Column(name = ALARM_STATUS_PROPERTY, codec = AlarmStatusCodec.class) | ||
67 | + private AlarmStatus status; | ||
68 | + | ||
69 | + @Column(name = ALARM_START_TS_PROPERTY) | ||
70 | + private Long startTs; | ||
71 | + | ||
72 | + @Column(name = ALARM_END_TS_PROPERTY) | ||
73 | + private Long endTs; | ||
74 | + | ||
75 | + @Column(name = ALARM_ACK_TS_PROPERTY) | ||
76 | + private Long ackTs; | ||
77 | + | ||
78 | + @Column(name = ALARM_CLEAR_TS_PROPERTY) | ||
79 | + private Long clearTs; | ||
80 | + | ||
81 | + @Column(name = ALARM_DETAILS_PROPERTY, codec = JsonCodec.class) | ||
82 | + private JsonNode details; | ||
83 | + | ||
84 | + @Column(name = ALARM_PROPAGATE_PROPERTY) | ||
85 | + private Boolean propagate; | ||
86 | + | ||
87 | + public AlarmEntity() { | ||
88 | + super(); | ||
89 | + } | ||
90 | + | ||
91 | + public AlarmEntity(Alarm alarm) { | ||
92 | + if (alarm.getId() != null) { | ||
93 | + this.id = alarm.getId().getId(); | ||
94 | + } | ||
95 | + if (alarm.getTenantId() != null) { | ||
96 | + this.tenantId = alarm.getTenantId().getId(); | ||
97 | + } | ||
98 | + this.type = alarm.getType(); | ||
99 | + this.originatorId = alarm.getOriginator().getId(); | ||
100 | + this.originatorType = alarm.getOriginator().getEntityType(); | ||
101 | + this.type = alarm.getType(); | ||
102 | + this.severity = alarm.getSeverity(); | ||
103 | + this.status = alarm.getStatus(); | ||
104 | + this.propagate = alarm.isPropagate(); | ||
105 | + this.startTs = alarm.getStartTs(); | ||
106 | + this.endTs = alarm.getEndTs(); | ||
107 | + this.ackTs = alarm.getAckTs(); | ||
108 | + this.clearTs = alarm.getClearTs(); | ||
109 | + this.details = alarm.getDetails(); | ||
110 | + } | ||
111 | + | ||
112 | + public UUID getId() { | ||
113 | + return id; | ||
114 | + } | ||
115 | + | ||
116 | + public void setId(UUID id) { | ||
117 | + this.id = id; | ||
118 | + } | ||
119 | + | ||
120 | + public UUID getTenantId() { | ||
121 | + return tenantId; | ||
122 | + } | ||
123 | + | ||
124 | + public void setTenantId(UUID tenantId) { | ||
125 | + this.tenantId = tenantId; | ||
126 | + } | ||
127 | + | ||
128 | + public UUID getOriginatorId() { | ||
129 | + return originatorId; | ||
130 | + } | ||
131 | + | ||
132 | + public void setOriginatorId(UUID originatorId) { | ||
133 | + this.originatorId = originatorId; | ||
134 | + } | ||
135 | + | ||
136 | + public EntityType getOriginatorType() { | ||
137 | + return originatorType; | ||
138 | + } | ||
139 | + | ||
140 | + public void setOriginatorType(EntityType originatorType) { | ||
141 | + this.originatorType = originatorType; | ||
142 | + } | ||
143 | + | ||
144 | + public String getType() { | ||
145 | + return type; | ||
146 | + } | ||
147 | + | ||
148 | + public void setType(String type) { | ||
149 | + this.type = type; | ||
150 | + } | ||
151 | + | ||
152 | + public AlarmSeverity getSeverity() { | ||
153 | + return severity; | ||
154 | + } | ||
155 | + | ||
156 | + public void setSeverity(AlarmSeverity severity) { | ||
157 | + this.severity = severity; | ||
158 | + } | ||
159 | + | ||
160 | + public AlarmStatus getStatus() { | ||
161 | + return status; | ||
162 | + } | ||
163 | + | ||
164 | + public void setStatus(AlarmStatus status) { | ||
165 | + this.status = status; | ||
166 | + } | ||
167 | + | ||
168 | + public Long getStartTs() { | ||
169 | + return startTs; | ||
170 | + } | ||
171 | + | ||
172 | + public void setStartTs(Long startTs) { | ||
173 | + this.startTs = startTs; | ||
174 | + } | ||
175 | + | ||
176 | + public Long getEndTs() { | ||
177 | + return endTs; | ||
178 | + } | ||
179 | + | ||
180 | + public void setEndTs(Long endTs) { | ||
181 | + this.endTs = endTs; | ||
182 | + } | ||
183 | + | ||
184 | + public Long getAckTs() { | ||
185 | + return ackTs; | ||
186 | + } | ||
187 | + | ||
188 | + public void setAckTs(Long ackTs) { | ||
189 | + this.ackTs = ackTs; | ||
190 | + } | ||
191 | + | ||
192 | + public Long getClearTs() { | ||
193 | + return clearTs; | ||
194 | + } | ||
195 | + | ||
196 | + public void setClearTs(Long clearTs) { | ||
197 | + this.clearTs = clearTs; | ||
198 | + } | ||
199 | + | ||
200 | + public JsonNode getDetails() { | ||
201 | + return details; | ||
202 | + } | ||
203 | + | ||
204 | + public void setDetails(JsonNode details) { | ||
205 | + this.details = details; | ||
206 | + } | ||
207 | + | ||
208 | + public Boolean getPropagate() { | ||
209 | + return propagate; | ||
210 | + } | ||
211 | + | ||
212 | + public void setPropagate(Boolean propagate) { | ||
213 | + this.propagate = propagate; | ||
214 | + } | ||
215 | + | ||
216 | + @Override | ||
217 | + public Alarm toData() { | ||
218 | + Alarm alarm = new Alarm(new AlarmId(id)); | ||
219 | + alarm.setCreatedTime(UUIDs.unixTimestamp(id)); | ||
220 | + if (tenantId != null) { | ||
221 | + alarm.setTenantId(new TenantId(tenantId)); | ||
222 | + } | ||
223 | + alarm.setOriginator(EntityIdFactory.getByTypeAndUuid(originatorType, originatorId)); | ||
224 | + alarm.setType(type); | ||
225 | + alarm.setSeverity(severity); | ||
226 | + alarm.setStatus(status); | ||
227 | + alarm.setPropagate(propagate); | ||
228 | + alarm.setStartTs(startTs); | ||
229 | + alarm.setEndTs(endTs); | ||
230 | + alarm.setAckTs(ackTs); | ||
231 | + alarm.setClearTs(clearTs); | ||
232 | + alarm.setDetails(details); | ||
233 | + return alarm; | ||
234 | + } | ||
235 | + | ||
236 | +} |
@@ -49,12 +49,13 @@ public final class AssetEntity implements SearchTextEntity<Asset> { | @@ -49,12 +49,13 @@ public final class AssetEntity implements SearchTextEntity<Asset> { | ||
49 | @Column(name = ASSET_CUSTOMER_ID_PROPERTY) | 49 | @Column(name = ASSET_CUSTOMER_ID_PROPERTY) |
50 | private UUID customerId; | 50 | private UUID customerId; |
51 | 51 | ||
52 | - @Column(name = ASSET_NAME_PROPERTY) | ||
53 | - private String name; | ||
54 | - | 52 | + @PartitionKey(value = 3) |
55 | @Column(name = ASSET_TYPE_PROPERTY) | 53 | @Column(name = ASSET_TYPE_PROPERTY) |
56 | private String type; | 54 | private String type; |
57 | 55 | ||
56 | + @Column(name = ASSET_NAME_PROPERTY) | ||
57 | + private String name; | ||
58 | + | ||
58 | @Column(name = SEARCH_TEXT_PROPERTY) | 59 | @Column(name = SEARCH_TEXT_PROPERTY) |
59 | private String searchText; | 60 | private String searchText; |
60 | 61 |
@@ -49,12 +49,13 @@ public final class DeviceEntity implements SearchTextEntity<Device> { | @@ -49,12 +49,13 @@ public final class DeviceEntity implements SearchTextEntity<Device> { | ||
49 | @Column(name = DEVICE_CUSTOMER_ID_PROPERTY) | 49 | @Column(name = DEVICE_CUSTOMER_ID_PROPERTY) |
50 | private UUID customerId; | 50 | private UUID customerId; |
51 | 51 | ||
52 | - @Column(name = DEVICE_NAME_PROPERTY) | ||
53 | - private String name; | ||
54 | - | 52 | + @PartitionKey(value = 3) |
55 | @Column(name = DEVICE_TYPE_PROPERTY) | 53 | @Column(name = DEVICE_TYPE_PROPERTY) |
56 | private String type; | 54 | private String type; |
57 | 55 | ||
56 | + @Column(name = DEVICE_NAME_PROPERTY) | ||
57 | + private String name; | ||
58 | + | ||
58 | @Column(name = SEARCH_TEXT_PROPERTY) | 59 | @Column(name = SEARCH_TEXT_PROPERTY) |
59 | private String searchText; | 60 | private String searchText; |
60 | 61 |
@@ -124,8 +124,11 @@ public class ModelConstants { | @@ -124,8 +124,11 @@ public class ModelConstants { | ||
124 | public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; | 124 | public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; |
125 | 125 | ||
126 | public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; | 126 | public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; |
127 | + public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; | ||
127 | public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; | 128 | public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; |
129 | + public static final String DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_by_type_and_search_text"; | ||
128 | public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name"; | 130 | public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name"; |
131 | + public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant"; | ||
129 | 132 | ||
130 | /** | 133 | /** |
131 | * Cassandra asset constants. | 134 | * Cassandra asset constants. |
@@ -138,8 +141,30 @@ public class ModelConstants { | @@ -138,8 +141,30 @@ public class ModelConstants { | ||
138 | public static final String ASSET_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; | 141 | public static final String ASSET_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; |
139 | 142 | ||
140 | public static final String ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_and_search_text"; | 143 | public static final String ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_and_search_text"; |
144 | + public static final String ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_by_type_and_search_text"; | ||
141 | public static final String ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_and_search_text"; | 145 | public static final String ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_and_search_text"; |
146 | + public static final String ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_by_type_and_search_text"; | ||
142 | public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name"; | 147 | public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name"; |
148 | + public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant"; | ||
149 | + | ||
150 | + /** | ||
151 | + * Cassandra alarm constants. | ||
152 | + */ | ||
153 | + public static final String ALARM_COLUMN_FAMILY_NAME = "alarm"; | ||
154 | + public static final String ALARM_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY; | ||
155 | + public static final String ALARM_TYPE_PROPERTY = "type"; | ||
156 | + public static final String ALARM_DETAILS_PROPERTY = "details"; | ||
157 | + public static final String ALARM_ORIGINATOR_ID_PROPERTY = "originator_id"; | ||
158 | + public static final String ALARM_ORIGINATOR_TYPE_PROPERTY = "originator_type"; | ||
159 | + public static final String ALARM_SEVERITY_PROPERTY = "severity"; | ||
160 | + public static final String ALARM_STATUS_PROPERTY = "status"; | ||
161 | + public static final String ALARM_START_TS_PROPERTY = "start_ts"; | ||
162 | + public static final String ALARM_END_TS_PROPERTY = "end_ts"; | ||
163 | + public static final String ALARM_ACK_TS_PROPERTY = "ack_ts"; | ||
164 | + public static final String ALARM_CLEAR_TS_PROPERTY = "clear_ts"; | ||
165 | + public static final String ALARM_PROPAGATE_PROPERTY = "propagate"; | ||
166 | + | ||
167 | + public static final String ALARM_BY_ID_VIEW_NAME = "alarm_by_id"; | ||
143 | 168 | ||
144 | /** | 169 | /** |
145 | * Cassandra entity relation constants. | 170 | * Cassandra entity relation constants. |
@@ -150,7 +175,9 @@ public class ModelConstants { | @@ -150,7 +175,9 @@ public class ModelConstants { | ||
150 | public static final String RELATION_TO_ID_PROPERTY = "to_id"; | 175 | public static final String RELATION_TO_ID_PROPERTY = "to_id"; |
151 | public static final String RELATION_TO_TYPE_PROPERTY = "to_type"; | 176 | public static final String RELATION_TO_TYPE_PROPERTY = "to_type"; |
152 | public static final String RELATION_TYPE_PROPERTY = "relation_type"; | 177 | public static final String RELATION_TYPE_PROPERTY = "relation_type"; |
178 | + public static final String RELATION_TYPE_GROUP_PROPERTY = "relation_type_group"; | ||
153 | 179 | ||
180 | + public static final String RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME = "relation_by_type_and_child_type"; | ||
154 | public static final String RELATION_REVERSE_VIEW_NAME = "reverse_relation"; | 181 | public static final String RELATION_REVERSE_VIEW_NAME = "reverse_relation"; |
155 | 182 | ||
156 | 183 |
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 | +} |
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.model.type; | ||
17 | + | ||
18 | +import com.datastax.driver.extras.codecs.enums.EnumNameCodec; | ||
19 | +import org.thingsboard.server.common.data.alarm.AlarmSeverity; | ||
20 | +import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
21 | +import org.thingsboard.server.dao.alarm.AlarmService; | ||
22 | + | ||
23 | +public class AlarmSeverityCodec extends EnumNameCodec<AlarmSeverity> { | ||
24 | + | ||
25 | + public AlarmSeverityCodec() { | ||
26 | + super(AlarmSeverity.class); | ||
27 | + } | ||
28 | + | ||
29 | +} |
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.model.type; | ||
17 | + | ||
18 | +import com.datastax.driver.extras.codecs.enums.EnumNameCodec; | ||
19 | +import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
20 | + | ||
21 | +public class AlarmStatusCodec extends EnumNameCodec<AlarmStatus> { | ||
22 | + | ||
23 | + public AlarmStatusCodec() { | ||
24 | + super(AlarmStatus.class); | ||
25 | + } | ||
26 | + | ||
27 | +} |
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.model.type; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
19 | + | ||
20 | +import com.datastax.driver.extras.codecs.enums.EnumNameCodec; | ||
21 | + | ||
22 | +public class RelationTypeGroupCodec extends EnumNameCodec<RelationTypeGroup> { | ||
23 | + | ||
24 | + public RelationTypeGroupCodec() { | ||
25 | + super(RelationTypeGroup.class); | ||
26 | + } | ||
27 | + | ||
28 | +} |
@@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils; | @@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils; | ||
22 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | import org.thingsboard.server.common.data.id.PluginId; | 24 | import org.thingsboard.server.common.data.id.PluginId; |
25 | -import org.thingsboard.server.common.data.id.RuleId; | ||
26 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
27 | import org.thingsboard.server.common.data.page.TextPageData; | 26 | import org.thingsboard.server.common.data.page.TextPageData; |
28 | import org.thingsboard.server.common.data.page.TextPageLink; | 27 | import org.thingsboard.server.common.data.page.TextPageLink; |
@@ -30,9 +29,8 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | @@ -30,9 +29,8 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | ||
30 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | 29 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
31 | import org.thingsboard.server.common.data.plugin.ComponentType; | 30 | import org.thingsboard.server.common.data.plugin.ComponentType; |
32 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 31 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
33 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | ||
34 | import org.thingsboard.server.dao.component.ComponentDescriptorService; | 32 | import org.thingsboard.server.dao.component.ComponentDescriptorService; |
35 | -import org.thingsboard.server.dao.entity.BaseEntityService; | 33 | +import org.thingsboard.server.dao.entity.AbstractEntityService; |
36 | import org.thingsboard.server.dao.exception.DataValidationException; | 34 | import org.thingsboard.server.dao.exception.DataValidationException; |
37 | import org.thingsboard.server.dao.exception.DatabaseException; | 35 | import org.thingsboard.server.dao.exception.DatabaseException; |
38 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 36 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
@@ -55,7 +53,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; | @@ -55,7 +53,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; | ||
55 | 53 | ||
56 | @Service | 54 | @Service |
57 | @Slf4j | 55 | @Slf4j |
58 | -public class BasePluginService extends BaseEntityService implements PluginService { | 56 | +public class BasePluginService extends AbstractEntityService implements PluginService { |
59 | 57 | ||
60 | //TODO: move to a better place. | 58 | //TODO: move to a better place. |
61 | public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); | 59 | public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
@@ -16,23 +16,34 @@ | @@ -16,23 +16,34 @@ | ||
16 | package org.thingsboard.server.dao.relation; | 16 | package org.thingsboard.server.dao.relation; |
17 | 17 | ||
18 | import com.datastax.driver.core.*; | 18 | import com.datastax.driver.core.*; |
19 | +import com.datastax.driver.core.querybuilder.QueryBuilder; | ||
20 | +import com.datastax.driver.core.querybuilder.Select; | ||
19 | import com.fasterxml.jackson.databind.JsonNode; | 21 | import com.fasterxml.jackson.databind.JsonNode; |
20 | import com.google.common.base.Function; | 22 | import com.google.common.base.Function; |
21 | import com.google.common.util.concurrent.Futures; | 23 | import com.google.common.util.concurrent.Futures; |
22 | import com.google.common.util.concurrent.ListenableFuture; | 24 | import com.google.common.util.concurrent.ListenableFuture; |
23 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
24 | import org.springframework.stereotype.Component; | 26 | import org.springframework.stereotype.Component; |
27 | +import org.thingsboard.server.common.data.EntityType; | ||
25 | import org.thingsboard.server.common.data.id.EntityId; | 28 | import org.thingsboard.server.common.data.id.EntityId; |
26 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 29 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
30 | +import org.thingsboard.server.common.data.page.TimePageLink; | ||
27 | import org.thingsboard.server.common.data.relation.EntityRelation; | 31 | import org.thingsboard.server.common.data.relation.EntityRelation; |
32 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
28 | import org.thingsboard.server.dao.AbstractAsyncDao; | 33 | import org.thingsboard.server.dao.AbstractAsyncDao; |
34 | +import org.thingsboard.server.dao.AbstractSearchTimeDao; | ||
29 | import org.thingsboard.server.dao.model.ModelConstants; | 35 | import org.thingsboard.server.dao.model.ModelConstants; |
36 | +import org.thingsboard.server.dao.model.type.RelationTypeGroupCodec; | ||
30 | 37 | ||
31 | import javax.annotation.Nullable; | 38 | import javax.annotation.Nullable; |
32 | import javax.annotation.PostConstruct; | 39 | import javax.annotation.PostConstruct; |
33 | import java.util.ArrayList; | 40 | import java.util.ArrayList; |
41 | +import java.util.Arrays; | ||
34 | import java.util.List; | 42 | import java.util.List; |
35 | 43 | ||
44 | +import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; | ||
45 | +import static org.thingsboard.server.dao.model.ModelConstants.RELATION_COLUMN_FAMILY_NAME; | ||
46 | + | ||
36 | /** | 47 | /** |
37 | * Created by ashvayka on 25.04.17. | 48 | * Created by ashvayka on 25.04.17. |
38 | */ | 49 | */ |
@@ -45,12 +56,15 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -45,12 +56,15 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
45 | ModelConstants.RELATION_FROM_TYPE_PROPERTY + "," + | 56 | ModelConstants.RELATION_FROM_TYPE_PROPERTY + "," + |
46 | ModelConstants.RELATION_TO_ID_PROPERTY + "," + | 57 | ModelConstants.RELATION_TO_ID_PROPERTY + "," + |
47 | ModelConstants.RELATION_TO_TYPE_PROPERTY + "," + | 58 | ModelConstants.RELATION_TO_TYPE_PROPERTY + "," + |
59 | + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + "," + | ||
48 | ModelConstants.RELATION_TYPE_PROPERTY + "," + | 60 | ModelConstants.RELATION_TYPE_PROPERTY + "," + |
49 | ModelConstants.ADDITIONAL_INFO_PROPERTY; | 61 | ModelConstants.ADDITIONAL_INFO_PROPERTY; |
50 | public static final String FROM = " FROM "; | 62 | public static final String FROM = " FROM "; |
51 | public static final String WHERE = " WHERE "; | 63 | public static final String WHERE = " WHERE "; |
52 | public static final String AND = " AND "; | 64 | public static final String AND = " AND "; |
53 | 65 | ||
66 | + private static final RelationTypeGroupCodec relationTypeGroupCodec = new RelationTypeGroupCodec(); | ||
67 | + | ||
54 | private PreparedStatement saveStmt; | 68 | private PreparedStatement saveStmt; |
55 | private PreparedStatement findAllByFromStmt; | 69 | private PreparedStatement findAllByFromStmt; |
56 | private PreparedStatement findAllByFromAndTypeStmt; | 70 | private PreparedStatement findAllByFromAndTypeStmt; |
@@ -66,43 +80,52 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -66,43 +80,52 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
66 | } | 80 | } |
67 | 81 | ||
68 | @Override | 82 | @Override |
69 | - public ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from) { | ||
70 | - BoundStatement stmt = getFindAllByFromStmt().bind().setUUID(0, from.getId()).setString(1, from.getEntityType().name()); | 83 | + public ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) { |
84 | + BoundStatement stmt = getFindAllByFromStmt().bind() | ||
85 | + .setUUID(0, from.getId()) | ||
86 | + .setString(1, from.getEntityType().name()) | ||
87 | + .set(2, typeGroup, relationTypeGroupCodec); | ||
71 | return executeAsyncRead(from, stmt); | 88 | return executeAsyncRead(from, stmt); |
72 | } | 89 | } |
73 | 90 | ||
74 | @Override | 91 | @Override |
75 | - public ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType) { | 92 | + public ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { |
76 | BoundStatement stmt = getFindAllByFromAndTypeStmt().bind() | 93 | BoundStatement stmt = getFindAllByFromAndTypeStmt().bind() |
77 | .setUUID(0, from.getId()) | 94 | .setUUID(0, from.getId()) |
78 | .setString(1, from.getEntityType().name()) | 95 | .setString(1, from.getEntityType().name()) |
79 | - .setString(2, relationType); | 96 | + .set(2, typeGroup, relationTypeGroupCodec) |
97 | + .setString(3, relationType); | ||
80 | return executeAsyncRead(from, stmt); | 98 | return executeAsyncRead(from, stmt); |
81 | } | 99 | } |
82 | 100 | ||
83 | @Override | 101 | @Override |
84 | - public ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to) { | ||
85 | - BoundStatement stmt = getFindAllByToStmt().bind().setUUID(0, to.getId()).setString(1, to.getEntityType().name()); | 102 | + public ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup) { |
103 | + BoundStatement stmt = getFindAllByToStmt().bind() | ||
104 | + .setUUID(0, to.getId()) | ||
105 | + .setString(1, to.getEntityType().name()) | ||
106 | + .set(2, typeGroup, relationTypeGroupCodec); | ||
86 | return executeAsyncRead(to, stmt); | 107 | return executeAsyncRead(to, stmt); |
87 | } | 108 | } |
88 | 109 | ||
89 | @Override | 110 | @Override |
90 | - public ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType) { | 111 | + public ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { |
91 | BoundStatement stmt = getFindAllByToAndTypeStmt().bind() | 112 | BoundStatement stmt = getFindAllByToAndTypeStmt().bind() |
92 | .setUUID(0, to.getId()) | 113 | .setUUID(0, to.getId()) |
93 | .setString(1, to.getEntityType().name()) | 114 | .setString(1, to.getEntityType().name()) |
94 | - .setString(2, relationType); | 115 | + .set(2, typeGroup, relationTypeGroupCodec) |
116 | + .setString(3, relationType); | ||
95 | return executeAsyncRead(to, stmt); | 117 | return executeAsyncRead(to, stmt); |
96 | } | 118 | } |
97 | 119 | ||
98 | @Override | 120 | @Override |
99 | - public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType) { | 121 | + public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { |
100 | BoundStatement stmt = getCheckRelationStmt().bind() | 122 | BoundStatement stmt = getCheckRelationStmt().bind() |
101 | .setUUID(0, from.getId()) | 123 | .setUUID(0, from.getId()) |
102 | .setString(1, from.getEntityType().name()) | 124 | .setString(1, from.getEntityType().name()) |
103 | .setUUID(2, to.getId()) | 125 | .setUUID(2, to.getId()) |
104 | .setString(3, to.getEntityType().name()) | 126 | .setString(3, to.getEntityType().name()) |
105 | - .setString(4, relationType); | 127 | + .set(4, typeGroup, relationTypeGroupCodec) |
128 | + .setString(5, relationType); | ||
106 | return getFuture(executeAsyncRead(stmt), rs -> rs != null ? rs.one() != null : false); | 129 | return getFuture(executeAsyncRead(stmt), rs -> rs != null ? rs.one() != null : false); |
107 | } | 130 | } |
108 | 131 | ||
@@ -113,25 +136,27 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -113,25 +136,27 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
113 | .setString(1, relation.getFrom().getEntityType().name()) | 136 | .setString(1, relation.getFrom().getEntityType().name()) |
114 | .setUUID(2, relation.getTo().getId()) | 137 | .setUUID(2, relation.getTo().getId()) |
115 | .setString(3, relation.getTo().getEntityType().name()) | 138 | .setString(3, relation.getTo().getEntityType().name()) |
116 | - .setString(4, relation.getType()) | ||
117 | - .set(5, relation.getAdditionalInfo(), JsonNode.class); | 139 | + .set(4, relation.getTypeGroup(), relationTypeGroupCodec) |
140 | + .setString(5, relation.getType()) | ||
141 | + .set(6, relation.getAdditionalInfo(), JsonNode.class); | ||
118 | ResultSetFuture future = executeAsyncWrite(stmt); | 142 | ResultSetFuture future = executeAsyncWrite(stmt); |
119 | return getBooleanListenableFuture(future); | 143 | return getBooleanListenableFuture(future); |
120 | } | 144 | } |
121 | 145 | ||
122 | @Override | 146 | @Override |
123 | public ListenableFuture<Boolean> deleteRelation(EntityRelation relation) { | 147 | public ListenableFuture<Boolean> deleteRelation(EntityRelation relation) { |
124 | - return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType()); | 148 | + return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup()); |
125 | } | 149 | } |
126 | 150 | ||
127 | @Override | 151 | @Override |
128 | - public ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType) { | 152 | + public ListenableFuture<Boolean> deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { |
129 | BoundStatement stmt = getDeleteStmt().bind() | 153 | BoundStatement stmt = getDeleteStmt().bind() |
130 | .setUUID(0, from.getId()) | 154 | .setUUID(0, from.getId()) |
131 | .setString(1, from.getEntityType().name()) | 155 | .setString(1, from.getEntityType().name()) |
132 | .setUUID(2, to.getId()) | 156 | .setUUID(2, to.getId()) |
133 | .setString(3, to.getEntityType().name()) | 157 | .setString(3, to.getEntityType().name()) |
134 | - .setString(4, relationType); | 158 | + .set(4, typeGroup, relationTypeGroupCodec) |
159 | + .setString(5, relationType); | ||
135 | ResultSetFuture future = executeAsyncWrite(stmt); | 160 | ResultSetFuture future = executeAsyncWrite(stmt); |
136 | return getBooleanListenableFuture(future); | 161 | return getBooleanListenableFuture(future); |
137 | } | 162 | } |
@@ -145,6 +170,21 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -145,6 +170,21 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
145 | return getBooleanListenableFuture(future); | 170 | return getBooleanListenableFuture(future); |
146 | } | 171 | } |
147 | 172 | ||
173 | + @Override | ||
174 | + public ListenableFuture<List<EntityRelation>> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType, TimePageLink pageLink) { | ||
175 | + Select.Where query = AbstractSearchTimeDao.buildQuery(ModelConstants.RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME, | ||
176 | + Arrays.asList(eq(ModelConstants.RELATION_FROM_ID_PROPERTY, from.getId()), | ||
177 | + eq(ModelConstants.RELATION_FROM_TYPE_PROPERTY, from.getEntityType().name()), | ||
178 | + eq(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, typeGroup.name()), | ||
179 | + eq(ModelConstants.RELATION_TYPE_PROPERTY, relationType), | ||
180 | + eq(ModelConstants.RELATION_TO_TYPE_PROPERTY, childType.name())), | ||
181 | + Arrays.asList(QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), | ||
182 | + QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), | ||
183 | + QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)), | ||
184 | + pageLink, ModelConstants.RELATION_TO_ID_PROPERTY); | ||
185 | + return getFuture(executeAsyncRead(query), rs -> getEntityRelations(rs)); | ||
186 | + } | ||
187 | + | ||
148 | private PreparedStatement getSaveStmt() { | 188 | private PreparedStatement getSaveStmt() { |
149 | if (saveStmt == null) { | 189 | if (saveStmt == null) { |
150 | saveStmt = getSession().prepare("INSERT INTO " + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + | 190 | saveStmt = getSession().prepare("INSERT INTO " + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + |
@@ -152,9 +192,10 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -152,9 +192,10 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
152 | "," + ModelConstants.RELATION_FROM_TYPE_PROPERTY + | 192 | "," + ModelConstants.RELATION_FROM_TYPE_PROPERTY + |
153 | "," + ModelConstants.RELATION_TO_ID_PROPERTY + | 193 | "," + ModelConstants.RELATION_TO_ID_PROPERTY + |
154 | "," + ModelConstants.RELATION_TO_TYPE_PROPERTY + | 194 | "," + ModelConstants.RELATION_TO_TYPE_PROPERTY + |
195 | + "," + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + | ||
155 | "," + ModelConstants.RELATION_TYPE_PROPERTY + | 196 | "," + ModelConstants.RELATION_TYPE_PROPERTY + |
156 | "," + ModelConstants.ADDITIONAL_INFO_PROPERTY + ")" + | 197 | "," + ModelConstants.ADDITIONAL_INFO_PROPERTY + ")" + |
157 | - " VALUES(?, ?, ?, ?, ?, ?)"); | 198 | + " VALUES(?, ?, ?, ?, ?, ?, ?)"); |
158 | } | 199 | } |
159 | return saveStmt; | 200 | return saveStmt; |
160 | } | 201 | } |
@@ -166,6 +207,7 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -166,6 +207,7 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
166 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ?" + | 207 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ?" + |
167 | AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ?" + | 208 | AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ?" + |
168 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ?" + | 209 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ?" + |
210 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ?" + | ||
169 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ?"); | 211 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ?"); |
170 | } | 212 | } |
171 | return deleteStmt; | 213 | return deleteStmt; |
@@ -185,7 +227,8 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -185,7 +227,8 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
185 | findAllByFromStmt = getSession().prepare(SELECT_COLUMNS + " " + | 227 | findAllByFromStmt = getSession().prepare(SELECT_COLUMNS + " " + |
186 | FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + | 228 | FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + |
187 | WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + | 229 | WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + |
188 | - AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? "); | 230 | + AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + |
231 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? "); | ||
189 | } | 232 | } |
190 | return findAllByFromStmt; | 233 | return findAllByFromStmt; |
191 | } | 234 | } |
@@ -196,17 +239,20 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -196,17 +239,20 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
196 | FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + | 239 | FROM + ModelConstants.RELATION_COLUMN_FAMILY_NAME + " " + |
197 | WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + | 240 | WHERE + ModelConstants.RELATION_FROM_ID_PROPERTY + " = ? " + |
198 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + | 241 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + |
242 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + | ||
199 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); | 243 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); |
200 | } | 244 | } |
201 | return findAllByFromAndTypeStmt; | 245 | return findAllByFromAndTypeStmt; |
202 | } | 246 | } |
203 | 247 | ||
248 | + | ||
204 | private PreparedStatement getFindAllByToStmt() { | 249 | private PreparedStatement getFindAllByToStmt() { |
205 | if (findAllByToStmt == null) { | 250 | if (findAllByToStmt == null) { |
206 | findAllByToStmt = getSession().prepare(SELECT_COLUMNS + " " + | 251 | findAllByToStmt = getSession().prepare(SELECT_COLUMNS + " " + |
207 | FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + | 252 | FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + |
208 | WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + | 253 | WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + |
209 | - AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? "); | 254 | + AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + |
255 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? "); | ||
210 | } | 256 | } |
211 | return findAllByToStmt; | 257 | return findAllByToStmt; |
212 | } | 258 | } |
@@ -217,11 +263,13 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -217,11 +263,13 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
217 | FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + | 263 | FROM + ModelConstants.RELATION_REVERSE_VIEW_NAME + " " + |
218 | WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + | 264 | WHERE + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + |
219 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + | 265 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + |
266 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + | ||
220 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); | 267 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); |
221 | } | 268 | } |
222 | return findAllByToAndTypeStmt; | 269 | return findAllByToAndTypeStmt; |
223 | } | 270 | } |
224 | 271 | ||
272 | + | ||
225 | private PreparedStatement getCheckRelationStmt() { | 273 | private PreparedStatement getCheckRelationStmt() { |
226 | if (checkRelationStmt == null) { | 274 | if (checkRelationStmt == null) { |
227 | checkRelationStmt = getSession().prepare(SELECT_COLUMNS + " " + | 275 | checkRelationStmt = getSession().prepare(SELECT_COLUMNS + " " + |
@@ -230,36 +278,19 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -230,36 +278,19 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
230 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + | 278 | AND + ModelConstants.RELATION_FROM_TYPE_PROPERTY + " = ? " + |
231 | AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + | 279 | AND + ModelConstants.RELATION_TO_ID_PROPERTY + " = ? " + |
232 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + | 280 | AND + ModelConstants.RELATION_TO_TYPE_PROPERTY + " = ? " + |
281 | + AND + ModelConstants.RELATION_TYPE_GROUP_PROPERTY + " = ? " + | ||
233 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); | 282 | AND + ModelConstants.RELATION_TYPE_PROPERTY + " = ? "); |
234 | } | 283 | } |
235 | return checkRelationStmt; | 284 | return checkRelationStmt; |
236 | } | 285 | } |
237 | 286 | ||
238 | - private EntityRelation getEntityRelation(Row row) { | ||
239 | - EntityRelation relation = new EntityRelation(); | ||
240 | - relation.setType(row.getString(ModelConstants.RELATION_TYPE_PROPERTY)); | ||
241 | - relation.setAdditionalInfo(row.get(ModelConstants.ADDITIONAL_INFO_PROPERTY, JsonNode.class)); | ||
242 | - relation.setFrom(toEntity(row, ModelConstants.RELATION_FROM_ID_PROPERTY, ModelConstants.RELATION_FROM_TYPE_PROPERTY)); | ||
243 | - relation.setTo(toEntity(row, ModelConstants.RELATION_TO_ID_PROPERTY, ModelConstants.RELATION_TO_TYPE_PROPERTY)); | ||
244 | - return relation; | ||
245 | - } | ||
246 | - | ||
247 | private EntityId toEntity(Row row, String uuidColumn, String typeColumn) { | 287 | private EntityId toEntity(Row row, String uuidColumn, String typeColumn) { |
248 | return EntityIdFactory.getByTypeAndUuid(row.getString(typeColumn), row.getUUID(uuidColumn)); | 288 | return EntityIdFactory.getByTypeAndUuid(row.getString(typeColumn), row.getUUID(uuidColumn)); |
249 | } | 289 | } |
250 | 290 | ||
251 | private ListenableFuture<List<EntityRelation>> executeAsyncRead(EntityId from, BoundStatement stmt) { | 291 | private ListenableFuture<List<EntityRelation>> executeAsyncRead(EntityId from, BoundStatement stmt) { |
252 | log.debug("Generated query [{}] for entity {}", stmt, from); | 292 | log.debug("Generated query [{}] for entity {}", stmt, from); |
253 | - return getFuture(executeAsyncRead(stmt), rs -> { | ||
254 | - List<Row> rows = rs.all(); | ||
255 | - List<EntityRelation> entries = new ArrayList<>(rows.size()); | ||
256 | - if (!rows.isEmpty()) { | ||
257 | - rows.forEach(row -> { | ||
258 | - entries.add(getEntityRelation(row)); | ||
259 | - }); | ||
260 | - } | ||
261 | - return entries; | ||
262 | - }); | 293 | + return getFuture(executeAsyncRead(stmt), rs -> getEntityRelations(rs)); |
263 | } | 294 | } |
264 | 295 | ||
265 | private ListenableFuture<Boolean> getBooleanListenableFuture(ResultSetFuture rsFuture) { | 296 | private ListenableFuture<Boolean> getBooleanListenableFuture(ResultSetFuture rsFuture) { |
@@ -276,4 +307,25 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | @@ -276,4 +307,25 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { | ||
276 | }, readResultsProcessingExecutor); | 307 | }, readResultsProcessingExecutor); |
277 | } | 308 | } |
278 | 309 | ||
310 | + private List<EntityRelation> getEntityRelations(ResultSet rs) { | ||
311 | + List<Row> rows = rs.all(); | ||
312 | + List<EntityRelation> entries = new ArrayList<>(rows.size()); | ||
313 | + if (!rows.isEmpty()) { | ||
314 | + rows.forEach(row -> { | ||
315 | + entries.add(getEntityRelation(row)); | ||
316 | + }); | ||
317 | + } | ||
318 | + return entries; | ||
319 | + } | ||
320 | + | ||
321 | + private EntityRelation getEntityRelation(Row row) { | ||
322 | + EntityRelation relation = new EntityRelation(); | ||
323 | + relation.setTypeGroup(row.get(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, relationTypeGroupCodec)); | ||
324 | + relation.setType(row.getString(ModelConstants.RELATION_TYPE_PROPERTY)); | ||
325 | + relation.setAdditionalInfo(row.get(ModelConstants.ADDITIONAL_INFO_PROPERTY, JsonNode.class)); | ||
326 | + relation.setFrom(toEntity(row, ModelConstants.RELATION_FROM_ID_PROPERTY, ModelConstants.RELATION_FROM_TYPE_PROPERTY)); | ||
327 | + relation.setTo(toEntity(row, ModelConstants.RELATION_TO_ID_PROPERTY, ModelConstants.RELATION_TO_TYPE_PROPERTY)); | ||
328 | + return relation; | ||
329 | + } | ||
330 | + | ||
279 | } | 331 | } |