Commit 5860a0651b3974be3ce010795d0ff87238a2eb63

Authored by mp-loki
1 parent 66d0e0cc

JPA WidgetType, WidgetsBundle, Tenant DAO

1 /** 1 /**
2 * Copyright © 2016-2017 The Thingsboard Authors 2 * Copyright © 2016-2017 The Thingsboard Authors
3 - * 3 + * <p>
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with 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 6 * You may obtain a copy of the License at
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * 7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,20 +16,28 @@ @@ -16,20 +16,28 @@
16 package org.thingsboard.server.dao.model.sql; 16 package org.thingsboard.server.dao.model.sql;
17 17
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
  19 +
19 import javax.persistence.Column; 20 import javax.persistence.Column;
20 import javax.persistence.Entity; 21 import javax.persistence.Entity;
21 import javax.persistence.Id; 22 import javax.persistence.Id;
22 import javax.persistence.Table; 23 import javax.persistence.Table;
23 import javax.persistence.Transient; 24 import javax.persistence.Transient;
  25 +
  26 +import com.fasterxml.jackson.databind.ObjectMapper;
  27 +import lombok.Data;
  28 +import lombok.extern.slf4j.Slf4j;
24 import org.thingsboard.server.common.data.Tenant; 29 import org.thingsboard.server.common.data.Tenant;
25 import org.thingsboard.server.common.data.id.TenantId; 30 import org.thingsboard.server.common.data.id.TenantId;
26 import org.thingsboard.server.dao.model.ModelConstants; 31 import org.thingsboard.server.dao.model.ModelConstants;
27 import org.thingsboard.server.dao.model.SearchTextEntity; 32 import org.thingsboard.server.dao.model.SearchTextEntity;
28 import com.fasterxml.jackson.databind.JsonNode; 33 import com.fasterxml.jackson.databind.JsonNode;
29 34
  35 +import java.io.IOException;
30 import java.util.UUID; 36 import java.util.UUID;
31 37
32 -//@Entity 38 +@Slf4j
  39 +@Data
  40 +@Entity
33 @Table(name = ModelConstants.TENANT_COLUMN_FAMILY_NAME) 41 @Table(name = ModelConstants.TENANT_COLUMN_FAMILY_NAME)
34 public final class TenantEntity implements SearchTextEntity<Tenant> { 42 public final class TenantEntity implements SearchTextEntity<Tenant> {
35 43
@@ -37,21 +45,21 @@ public final class TenantEntity implements SearchTextEntity<Tenant> { @@ -37,21 +45,21 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
37 private static final long serialVersionUID = -4330655990232136337L; 45 private static final long serialVersionUID = -4330655990232136337L;
38 46
39 @Id 47 @Id
40 - @Column(name = ModelConstants.ID_PROPERTY) 48 + @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
41 private UUID id; 49 private UUID id;
42 50
43 @Column(name = ModelConstants.TENANT_TITLE_PROPERTY) 51 @Column(name = ModelConstants.TENANT_TITLE_PROPERTY)
44 private String title; 52 private String title;
45 - 53 +
46 @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) 54 @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
47 private String searchText; 55 private String searchText;
48 56
49 @Column(name = ModelConstants.TENANT_REGION_PROPERTY) 57 @Column(name = ModelConstants.TENANT_REGION_PROPERTY)
50 private String region; 58 private String region;
51 - 59 +
52 @Column(name = ModelConstants.COUNTRY_PROPERTY) 60 @Column(name = ModelConstants.COUNTRY_PROPERTY)
53 private String country; 61 private String country;
54 - 62 +
55 @Column(name = ModelConstants.STATE_PROPERTY) 63 @Column(name = ModelConstants.STATE_PROPERTY)
56 private String state; 64 private String state;
57 65
@@ -74,7 +82,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> { @@ -74,7 +82,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
74 private String email; 82 private String email;
75 83
76 @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY) 84 @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY)
77 - private JsonNode additionalInfo; 85 + private String additionalInfo;
78 86
79 public TenantEntity() { 87 public TenantEntity() {
80 super(); 88 super();
@@ -94,104 +102,11 @@ public final class TenantEntity implements SearchTextEntity<Tenant> { @@ -94,104 +102,11 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
94 this.zip = tenant.getZip(); 102 this.zip = tenant.getZip();
95 this.phone = tenant.getPhone(); 103 this.phone = tenant.getPhone();
96 this.email = tenant.getEmail(); 104 this.email = tenant.getEmail();
97 - this.additionalInfo = tenant.getAdditionalInfo();  
98 - }  
99 -  
100 - public UUID getId() {  
101 - return id;  
102 - }  
103 -  
104 - public void setId(UUID id) {  
105 - this.id = id;  
106 - }  
107 -  
108 - public String getTitle() {  
109 - return title;  
110 - }  
111 -  
112 - public void setTitle(String title) {  
113 - this.title = title;  
114 - }  
115 -  
116 - public String getRegion() {  
117 - return region;  
118 - }  
119 -  
120 - public void setRegion(String region) {  
121 - this.region = region;  
122 - }  
123 -  
124 - public String getCountry() {  
125 - return country;  
126 - }  
127 -  
128 - public void setCountry(String country) {  
129 - this.country = country;  
130 - }  
131 -  
132 - public String getState() {  
133 - return state;  
134 - }  
135 -  
136 - public void setState(String state) {  
137 - this.state = state;  
138 - }  
139 -  
140 - public String getCity() {  
141 - return city;  
142 - }  
143 -  
144 - public void setCity(String city) {  
145 - this.city = city;  
146 - }  
147 -  
148 - public String getAddress() {  
149 - return address;  
150 - }  
151 -  
152 - public void setAddress(String address) {  
153 - this.address = address;  
154 - }  
155 -  
156 - public String getAddress2() {  
157 - return address2;  
158 - }  
159 -  
160 - public void setAddress2(String address2) {  
161 - this.address2 = address2;  
162 - }  
163 -  
164 - public String getZip() {  
165 - return zip;  
166 - }  
167 -  
168 - public void setZip(String zip) {  
169 - this.zip = zip;  
170 - }  
171 -  
172 - public String getPhone() {  
173 - return phone;  
174 - }  
175 -  
176 - public void setPhone(String phone) {  
177 - this.phone = phone;  
178 - }  
179 -  
180 - public String getEmail() {  
181 - return email;  
182 - }  
183 -  
184 - public void setEmail(String email) {  
185 - this.email = email;  
186 - }  
187 -  
188 - public JsonNode getAdditionalInfo() {  
189 - return additionalInfo; 105 + if (tenant.getAdditionalInfo() != null) {
  106 + this.additionalInfo = tenant.getAdditionalInfo().toString();
  107 + }
190 } 108 }
191 109
192 - public void setAdditionalInfo(JsonNode additionalInfo) {  
193 - this.additionalInfo = additionalInfo;  
194 - }  
195 110
196 @Override 111 @Override
197 public String getSearchTextSource() { 112 public String getSearchTextSource() {
@@ -202,7 +117,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> { @@ -202,7 +117,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
202 public void setSearchText(String searchText) { 117 public void setSearchText(String searchText) {
203 this.searchText = searchText; 118 this.searchText = searchText;
204 } 119 }
205 - 120 +
206 public String getSearchText() { 121 public String getSearchText() {
207 return searchText; 122 return searchText;
208 } 123 }
@@ -343,7 +258,15 @@ public final class TenantEntity implements SearchTextEntity<Tenant> { @@ -343,7 +258,15 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
343 tenant.setZip(zip); 258 tenant.setZip(zip);
344 tenant.setPhone(phone); 259 tenant.setPhone(phone);
345 tenant.setEmail(email); 260 tenant.setEmail(email);
346 - tenant.setAdditionalInfo(additionalInfo); 261 + ObjectMapper mapper = new ObjectMapper();
  262 + if (additionalInfo != null) {
  263 + try {
  264 + JsonNode jsonNode = mapper.readTree(additionalInfo);
  265 + tenant.setAdditionalInfo(jsonNode);
  266 + } catch (IOException e) {
  267 + log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
  268 + }
  269 + }
347 return tenant; 270 return tenant;
348 } 271 }
349 272
@@ -19,6 +19,7 @@ import com.datastax.driver.core.utils.UUIDs; @@ -19,6 +19,7 @@ import com.datastax.driver.core.utils.UUIDs;
19 import com.fasterxml.jackson.databind.JsonNode; 19 import com.fasterxml.jackson.databind.JsonNode;
20 import com.fasterxml.jackson.databind.ObjectMapper; 20 import com.fasterxml.jackson.databind.ObjectMapper;
21 import lombok.Data; 21 import lombok.Data;
  22 +import lombok.extern.slf4j.Slf4j;
22 import org.thingsboard.server.common.data.User; 23 import org.thingsboard.server.common.data.User;
23 import org.thingsboard.server.common.data.id.CustomerId; 24 import org.thingsboard.server.common.data.id.CustomerId;
24 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
@@ -34,6 +35,7 @@ import java.util.UUID; @@ -34,6 +35,7 @@ import java.util.UUID;
34 /** 35 /**
35 * Created by Valerii Sosliuk on 4/21/2017. 36 * Created by Valerii Sosliuk on 4/21/2017.
36 */ 37 */
  38 +@Slf4j
