Details
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
index 8987425..6c54fd0 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
@@ -1,12 +1,12 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
- *
+ * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,20 +16,28 @@
package org.thingsboard.server.dao.model.sql;
import com.datastax.driver.core.utils.UUIDs;
+
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.SearchTextEntity;
import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
import java.util.UUID;
-//@Entity
+@Slf4j
+@Data
+@Entity
@Table(name = ModelConstants.TENANT_COLUMN_FAMILY_NAME)
public final class TenantEntity implements SearchTextEntity<Tenant> {
@@ -37,21 +45,21 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
private static final long serialVersionUID = -4330655990232136337L;
@Id
- @Column(name = ModelConstants.ID_PROPERTY)
+ @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID id;
@Column(name = ModelConstants.TENANT_TITLE_PROPERTY)
private String title;
-
+
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = ModelConstants.TENANT_REGION_PROPERTY)
private String region;
-
+
@Column(name = ModelConstants.COUNTRY_PROPERTY)
private String country;
-
+
@Column(name = ModelConstants.STATE_PROPERTY)
private String state;
@@ -74,7 +82,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
private String email;
@Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY)
- private JsonNode additionalInfo;
+ private String additionalInfo;
public TenantEntity() {
super();
@@ -94,104 +102,11 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
this.zip = tenant.getZip();
this.phone = tenant.getPhone();
this.email = tenant.getEmail();
- this.additionalInfo = tenant.getAdditionalInfo();
- }
-
- public UUID getId() {
- return id;
- }
-
- public void setId(UUID id) {
- this.id = id;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getRegion() {
- return region;
- }
-
- public void setRegion(String region) {
- this.region = region;
- }
-
- public String getCountry() {
- return country;
- }
-
- public void setCountry(String country) {
- this.country = country;
- }
-
- public String getState() {
- return state;
- }
-
- public void setState(String state) {
- this.state = state;
- }
-
- public String getCity() {
- return city;
- }
-
- public void setCity(String city) {
- this.city = city;
- }
-
- public String getAddress() {
- return address;
- }
-
- public void setAddress(String address) {
- this.address = address;
- }
-
- public String getAddress2() {
- return address2;
- }
-
- public void setAddress2(String address2) {
- this.address2 = address2;
- }
-
- public String getZip() {
- return zip;
- }
-
- public void setZip(String zip) {
- this.zip = zip;
- }
-
- public String getPhone() {
- return phone;
- }
-
- public void setPhone(String phone) {
- this.phone = phone;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public JsonNode getAdditionalInfo() {
- return additionalInfo;
+ if (tenant.getAdditionalInfo() != null) {
+ this.additionalInfo = tenant.getAdditionalInfo().toString();
+ }
}
- public void setAdditionalInfo(JsonNode additionalInfo) {
- this.additionalInfo = additionalInfo;
- }
@Override
public String getSearchTextSource() {
@@ -202,7 +117,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
public void setSearchText(String searchText) {
this.searchText = searchText;
}
-
+
public String getSearchText() {
return searchText;
}
@@ -343,7 +258,15 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
tenant.setZip(zip);
tenant.setPhone(phone);
tenant.setEmail(email);
- tenant.setAdditionalInfo(additionalInfo);
+ ObjectMapper mapper = new ObjectMapper();
+ if (additionalInfo != null) {
+ try {
+ JsonNode jsonNode = mapper.readTree(additionalInfo);
+ tenant.setAdditionalInfo(jsonNode);
+ } catch (IOException e) {
+ log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
+ }
+ }
return tenant;
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
index bf006bb..9df32e3 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
@@ -19,6 +19,7 @@ import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@@ -34,6 +35,7 @@ import java.util.UUID;
/**
* Created by Valerii Sosliuk on 4/21/2017.
*/
+@Slf4j
@Data
@Entity
@Table(name = ModelConstants.USER_COLUMN_FAMILY_NAME)
@@ -86,7 +88,9 @@ public class UserEntity implements SearchTextEntity<User> {
this.email = user.getEmail();
this.firstName = user.getFirstName();
this.lastName = user.getLastName();
- this.additionalInfo = user.getAdditionalInfo().toString();
+ if (user.getAdditionalInfo() != null) {
+ this.additionalInfo = user.getAdditionalInfo().toString();
+ }
}
@Override
@@ -152,7 +156,7 @@ public class UserEntity implements SearchTextEntity<User> {
JsonNode jsonNode = mapper.readTree(additionalInfo);
user.setAdditionalInfo(jsonNode);
} catch (IOException e) {
- e.printStackTrace();
+ log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
}
}
return user;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
index 2c84f72..7900891 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
@@ -24,15 +24,19 @@ import javax.persistence.Transient;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.dao.model.BaseEntity;
import org.thingsboard.server.dao.model.ModelConstants;
+import java.io.IOException;
import java.util.UUID;
-//@Entity
+@Slf4j
+@Entity
@Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME)
public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
@@ -40,11 +44,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
private static final long serialVersionUID = -5436279069884988630L;
@Id
- @Column(name = ModelConstants.ID_PROPERTY)
+ @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID id;
@PartitionKey(value = 1)
- @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY)
+ @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID tenantId;
@PartitionKey(value = 2)
@@ -58,7 +62,7 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
private String name;
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY)
- private JsonNode descriptor;
+ private String descriptor;
public WidgetTypeEntity() {
super();
@@ -74,7 +78,9 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
this.bundleAlias = widgetType.getBundleAlias();
this.alias = widgetType.getAlias();
this.name = widgetType.getName();
- this.descriptor = widgetType.getDescriptor();
+ if (widgetType.getDescriptor() != null) {
+ this.descriptor = widgetType.getDescriptor().toString();
+ }
}
@Override
@@ -119,11 +125,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
this.name = name;
}
- public JsonNode getDescriptor() {
+ public String getDescriptor() {
return descriptor;
}
- public void setDescriptor(JsonNode descriptor) {
+ public void setDescriptor(String descriptor) {
this.descriptor = descriptor;
}
@@ -176,7 +182,15 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
widgetType.setBundleAlias(bundleAlias);
widgetType.setAlias(alias);
widgetType.setName(name);
- widgetType.setDescriptor(descriptor);
+ ObjectMapper mapper = new ObjectMapper();
+ if (descriptor != null) {
+ try {
+ JsonNode jsonNode = mapper.readTree(descriptor);
+ widgetType.setDescriptor(jsonNode);
+ } catch (IOException e) {
+ log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", descriptor, e.getMessage()), e);
+ }
+ }
return widgetType;
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
index f38f49e..414c213 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
@@ -1,12 +1,12 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
- *
+ * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.Dao;
@@ -26,6 +28,7 @@ import org.thingsboard.server.dao.model.SearchTextEntity;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.Executors;
/**
* @author Valerii Sosliuk
@@ -51,7 +54,8 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
} catch (Exception e) {
log.error("Can't create entity for domain object {}", domain, e);
throw new IllegalArgumentException("Can't create entity for domain object {" + domain + "}", e);
- } if (isSearchTextDao()) {
+ }
+ if (isSearchTextDao()) {
((SearchTextEntity) entity).setSearchText(((SearchTextEntity) entity).getSearchTextSource().toLowerCase());
}
log.debug("Saving entity {}", entity);
@@ -68,10 +72,11 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
@Override
public ListenableFuture<D> findByIdAsync(UUID key) {
- log.debug("Get entity by key {}", key);
- // org.springframework.util.concurrent.ListenableFuture<E> entityFuture = getCrudRepository().findByIdAsync(key);
- // TODO: vsosliuk implement
- return null;
+ log.debug("Get entity by key async {}", key);
+ // Should it be a field?
+ ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
+ ListenableFuture<D> listenableFuture = service.submit(() -> DaoUtil.getData(getCrudRepository().findOne(key)));
+ return listenableFuture;
}
@Override
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
new file mode 100644
index 0000000..7cdb727
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
@@ -0,0 +1,57 @@
+package org.thingsboard.server.dao.sql.tenant;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.Tenant;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.sql.TenantEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.tenant.TenantDao;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMILY_NAME;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implements TenantDao {
+
+ @Autowired
+ private TenantRepository tenantRepository;
+
+ @Override
+ protected Class<TenantEntity> getEntityClass() {
+ return TenantEntity.class;
+ }
+
+ @Override
+ protected String getColumnFamilyName() {
+ return TENANT_COLUMN_FAMILY_NAME;
+ }
+
+ @Override
+ protected CrudRepository<TenantEntity, UUID> getCrudRepository() {
+ return tenantRepository;
+ }
+
+ @Override
+ protected boolean isSearchTextDao() {
+ return true;
+ }
+
+ @Override
+ public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) {
+ if (pageLink.getIdOffset() == null) {
+ return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch()));
+ } else {
+ return DaoUtil.convertDataList(tenantRepository.findByRegionNextPage(pageLink.getLimit(), region, pageLink.getTextSearch(), pageLink.getIdOffset()));
+ }
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java
new file mode 100644
index 0000000..ec533f4
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java
@@ -0,0 +1,28 @@
+package org.thingsboard.server.dao.sql.tenant;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.dao.model.sql.TenantEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface TenantRepository extends CrudRepository<TenantEntity, UUID> {
+
+
+ @Query(nativeQuery = true, value = "SELECT * FROM TENANT WHERE REGION = ?2 " +
+ "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+ "ORDER BY ID LIMIT ?1")
+ List<TenantEntity> findByRegionFirstPage(int limit, String region, String textSearch);
+
+
+ @Query(nativeQuery = true, value = "SELECT * FROM TENANT WHERE REGION = ?2 " +
+ "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+ "AND ID > ?4 ORDER BY ID LIMIT ?1")
+ List<TenantEntity> findByRegionNextPage(int limit, String region, String textSearch, UUID idOffset);
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
index 662dbee..cffccdb 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
@@ -1,12 +1,12 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
- *
+ * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -34,7 +34,7 @@ import java.util.UUID;
* @author Valerii Sosliuk
*/
@Component
-@ConditionalOnProperty(prefix="sql", value="enabled",havingValue = "true", matchIfMissing = false)
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements UserDao {
@Autowired
@@ -62,11 +62,20 @@ public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements User
@Override
public List<User> findTenantAdmins(UUID tenantId, TextPageLink pageLink) {
- throw new RuntimeException("Not Implemented");
+ if (pageLink.getIdOffset() == null) {
+ return DaoUtil.convertDataList(userRepository.findTenantAdminsFirstPage(pageLink.getLimit(), tenantId));
+ } else {
+ return DaoUtil.convertDataList(userRepository.findTenantAdminsNextPage(pageLink.getLimit(), tenantId, pageLink.getIdOffset()));
+ }
}
@Override
public List<User> findCustomerUsers(UUID tenantId, UUID customerId, TextPageLink pageLink) {
- throw new RuntimeException("Not Implemented");
+ if (pageLink.getIdOffset() == null) {
+ return DaoUtil.convertDataList(userRepository.findCustomerUsersFirstPage(pageLink.getLimit(), tenantId, customerId));
+ } else {
+ return DaoUtil.convertDataList(userRepository.findCustomerUsersNextPage(pageLink.getLimit(), tenantId,
+ customerId, pageLink.getIdOffset()));
+ }
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
index aec4137..cc4df06 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
@@ -1,12 +1,12 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
- *
+ * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,17 +16,39 @@
package org.thingsboard.server.dao.sql.user;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.model.sql.UserEntity;
+import java.util.List;
import java.util.UUID;
/**
* @author Valerii Sosliuk
*/
-@ConditionalOnProperty(prefix="sql", value="enabled",havingValue = "true", matchIfMissing = false)
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
public interface UserRepository extends CrudRepository<UserEntity, UUID> {
UserEntity findByEmail(String email);
-}
+ @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+ "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
+ "ORDER BY ID LIMIT ?1")
+ List<UserEntity> findTenantAdminsFirstPage(int limit, UUID tenantId);
+
+ @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+ "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
+ "AND ID > ?3 ORDER BY ID LIMIT ?1")
+ List<UserEntity> findTenantAdminsNextPage(int limit, UUID tenantId, UUID idOffset);
+
+ @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+ "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
+ "ORDER BY ID LIMIT ?1")
+ List<UserEntity> findCustomerUsersFirstPage(int limit, UUID tenantId, UUID customerId);
+
+ @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+ "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
+ "AND ID > ?4 ORDER BY ID LIMIT ?1")
+ List<UserEntity> findCustomerUsersNextPage(int limit, UUID tenantId, UUID customerId, UUID idOffset);
+
+}
\ No newline at end of file
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
index 512e661..ff40dd2 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
@@ -62,6 +62,11 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
}
@Override
+ protected boolean isSearchTextDao() {
+ return true;
+ }
+
+ @Override
public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) {
if (pageLink.getIdOffset() == null) {
return DaoUtil.convertDataList(widgetsBundleRepository.findSystemWidgetsBundlesFirstPage(pageLink.getLimit(),
@@ -93,9 +98,4 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
tenantId, pageLink.getTextSearch(), pageLink.getIdOffset()));
}
}
-
- @Override
- protected boolean isSearchTextDao() {
- return true;
- }
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
new file mode 100644
index 0000000..9cc89b2
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
@@ -0,0 +1,52 @@
+package org.thingsboard.server.dao.sql.widget;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.widget.WidgetType;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.widget.WidgetTypeDao;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.thingsboard.server.dao.model.ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME;
+
+/**
+ * Created by Valerii Sosliuk on 4/29/2017.
+ */
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeEntity, WidgetType> implements WidgetTypeDao {
+
+ @Autowired
+ private WidgetTypeRepository widgetTypeRepository;
+
+ @Override
+ protected Class<WidgetTypeEntity> getEntityClass() {
+ return WidgetTypeEntity.class;
+ }
+
+ @Override
+ protected String getColumnFamilyName() {
+ return WIDGET_TYPE_COLUMN_FAMILY_NAME;
+ }
+
+ @Override
+ protected CrudRepository<WidgetTypeEntity, UUID> getCrudRepository() {
+ return widgetTypeRepository;
+ }
+
+ @Override
+ public List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) {
+ return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias));
+ }
+
+ @Override
+ public WidgetType findByTenantIdBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias) {
+ return DaoUtil.getData(widgetTypeRepository.findByTenantIdAndBundleAliasAndAlias(tenantId, bundleAlias, alias));
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java
index cc47762..d94dd13 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java
@@ -15,25 +15,19 @@
*/
package org.thingsboard.server.dao.sql.widget;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
-import org.springframework.data.repository.query.Param;
-import org.thingsboard.server.common.data.page.TextPageLink;
-import org.thingsboard.server.dao.model.ToData;
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
-import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
* Created by Valerii Sosliuk on 4/23/2017.
*/
-//public interface WidgetsBundleRepository extends CrudRepository<WidgetsBundleEntity, UUID> {
-public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEntity, UUID>, JpaSpecificationExecutor {
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface WidgetsBundleRepository extends CrudRepository<WidgetsBundleEntity, UUID> {
WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
new file mode 100644
index 0000000..5b33617
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
@@ -0,0 +1,20 @@
+package org.thingsboard.server.dao.sql.widget;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.common.data.widget.WidgetType;
+import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 4/29/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface WidgetTypeRepository extends CrudRepository<WidgetTypeEntity, UUID> {
+
+ List<WidgetTypeEntity> findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias);
+
+ WidgetTypeEntity findByTenantIdAndBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias);
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java
new file mode 100644
index 0000000..2515618
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java
@@ -0,0 +1,55 @@
+package org.thingsboard.server.dao.sql.tenant;
+
+import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.Tenant;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.tenant.TenantDao;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+public class JpaTenantDaoTest extends AbstractJpaDaoTest {
+
+ @Autowired
+ private TenantDao tenantDao;
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void testFindTenantsByRegion() {
+ createTenants();
+ assertEquals(60, tenantDao.find().size());
+ List<Tenant> tenants1 = tenantDao.findTenantsByRegion("REGION_1", new TextPageLink(20,"title"));
+ assertEquals(20, tenants1.size());
+ List<Tenant> tenants2 = tenantDao.findTenantsByRegion("REGION_1",
+ new TextPageLink(20,"title", tenants1.get(19).getId().getId(), null));
+ assertEquals(10, tenants2.size());
+ List<Tenant> tenants3 = tenantDao.findTenantsByRegion("REGION_1",
+ new TextPageLink(20,"title", tenants2.get(9).getId().getId(), null));
+ assertEquals(0, tenants3.size());
+ }
+
+ private void createTenants() {
+ for (int i = 0; i < 30; i++) {
+ createTenant("REGION_1", "TITLE", i);
+ createTenant("REGION_2", "TITLE", i);
+ }
+ }
+
+ private void createTenant(String region, String title, int index) {
+ Tenant tenant = new Tenant();
+ tenant.setId(new TenantId(UUIDs.timeBased()));
+ tenant.setRegion(region);
+ tenant.setTitle(title + "_" + index);
+ tenantDao.save(tenant);
+ }
+
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
index 5bd254f..fe540fa 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.sql.user;
+import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.springtestdbunit.annotation.DatabaseSetup;
@@ -24,6 +25,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.AbstractJpaDaoTest;
import org.thingsboard.server.dao.user.UserDao;
@@ -51,7 +53,7 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
@Test
@DatabaseSetup("classpath:dbunit/users.xml")
- public void findByEmail() {
+ public void testFindByEmail() {
User user = userDao.findByEmail("sysadm@thingsboard.org");
assertNotNull("User is expected to be not null", user);
assertEquals("9cb58ba0-27c1-11e7-93ae-92361f002671", user.getId().toString());
@@ -64,6 +66,40 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
}
@Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void testFindTenantAdmins() {
+ UUID tenantId = UUIDs.timeBased();
+ UUID customerId = UUIDs.timeBased();
+ create30Adminsand60Users(tenantId, customerId);
+ assertEquals(90, userDao.find().size());
+ List<User> tenantAdmins1 = userDao.findTenantAdmins(tenantId, new TextPageLink(20));
+ assertEquals(20, tenantAdmins1.size());
+ List<User> tenantAdmins2 = userDao.findTenantAdmins(tenantId,
+ new TextPageLink(20, null, tenantAdmins1.get(19).getId().getId(), null));
+ assertEquals(10, tenantAdmins2.size());
+ List<User> tenantAdmins3 = userDao.findTenantAdmins(tenantId,
+ new TextPageLink(20, null, tenantAdmins2.get(9).getId().getId(), null));
+ assertEquals(0, tenantAdmins3.size());
+ }
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void testFindCustomerUsers() {
+ UUID tenantId = UUIDs.timeBased();
+ UUID customerId = UUIDs.timeBased();
+ create30Adminsand60Users(tenantId, customerId);
+ assertEquals(90, userDao.find().size());
+ List<User> customerUsers1 = userDao.findCustomerUsers(tenantId, customerId, new TextPageLink(40));
+ assertEquals(40, customerUsers1.size());
+ List<User> customerUsers2 = userDao.findCustomerUsers(tenantId, customerId,
+ new TextPageLink(20, null, customerUsers1.get(39).getId().getId(), null));
+ assertEquals(20, customerUsers2.size());
+ List<User> customerUsers3 = userDao.findCustomerUsers(tenantId, customerId,
+ new TextPageLink(20, null, customerUsers2.get(19).getId().getId(), null));
+ assertEquals(0, customerUsers3.size());
+ }
+
+ @Test
@DatabaseSetup("classpath:dbunit/users.xml")
public void testSave() throws IOException {
User user = new User();
@@ -82,4 +118,30 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
User savedUser = userDao.findByEmail("user@thingsboard.org");
assertNotNull(savedUser);
}
+
+ private void create30Adminsand60Users(UUID tenantId, UUID customerId) {
+ // Create 30 tenant admins and 60 customer users
+ for (int i = 0; i < 30; i++) {
+ saveUser(tenantId, null);
+ saveUser(tenantId, customerId);
+ saveUser(tenantId, customerId);
+ }
+ }
+
+ private void saveUser(UUID tenantId, UUID customerId) {
+ User user = new User();
+ UUID id = UUIDs.timeBased();
+ user.setId(new UserId(id));
+ user.setTenantId(new TenantId(tenantId));
+ if (customerId == null) {
+ user.setAuthority(Authority.TENANT_ADMIN);
+ } else {
+ user.setCustomerId(new CustomerId(customerId));
+ user.setAuthority(Authority.CUSTOMER_USER);
+ }
+ String idString = id.toString();
+ String email = idString.substring(0, idString.indexOf('-')) + "@thingsboard.org";
+ user.setEmail(email);
+ userDao.save(user);
+ }
}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
new file mode 100644
index 0000000..c41a7c5
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
@@ -0,0 +1,40 @@
+package org.thingsboard.server.dao.sql.widget;
+
+import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.widget.WidgetType;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.widget.WidgetTypeDao;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
+
+ @Autowired
+ private WidgetTypeDao widgetTypeDao;
+
+ @Test
+ @DatabaseSetup(("classpath:dbunit/widget_type.xml"))
+ public void testFindByTenantIdAndBundleAlias() {
+ UUID tenantId = UUID.fromString("2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833");
+ List<WidgetType> widgetTypes = widgetTypeDao.findWidgetTypesByTenantIdAndBundleAlias(tenantId, "BUNDLE_ALIAS_1");
+ assertEquals(3, widgetTypes.size());
+ }
+
+ @Test
+ @DatabaseSetup(("classpath:dbunit/widget_type.xml"))
+ public void testFindByTenantIdAndBundleAliasAndAlias() {
+ UUID tenantId = UUID.fromString("2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833");
+ WidgetType widgetType = widgetTypeDao.findByTenantIdBundleAliasAndAlias(tenantId, "BUNDLE_ALIAS_1", "ALIAS3");
+ UUID id = UUID.fromString("2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833");
+ assertEquals(id, widgetType.getId().getId());
+ }
+}
diff --git a/dao/src/test/resources/dbunit/users.xml b/dao/src/test/resources/dbunit/users.xml
index 644a6e9..b1e51dd 100644
--- a/dao/src/test/resources/dbunit/users.xml
+++ b/dao/src/test/resources/dbunit/users.xml
@@ -11,7 +11,6 @@
/>
<user id="uuid'1312f328-27c7-11e7-93ae-92361f002671'"
tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
- customer_id="uuid'22fe91e8-27c7-11e7-93ae-92361f002671'"
authority="1"
email="tenantadm1@thingsboard.org"
search_text="TENANTADM1 SEARCH TEXT"
@@ -21,7 +20,6 @@
/>
<user id="uuid'2b090dde-27ca-11e7-93ae-92361f002671'"
tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
- customer_id="uuid'34be535c-27ca-11e7-93ae-92361f002671'"
authority="1"
email="tenantadm2@thingsboard.org"
search_text="TENANTADM2 SEARCH TEXT"
diff --git a/dao/src/test/resources/dbunit/widget_type.xml b/dao/src/test/resources/dbunit/widget_type.xml
new file mode 100644
index 0000000..49664d3
--- /dev/null
+++ b/dao/src/test/resources/dbunit/widget_type.xml
@@ -0,0 +1,31 @@
+<dataset>
+ <widget_type
+ id="uuid'2b7e4c91-2dfe-11e7-94aa-f7f6dbfb4833'"
+ tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+ bundle_alias="BUNDLE_ALIAS_1"
+ alias="ALIAS1"
+ name="ALIAS1"
+ />
+ <widget_type
+ id="uuid'2b7e4c92-2dfe-11e7-94aa-f7f6dbfb4833'"
+ tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+ bundle_alias="BUNDLE_ALIAS_1"
+ alias="ALIAS2"
+ name="ALIAS2"
+ />
+ <widget_type
+ id="uuid'2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833'"
+ tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+ bundle_alias="BUNDLE_ALIAS_1"
+ alias="ALIAS3"
+ name="ALIAS3"
+ />
+ <widget_type
+ id="uuid'2b7e4c94-2dfe-11e7-94aa-f7f6dbfb4833'"
+ tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+ bundle_alias="BUNDLE_ALIAS_2"
+ alias="ALIAS4"
+ name="ALIAS4"
+ />
+
+</dataset>
\ No newline at end of file