37 @Data 39 @Data
38 @Entity 40 @Entity
39 @Table(name = ModelConstants.USER_COLUMN_FAMILY_NAME) 41 @Table(name = ModelConstants.USER_COLUMN_FAMILY_NAME)
@@ -86,7 +88,9 @@ public class UserEntity implements SearchTextEntity<User> { @@ -86,7 +88,9 @@ public class UserEntity implements SearchTextEntity<User> {
86 this.email = user.getEmail(); 88 this.email = user.getEmail();
87 this.firstName = user.getFirstName(); 89 this.firstName = user.getFirstName();
88 this.lastName = user.getLastName(); 90 this.lastName = user.getLastName();
89 - this.additionalInfo = user.getAdditionalInfo().toString(); 91 + if (user.getAdditionalInfo() != null) {
  92 + this.additionalInfo = user.getAdditionalInfo().toString();
  93 + }
90 } 94 }
91 95
92 @Override 96 @Override
@@ -152,7 +156,7 @@ public class UserEntity implements SearchTextEntity<User> { @@ -152,7 +156,7 @@ public class UserEntity implements SearchTextEntity<User> {
152 JsonNode jsonNode = mapper.readTree(additionalInfo); 156 JsonNode jsonNode = mapper.readTree(additionalInfo);
153 user.setAdditionalInfo(jsonNode); 157 user.setAdditionalInfo(jsonNode);
154 } catch (IOException e) { 158 } catch (IOException e) {
155 - e.printStackTrace(); 159 + log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
156 } 160 }
157 } 161 }
158 return user; 162 return user;
@@ -24,15 +24,19 @@ import javax.persistence.Transient; @@ -24,15 +24,19 @@ import javax.persistence.Transient;
24 24
25 import com.datastax.driver.mapping.annotations.PartitionKey; 25 import com.datastax.driver.mapping.annotations.PartitionKey;
26 import com.fasterxml.jackson.databind.JsonNode; 26 import com.fasterxml.jackson.databind.JsonNode;
  27 +import com.fasterxml.jackson.databind.ObjectMapper;
  28 +import lombok.extern.slf4j.Slf4j;
27 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.id.WidgetTypeId; 30 import org.thingsboard.server.common.data.id.WidgetTypeId;
29 import org.thingsboard.server.common.data.widget.WidgetType; 31 import org.thingsboard.server.common.data.widget.WidgetType;
30 import org.thingsboard.server.dao.model.BaseEntity; 32 import org.thingsboard.server.dao.model.BaseEntity;
31 import org.thingsboard.server.dao.model.ModelConstants; 33 import org.thingsboard.server.dao.model.ModelConstants;
32 34
  35 +import java.io.IOException;
33 import java.util.UUID; 36 import java.util.UUID;
34 37
35 -//@Entity 38 +@Slf4j
  39 +@Entity
36 @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME) 40 @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME)
37 public final class WidgetTypeEntity implements BaseEntity<WidgetType> { 41 public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
38 42
@@ -40,11 +44,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> { @@ -40,11 +44,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
40 private static final long serialVersionUID = -5436279069884988630L; 44 private static final long serialVersionUID = -5436279069884988630L;
41 45
42 @Id 46 @Id
43 - @Column(name = ModelConstants.ID_PROPERTY) 47 + @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
44 private UUID id; 48 private UUID id;
45 49
46 @PartitionKey(value = 1) 50 @PartitionKey(value = 1)
47 - @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY) 51 + @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
48 private UUID tenantId; 52 private UUID tenantId;
49 53
50 @PartitionKey(value = 2) 54 @PartitionKey(value = 2)
@@ -58,7 +62,7 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> { @@ -58,7 +62,7 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
58 private String name; 62 private String name;
59 63
60 @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) 64 @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY)
61 - private JsonNode descriptor; 65 + private String descriptor;
62 66
63 public WidgetTypeEntity() { 67 public WidgetTypeEntity() {
64 super(); 68 super();
@@ -74,7 +78,9 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> { @@ -74,7 +78,9 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
74 this.bundleAlias = widgetType.getBundleAlias(); 78 this.bundleAlias = widgetType.getBundleAlias();
75 this.alias = widgetType.getAlias(); 79 this.alias = widgetType.getAlias();
76 this.name = widgetType.getName(); 80 this.name = widgetType.getName();
77 - this.descriptor = widgetType.getDescriptor(); 81 + if (widgetType.getDescriptor() != null) {
  82 + this.descriptor = widgetType.getDescriptor().toString();
  83 + }
78 } 84 }
79 85
80 @Override 86 @Override
@@ -119,11 +125,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> { @@ -119,11 +125,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
119 this.name = name; 125 this.name = name;
120 } 126 }
121 127
122 - public JsonNode getDescriptor() { 128 + public String getDescriptor() {
123 return descriptor; 129 return descriptor;
124 } 130 }
125 131
126 - public void setDescriptor(JsonNode descriptor) { 132 + public void setDescriptor(String descriptor) {
127 this.descriptor = descriptor; 133 this.descriptor = descriptor;
128 } 134 }
129 135
@@ -176,7 +182,15 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> { @@ -176,7 +182,15 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
176 widgetType.setBundleAlias(bundleAlias); 182 widgetType.setBundleAlias(bundleAlias);
177 widgetType.setAlias(alias); 183 widgetType.setAlias(alias);
178 widgetType.setName(name); 184 widgetType.setName(name);
179 - widgetType.setDescriptor(descriptor); 185 + ObjectMapper mapper = new ObjectMapper();
  186 + if (descriptor != null) {
  187 + try {
  188 + JsonNode jsonNode = mapper.readTree(descriptor);
  189 + widgetType.setDescriptor(jsonNode);
  190 + } catch (IOException e) {
  191 + log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", descriptor, e.getMessage()), e);
  192 + }
  193 + }
180 return widgetType; 194 return widgetType;
181 } 195 }
182 196
1 /** 1 /**
2 * Copyright © 2016-2017 The Thingsboard Authors 2 * Copyright © 2016-2017 The Thingsboard Authors
3 - * 3 + * <p>
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with 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 6 * You may obtain a copy of the License at
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * 7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql; @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql;
17 17
18 import com.google.common.collect.Lists; 18 import com.google.common.collect.Lists;
19 import com.google.common.util.concurrent.ListenableFuture; 19 import com.google.common.util.concurrent.ListenableFuture;
  20 +import com.google.common.util.concurrent.ListeningExecutorService;
  21 +import com.google.common.util.concurrent.MoreExecutors;
20 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.data.repository.CrudRepository; 23 import org.springframework.data.repository.CrudRepository;
22 import org.thingsboard.server.dao.Dao; 24 import org.thingsboard.server.dao.Dao;
@@ -26,6 +28,7 @@ import org.thingsboard.server.dao.model.SearchTextEntity; @@ -26,6 +28,7 @@ import org.thingsboard.server.dao.model.SearchTextEntity;
26 28
27 import java.util.List; 29 import java.util.List;
28 import java.util.UUID; 30 import java.util.UUID;
  31 +import java.util.concurrent.Executors;
29 32
30 /** 33 /**
31 * @author Valerii Sosliuk 34 * @author Valerii Sosliuk
@@ -51,7 +54,8 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao< @@ -51,7 +54,8 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
51 } catch (Exception e) { 54 } catch (Exception e) {
52 log.error("Can't create entity for domain object {}", domain, e); 55 log.error("Can't create entity for domain object {}", domain, e);
53 throw new IllegalArgumentException("Can't create entity for domain object {" + domain + "}", e); 56 throw new IllegalArgumentException("Can't create entity for domain object {" + domain + "}", e);
54 - } if (isSearchTextDao()) { 57 + }
  58 + if (isSearchTextDao()) {
55 ((SearchTextEntity) entity).setSearchText(((SearchTextEntity) entity).getSearchTextSource().toLowerCase()); 59 ((SearchTextEntity) entity).setSearchText(((SearchTextEntity) entity).getSearchTextSource().toLowerCase());
56 } 60 }
57 log.debug("Saving entity {}", entity); 61 log.debug("Saving entity {}", entity);
@@ -68,10 +72,11 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao< @@ -68,10 +72,11 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
68 72
69 @Override 73 @Override
70 public ListenableFuture<D> findByIdAsync(UUID key) { 74 public ListenableFuture<D> findByIdAsync(UUID key) {
71 - log.debug("Get entity by key {}", key);  
72 - // org.springframework.util.concurrent.ListenableFuture<E> entityFuture = getCrudRepository().findByIdAsync(key);  
73 - // TODO: vsosliuk implement  
74 - return null; 75 + log.debug("Get entity by key async {}", key);
  76 + // Should it be a field?
  77 + ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
  78 + ListenableFuture<D> listenableFuture = service.submit(() -> DaoUtil.getData(getCrudRepository().findOne(key)));
  79 + return listenableFuture;
75 } 80 }
76 81
77 @Override 82 @Override
  1 +package org.thingsboard.server.dao.sql.tenant;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  5 +import org.springframework.data.repository.CrudRepository;
  6 +import org.springframework.stereotype.Component;
  7 +import org.thingsboard.server.common.data.Tenant;
  8 +import org.thingsboard.server.common.data.page.TextPageLink;
  9 +import org.thingsboard.server.dao.DaoUtil;
  10 +import org.thingsboard.server.dao.model.sql.TenantEntity;
  11 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  12 +import org.thingsboard.server.dao.tenant.TenantDao;
  13 +
  14 +import java.util.List;
  15 +import java.util.UUID;
  16 +
  17 +import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMILY_NAME;
  18 +
  19 +/**
  20 + * Created by Valerii Sosliuk on 4/30/2017.
  21 + */
  22 +@Component
  23 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
  24 +public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implements TenantDao {
  25 +
  26 + @Autowired
  27 + private TenantRepository tenantRepository;
  28 +
  29 + @Override
  30 + protected Class<TenantEntity> getEntityClass() {
  31 + return TenantEntity.class;
  32 + }
  33 +
  34 + @Override
  35 + protected String getColumnFamilyName() {
  36 + return TENANT_COLUMN_FAMILY_NAME;
  37 + }
  38 +
  39 + @Override
  40 + protected CrudRepository<TenantEntity, UUID> getCrudRepository() {
  41 + return tenantRepository;
  42 + }
  43 +
  44 + @Override
  45 + protected boolean isSearchTextDao() {
  46 + return true;
  47 + }
  48 +
  49 + @Override
  50 + public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) {
  51 + if (pageLink.getIdOffset() == null) {
  52 + return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch()));
  53 + } else {
  54 + return DaoUtil.convertDataList(tenantRepository.findByRegionNextPage(pageLink.getLimit(), region, pageLink.getTextSearch(), pageLink.getIdOffset()));
  55 + }
  56 + }
  57 +}
  1 +package org.thingsboard.server.dao.sql.tenant;
  2 +
  3 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  4 +import org.springframework.data.jpa.repository.Query;
  5 +import org.springframework.data.repository.CrudRepository;
  6 +import org.thingsboard.server.dao.model.sql.TenantEntity;
  7 +
  8 +import java.util.List;
  9 +import java.util.UUID;
  10 +
  11 +/**
  12 + * Created by Valerii Sosliuk on 4/30/2017.
  13 + */
  14 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
  15 +public interface TenantRepository extends CrudRepository<TenantEntity, UUID> {
  16 +
  17 +
  18 + @Query(nativeQuery = true, value = "SELECT * FROM TENANT WHERE REGION = ?2 " +
  19 + "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
  20 + "ORDER BY ID LIMIT ?1")
  21 + List<TenantEntity> findByRegionFirstPage(int limit, String region, String textSearch);
  22 +
  23 +
  24 + @Query(nativeQuery = true, value = "SELECT * FROM TENANT WHERE REGION = ?2 " +
  25 + "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
  26 + "AND ID > ?4 ORDER BY ID LIMIT ?1")
  27 + List<TenantEntity> findByRegionNextPage(int limit, String region, String textSearch, UUID idOffset);
  28 +}
1 /** 1 /**
2 * Copyright © 2016-2017 The Thingsboard Authors 2 * Copyright © 2016-2017 The Thingsboard Authors
3 - * 3 + * <p>
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with 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 6 * You may obtain a copy of the License at
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * 7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -34,7 +34,7 @@ import java.util.UUID; @@ -34,7 +34,7 @@ import java.util.UUID;
34 * @author Valerii Sosliuk 34 * @author Valerii Sosliuk
35 */ 35 */
36 @Component 36 @Component
37 -@ConditionalOnProperty(prefix="sql", value="enabled",havingValue = "true", matchIfMissing = false) 37 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
38 public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements UserDao { 38 public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements UserDao {
39 39
40 @Autowired 40 @Autowired
@@ -62,11 +62,20 @@ public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements User @@ -62,11 +62,20 @@ public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements User
62 62
63 @Override 63 @Override
64 public List<User> findTenantAdmins(UUID tenantId, TextPageLink pageLink) { 64 public List<User> findTenantAdmins(UUID tenantId, TextPageLink pageLink) {
65 - throw new RuntimeException("Not Implemented"); 65 + if (pageLink.getIdOffset() == null) {
  66 + return DaoUtil.convertDataList(userRepository.findTenantAdminsFirstPage(pageLink.getLimit(), tenantId));
  67 + } else {
  68 + return DaoUtil.convertDataList(userRepository.findTenantAdminsNextPage(pageLink.getLimit(), tenantId, pageLink.getIdOffset()));
  69 + }
66 } 70 }
67 71
68 @Override 72 @Override
69 public List<User> findCustomerUsers(UUID tenantId, UUID customerId, TextPageLink pageLink) { 73 public List<User> findCustomerUsers(UUID tenantId, UUID customerId, TextPageLink pageLink) {
70 - throw new RuntimeException("Not Implemented"); 74 + if (pageLink.getIdOffset() == null) {
  75 + return DaoUtil.convertDataList(userRepository.findCustomerUsersFirstPage(pageLink.getLimit(), tenantId, customerId));
  76 + } else {
  77 + return DaoUtil.convertDataList(userRepository.findCustomerUsersNextPage(pageLink.getLimit(), tenantId,
  78 + customerId, pageLink.getIdOffset()));
  79 + }
71 } 80 }
72 } 81 }
1 /** 1 /**
2 * Copyright © 2016-2017 The Thingsboard Authors 2 * Copyright © 2016-2017 The Thingsboard Authors
3 - * 3 + * <p>
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with 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 6 * You may obtain a copy of the License at
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * 7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,17 +16,39 @@ @@ -16,17 +16,39 @@
16 package org.thingsboard.server.dao.sql.user; 16 package org.thingsboard.server.dao.sql.user;
17 17
18 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 18 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  19 +import org.springframework.data.jpa.repository.Query;
19 import org.springframework.data.repository.CrudRepository; 20 import org.springframework.data.repository.CrudRepository;
20 import org.thingsboard.server.dao.model.sql.UserEntity; 21 import org.thingsboard.server.dao.model.sql.UserEntity;
21 22
  23 +import java.util.List;
22 import java.util.UUID; 24 import java.util.UUID;
23 25
24 /** 26 /**
25 * @author Valerii Sosliuk 27 * @author Valerii Sosliuk
26 */ 28 */
27 -@ConditionalOnProperty(prefix="sql", value="enabled",havingValue = "true", matchIfMissing = false) 29 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
28 public interface UserRepository extends CrudRepository<UserEntity, UUID> { 30 public interface UserRepository extends CrudRepository<UserEntity, UUID> {
29 31
30 UserEntity findByEmail(String email); 32 UserEntity findByEmail(String email);
31 33
32 -} 34 + @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
  35 + "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
  36 + "ORDER BY ID LIMIT ?1")
  37 + List<UserEntity> findTenantAdminsFirstPage(int limit, UUID tenantId);
  38 +
  39 + @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
  40 + "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
  41 + "AND ID > ?3 ORDER BY ID LIMIT ?1")
  42 + List<UserEntity> findTenantAdminsNextPage(int limit, UUID tenantId, UUID idOffset);
  43 +
  44 + @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
  45 + "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
  46 + "ORDER BY ID LIMIT ?1")
  47 + List<UserEntity> findCustomerUsersFirstPage(int limit, UUID tenantId, UUID customerId);
  48 +
  49 + @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
  50 + "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
  51 + "AND ID > ?4 ORDER BY ID LIMIT ?1")
  52 + List<UserEntity> findCustomerUsersNextPage(int limit, UUID tenantId, UUID customerId, UUID idOffset);
  53 +
  54 +}
  1 +package org.thingsboard.server.dao.sql.widget;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  5 +import org.springframework.data.repository.CrudRepository;
  6 +import org.springframework.stereotype.Component;
  7 +import org.thingsboard.server.common.data.widget.WidgetType;
  8 +import org.thingsboard.server.dao.DaoUtil;
  9 +import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
  10 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  11 +import org.thingsboard.server.dao.widget.WidgetTypeDao;
  12 +
  13 +import java.util.List;
  14 +import java.util.UUID;
  15 +
  16 +import static org.thingsboard.server.dao.model.ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME;
  17 +
  18 +/**
  19 + * Created by Valerii Sosliuk on 4/29/2017.
  20 + */
  21 +@Component
  22 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
  23 +public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeEntity, WidgetType> implements WidgetTypeDao {
  24 +
  25 + @Autowired
  26 + private WidgetTypeRepository widgetTypeRepository;
  27 +
  28 + @Override
  29 + protected Class<WidgetTypeEntity> getEntityClass() {
  30 + return WidgetTypeEntity.class;
  31 + }
  32 +
  33 + @Override
  34 + protected String getColumnFamilyName() {
  35 + return WIDGET_TYPE_COLUMN_FAMILY_NAME;
  36 + }
  37 +
  38 + @Override
  39 + protected CrudRepository<WidgetTypeEntity, UUID> getCrudRepository() {
  40 + return widgetTypeRepository;
  41 + }
  42 +
  43 + @Override
  44 + public List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) {
  45 + return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias));
  46 + }
  47 +
  48 + @Override
  49 + public WidgetType findByTenantIdBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias) {
  50 + return DaoUtil.getData(widgetTypeRepository.findByTenantIdAndBundleAliasAndAlias(tenantId, bundleAlias, alias));
  51 + }
  52 +}
@@ -62,6 +62,11 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid @@ -62,6 +62,11 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
62 } 62 }
63 63
64 @Override 64 @Override
  65 + protected boolean isSearchTextDao() {
  66 + return true;
  67 + }
  68 +
  69 + @Override
65 public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) { 70 public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) {
66 if (pageLink.getIdOffset() == null) { 71 if (pageLink.getIdOffset() == null) {
67 return DaoUtil.convertDataList(widgetsBundleRepository.findSystemWidgetsBundlesFirstPage(pageLink.getLimit(), 72 return DaoUtil.convertDataList(widgetsBundleRepository.findSystemWidgetsBundlesFirstPage(pageLink.getLimit(),
@@ -93,9 +98,4 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid @@ -93,9 +98,4 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
93 tenantId, pageLink.getTextSearch(), pageLink.getIdOffset())); 98 tenantId, pageLink.getTextSearch(), pageLink.getIdOffset()));
94 } 99 }
95 } 100 }
96 -  
97 - @Override  
98 - protected boolean isSearchTextDao() {  
99 - return true;  
100 - }  
101 } 101 }
  1 +package org.thingsboard.server.dao.sql.widget;
  2 +
  3 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  4 +import org.springframework.data.repository.CrudRepository;
  5 +import org.thingsboard.server.common.data.widget.WidgetType;
  6 +import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
  7 +
  8 +import java.util.List;
  9 +import java.util.UUID;
  10 +
  11 +/**
  12 + * Created by Valerii Sosliuk on 4/29/2017.
  13 + */
  14 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
  15 +public interface WidgetTypeRepository extends CrudRepository<WidgetTypeEntity, UUID> {
  16 +
  17 + List<WidgetTypeEntity> findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias);
  18 +
  19 + WidgetTypeEntity findByTenantIdAndBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias);
  20 +}
@@ -15,25 +15,19 @@ @@ -15,25 +15,19 @@
15 */ 15 */
16 package org.thingsboard.server.dao.sql.widget; 16 package org.thingsboard.server.dao.sql.widget;
17 17
18 -import org.springframework.data.domain.Pageable;  
19 -import org.springframework.data.jpa.repository.JpaRepository;  
20 -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 18 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
21 import org.springframework.data.jpa.repository.Query; 19 import org.springframework.data.jpa.repository.Query;
22 import org.springframework.data.repository.CrudRepository; 20 import org.springframework.data.repository.CrudRepository;
23 -import org.springframework.data.repository.query.Param;  
24 -import org.thingsboard.server.common.data.page.TextPageLink;  
25 -import org.thingsboard.server.dao.model.ToData;  
26 import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; 21 import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
27 22
28 -import java.util.Collection;  
29 import java.util.List; 23 import java.util.List;
30 import java.util.UUID; 24 import java.util.UUID;
31 25
32 /** 26 /**
33 * Created by Valerii Sosliuk on 4/23/2017. 27 * Created by Valerii Sosliuk on 4/23/2017.
34 */ 28 */
35 -//public interface WidgetsBundleRepository extends CrudRepository<WidgetsBundleEntity, UUID> {  
36 -public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEntity, UUID>, JpaSpecificationExecutor { 29 +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
  30 +public interface WidgetsBundleRepository extends CrudRepository<WidgetsBundleEntity, UUID> {
37 31
38 WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias); 32 WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias);
39 33
  1 +package org.thingsboard.server.dao.sql.tenant;
  2 +
  3 +import com.datastax.driver.core.utils.UUIDs;
  4 +import com.github.springtestdbunit.annotation.DatabaseSetup;
  5 +import org.junit.Test;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.thingsboard.server.common.data.Tenant;
  8 +import org.thingsboard.server.common.data.id.TenantId;
  9 +import org.thingsboard.server.common.data.page.TextPageLink;
  10 +import org.thingsboard.server.dao.AbstractJpaDaoTest;
  11 +import org.thingsboard.server.dao.tenant.TenantDao;
  12 +
  13 +import java.util.List;
  14 +
  15 +import static org.junit.Assert.*;
  16 +
  17 +/**
  18 + * Created by Valerii Sosliuk on 4/30/2017.
  19 + */
  20 +public class JpaTenantDaoTest extends AbstractJpaDaoTest {
  21 +
  22 + @Autowired
  23 + private TenantDao tenantDao;
  24 +
  25 + @Test
  26 + @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
  27 + public void testFindTenantsByRegion() {
  28 + createTenants();
  29 + assertEquals(60, tenantDao.find().size());
  30 + List<Tenant> tenants1 = tenantDao.findTenantsByRegion("REGION_1", new TextPageLink(20,"title"));
  31 + assertEquals(20, tenants1.size());
  32 + List<Tenant> tenants2 = tenantDao.findTenantsByRegion("REGION_1",
  33 + new TextPageLink(20,"title", tenants1.get(19).getId().getId(), null));
  34 + assertEquals(10, tenants2.size());
  35 + List<Tenant> tenants3 = tenantDao.findTenantsByRegion("REGION_1",
  36 + new TextPageLink(20,"title", tenants2.get(9).getId().getId(), null));
  37 + assertEquals(0, tenants3.size());
  38 + }
  39 +
  40 + private void createTenants() {
  41 + for (int i = 0; i < 30; i++) {
  42 + createTenant("REGION_1", "TITLE", i);
  43 + createTenant("REGION_2", "TITLE", i);
  44 + }
  45 + }
  46 +
  47 + private void createTenant(String region, String title, int index) {
  48 + Tenant tenant = new Tenant();
  49 + tenant.setId(new TenantId(UUIDs.timeBased()));
  50 + tenant.setRegion(region);
  51 + tenant.setTitle(title + "_" + index);
  52 + tenantDao.save(tenant);
  53 + }
  54 +
  55 +}
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.dao.sql.user; 16 package org.thingsboard.server.dao.sql.user;
17 17
  18 +import com.datastax.driver.core.utils.UUIDs;
18 import com.fasterxml.jackson.databind.JsonNode; 19 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.ObjectMapper; 20 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.github.springtestdbunit.annotation.DatabaseSetup; 21 import com.github.springtestdbunit.annotation.DatabaseSetup;
@@ -24,6 +25,7 @@ import org.thingsboard.server.common.data.User; @@ -24,6 +25,7 @@ import org.thingsboard.server.common.data.User;
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.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
26 import org.thingsboard.server.common.data.id.UserId; 27 import org.thingsboard.server.common.data.id.UserId;
  28 +import org.thingsboard.server.common.data.page.TextPageLink;
27 import org.thingsboard.server.common.data.security.Authority; 29 import org.thingsboard.server.common.data.security.Authority;
28 import org.thingsboard.server.dao.AbstractJpaDaoTest; 30 import org.thingsboard.server.dao.AbstractJpaDaoTest;
29 import org.thingsboard.server.dao.user.UserDao; 31 import org.thingsboard.server.dao.user.UserDao;
@@ -51,7 +53,7 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest { @@ -51,7 +53,7 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
51 53
52 @Test 54 @Test
53 @DatabaseSetup("classpath:dbunit/users.xml") 55 @DatabaseSetup("classpath:dbunit/users.xml")
54 - public void findByEmail() { 56 + public void testFindByEmail() {
55 User user = userDao.findByEmail("sysadm@thingsboard.org"); 57 User user = userDao.findByEmail("sysadm@thingsboard.org");
56 assertNotNull("User is expected to be not null", user); 58 assertNotNull("User is expected to be not null", user);
57 assertEquals("9cb58ba0-27c1-11e7-93ae-92361f002671", user.getId().toString()); 59 assertEquals("9cb58ba0-27c1-11e7-93ae-92361f002671", user.getId().toString());
@@ -64,6 +66,40 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest { @@ -64,6 +66,40 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
64 } 66 }
65 67
66 @Test 68 @Test
  69 + @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
  70 + public void testFindTenantAdmins() {
  71 + UUID tenantId = UUIDs.timeBased();
  72 + UUID customerId = UUIDs.timeBased();
  73 + create30Adminsand60Users(tenantId, customerId);
  74 + assertEquals(90, userDao.find().size());
  75 + List<User> tenantAdmins1 = userDao.findTenantAdmins(tenantId, new TextPageLink(20));
  76 + assertEquals(20, tenantAdmins1.size());
  77 + List<User> tenantAdmins2 = userDao.findTenantAdmins(tenantId,
  78 + new TextPageLink(20, null, tenantAdmins1.get(19).getId().getId(), null));
  79 + assertEquals(10, tenantAdmins2.size());
  80 + List<User> tenantAdmins3 = userDao.findTenantAdmins(tenantId,
  81 + new TextPageLink(20, null, tenantAdmins2.get(9).getId().getId(), null));
  82 + assertEquals(0, tenantAdmins3.size());
  83 + }
  84 +
  85 + @Test
  86 + @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
  87 + public void testFindCustomerUsers() {
  88 + UUID tenantId = UUIDs.timeBased();
  89 + UUID customerId = UUIDs.timeBased();
  90 + create30Adminsand60Users(tenantId, customerId);
  91 + assertEquals(90, userDao.find().size());
  92 + List<User> customerUsers1 = userDao.findCustomerUsers(tenantId, customerId, new TextPageLink(40));
  93 + assertEquals(40, customerUsers1.size());
  94 + List<User> customerUsers2 = userDao.findCustomerUsers(tenantId, customerId,
  95 + new TextPageLink(20, null, customerUsers1.get(39).getId().getId(), null));
  96 + assertEquals(20, customerUsers2.size());
  97 + List<User> customerUsers3 = userDao.findCustomerUsers(tenantId, customerId,
  98 + new TextPageLink(20, null, customerUsers2.get(19).getId().getId(), null));
  99 + assertEquals(0, customerUsers3.size());
  100 + }
  101 +
  102 + @Test
67 @DatabaseSetup("classpath:dbunit/users.xml") 103 @DatabaseSetup("classpath:dbunit/users.xml")
68 public void testSave() throws IOException { 104 public void testSave() throws IOException {
69 User user = new User(); 105 User user = new User();
@@ -82,4 +118,30 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest { @@ -82,4 +118,30 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
82 User savedUser = userDao.findByEmail("user@thingsboard.org"); 118 User savedUser = userDao.findByEmail("user@thingsboard.org");
83 assertNotNull(savedUser); 119 assertNotNull(savedUser);
84 } 120 }
  121 +
  122 + private void create30Adminsand60Users(UUID tenantId, UUID customerId) {
  123 + // Create 30 tenant admins and 60 customer users
  124 + for (int i = 0; i < 30; i++) {
  125 + saveUser(tenantId, null);
  126 + saveUser(tenantId, customerId);
  127 + saveUser(tenantId, customerId);
  128 + }
  129 + }
  130 +
  131 + private void saveUser(UUID tenantId, UUID customerId) {
  132 + User user = new User();
  133 + UUID id = UUIDs.timeBased();
  134 + user.setId(new UserId(id));
  135 + user.setTenantId(new TenantId(tenantId));
  136 + if (customerId == null) {
  137 + user.setAuthority(Authority.TENANT_ADMIN);
  138 + } else {
  139 + user.setCustomerId(new CustomerId(customerId));
  140 + user.setAuthority(Authority.CUSTOMER_USER);
  141 + }
  142 + String idString = id.toString();
  143 + String email = idString.substring(0, idString.indexOf('-')) + "@thingsboard.org";
  144 + user.setEmail(email);
  145 + userDao.save(user);
  146 + }
85 } 147 }
  1 +package org.thingsboard.server.dao.sql.widget;
  2 +
  3 +import com.datastax.driver.core.utils.UUIDs;
  4 +import com.github.springtestdbunit.annotation.DatabaseSetup;
  5 +import org.junit.Test;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.thingsboard.server.common.data.widget.WidgetType;
  8 +import org.thingsboard.server.dao.AbstractJpaDaoTest;
  9 +import org.thingsboard.server.dao.widget.WidgetTypeDao;
  10 +
  11 +import java.util.List;
  12 +import java.util.UUID;
  13 +
  14 +import static org.junit.Assert.assertEquals;
  15 +
  16 +/**
  17 + * Created by Valerii Sosliuk on 4/30/2017.
  18 + */
  19 +public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
  20 +
  21 + @Autowired
  22 + private WidgetTypeDao widgetTypeDao;
  23 +
  24 + @Test
  25 + @DatabaseSetup(("classpath:dbunit/widget_type.xml"))
  26 + public void testFindByTenantIdAndBundleAlias() {
  27 + UUID tenantId = UUID.fromString("2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833");
  28 + List<WidgetType> widgetTypes = widgetTypeDao.findWidgetTypesByTenantIdAndBundleAlias(tenantId, "BUNDLE_ALIAS_1");
  29 + assertEquals(3, widgetTypes.size());
  30 + }
  31 +
  32 + @Test
  33 + @DatabaseSetup(("classpath:dbunit/widget_type.xml"))
  34 + public void testFindByTenantIdAndBundleAliasAndAlias() {
  35 + UUID tenantId = UUID.fromString("2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833");
  36 + WidgetType widgetType = widgetTypeDao.findByTenantIdBundleAliasAndAlias(tenantId, "BUNDLE_ALIAS_1", "ALIAS3");
  37 + UUID id = UUID.fromString("2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833");
  38 + assertEquals(id, widgetType.getId().getId());
  39 + }
  40 +}
@@ -11,7 +11,6 @@ @@ -11,7 +11,6 @@
11 /> 11 />
12 <user id="uuid'1312f328-27c7-11e7-93ae-92361f002671'" 12 <user id="uuid'1312f328-27c7-11e7-93ae-92361f002671'"
13 tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'" 13 tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
14 - customer_id="uuid'22fe91e8-27c7-11e7-93ae-92361f002671'"  
15 authority="1" 14 authority="1"
16 email="tenantadm1@thingsboard.org" 15 email="tenantadm1@thingsboard.org"
17 search_text="TENANTADM1 SEARCH TEXT" 16 search_text="TENANTADM1 SEARCH TEXT"
@@ -21,7 +20,6 @@ @@ -21,7 +20,6 @@
21 /> 20 />
22 <user id="uuid'2b090dde-27ca-11e7-93ae-92361f002671'" 21 <user id="uuid'2b090dde-27ca-11e7-93ae-92361f002671'"
23 tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'" 22 tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
24 - customer_id="uuid'34be535c-27ca-11e7-93ae-92361f002671'"  
25 authority="1" 23 authority="1"
26 email="tenantadm2@thingsboard.org" 24 email="tenantadm2@thingsboard.org"
27 search_text="TENANTADM2 SEARCH TEXT" 25 search_text="TENANTADM2 SEARCH TEXT"
  1 +<dataset>
  2 + <widget_type
  3 + id="uuid'2b7e4c91-2dfe-11e7-94aa-f7f6dbfb4833'"
  4 + tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
  5 + bundle_alias="BUNDLE_ALIAS_1"
  6 + alias="ALIAS1"
  7 + name="ALIAS1"
  8 + />
  9 + <widget_type
  10 + id="uuid'2b7e4c92-2dfe-11e7-94aa-f7f6dbfb4833'"
  11 + tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
  12 + bundle_alias="BUNDLE_ALIAS_1"
  13 + alias="ALIAS2"
  14 + name="ALIAS2"
  15 + />
  16 + <widget_type
  17 + id="uuid'2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833'"
  18 + tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
  19 + bundle_alias="BUNDLE_ALIAS_1"
  20 + alias="ALIAS3"
  21 + name="ALIAS3"
  22 + />
  23 + <widget_type
  24 + id="uuid'2b7e4c94-2dfe-11e7-94aa-f7f6dbfb4833'"
  25 + tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
  26 + bundle_alias="BUNDLE_ALIAS_2"
  27 + alias="ALIAS4"
  28 + name="ALIAS4"
  29 + />
  30 +
  31 +</dataset>