Browse Source

Entity data query - query builder

pull/2989/head
Igor Kulikov 6 years ago
parent
commit
3acae2fbf2
  1. 65
      application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java
  2. 46
      application/src/main/java/org/thingsboard/server/service/query/DefaultEntityQueryService.java
  3. 30
      application/src/main/java/org/thingsboard/server/service/query/EntityQueryService.java
  4. 2
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/TelemetryPluginCmdsWrapper.java
  5. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java
  6. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUnsubscribeCmd.java
  7. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java
  8. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityHistoryCmd.java
  9. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/LatestValueCmd.java
  10. 15
      application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/TimeSeriesCmd.java
  11. 7
      common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java
  12. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/AssetSearchQueryFilter.java
  13. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/AssetTypeFilter.java
  14. 35
      common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java
  15. 37
      common/data/src/main/java/org/thingsboard/server/common/data/query/ComplexFilterPredicate.java
  16. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/DeviceSearchQueryFilter.java
  17. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/DeviceTypeFilter.java
  18. 15
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java
  19. 15
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java
  20. 18
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataPageLink.java
  21. 24
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataQuery.java
  22. 39
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataSortOrder.java
  23. 15
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityFilter.java
  24. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityFilterType.java
  25. 18
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java
  26. 18
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKeyType.java
  27. 35
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityListFilter.java
  28. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityNameFilter.java
  29. 31
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntitySearchQueryFilter.java
  30. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityViewSearchQueryFilter.java
  31. 32
      common/data/src/main/java/org/thingsboard/server/common/data/query/EntityViewTypeFilter.java
  32. 23
      common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateType.java
  33. 26
      common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java
  34. 22
      common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilterPredicate.java
  35. 39
      common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java
  36. 39
      common/data/src/main/java/org/thingsboard/server/common/data/query/RelationsQueryFilter.java
  37. 15
      common/data/src/main/java/org/thingsboard/server/common/data/query/SingleEntityFilter.java
  38. 40
      common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java
  39. 15
      common/data/src/main/java/org/thingsboard/server/common/data/query/TsValue.java
  40. 55
      dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
  41. 31
      dao/src/main/java/org/thingsboard/server/dao/entity/EntityQueryDao.java
  42. 1
      dao/src/main/java/org/thingsboard/server/dao/service/Validator.java
  43. 551
      dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java
  44. 36
      dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java
  45. 31
      dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryRepository.java
  46. 45
      dao/src/main/java/org/thingsboard/server/dao/sql/query/JpaEntityQueryDao.java

65
application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java

@ -0,0 +1,65 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.query.EntityQueryService;
@RestController
@TbCoreComponent
@RequestMapping("/api")
public class EntityQueryController extends BaseController {
@Autowired
private EntityQueryService entityQueryService;
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entitiesQuery/count", method = RequestMethod.POST)
@ResponseBody
public long countEntitiesByQuery(@RequestBody EntityCountQuery query) throws ThingsboardException {
checkNotNull(query);
try {
return this.entityQueryService.countEntitiesByQuery(getCurrentUser(), query);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entitiesQuery/find", method = RequestMethod.POST)
@ResponseBody
public PageData<EntityData> findEntityDataByQuery(@RequestBody EntityDataQuery query) throws ThingsboardException {
checkNotNull(query);
try {
return this.entityQueryService.findEntityDataByQuery(getCurrentUser(), query);
} catch (Exception e) {
throw handleException(e);
}
}
}

46
application/src/main/java/org/thingsboard/server/service/query/DefaultEntityQueryService.java

@ -0,0 +1,46 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.query;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
@Service
@Slf4j
@TbCoreComponent
public class DefaultEntityQueryService implements EntityQueryService {
@Autowired
private EntityService entityService;
@Override
public long countEntitiesByQuery(SecurityUser securityUser, EntityCountQuery query) {
return entityService.countEntitiesByQuery(securityUser.getTenantId(), securityUser.getCustomerId(), query);
}
@Override
public PageData<EntityData> findEntityDataByQuery(SecurityUser securityUser, EntityDataQuery query) {
return entityService.findEntityDataByQuery(securityUser.getTenantId(), securityUser.getCustomerId(), query);
}
}

30
application/src/main/java/org/thingsboard/server/service/query/EntityQueryService.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.query;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.service.security.model.SecurityUser;
public interface EntityQueryService {
long countEntitiesByQuery(SecurityUser securityUser, EntityCountQuery query);
PageData<EntityData> findEntityDataByQuery(SecurityUser securityUser, EntityDataQuery query);
}

2
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/TelemetryPluginCmdsWrapper.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import lombok.Data; import lombok.Data;

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUnsubscribeCmd.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import lombok.Data; import lombok.Data;

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import lombok.Data; import lombok.Data;

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityHistoryCmd.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import org.thingsboard.server.common.data.kv.Aggregation; import org.thingsboard.server.common.data.kv.Aggregation;

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/LatestValueCmd.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import org.thingsboard.server.common.data.query.EntityKey; import org.thingsboard.server.common.data.query.EntityKey;

15
application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/TimeSeriesCmd.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.telemetry.cmd.v2; package org.thingsboard.server.service.telemetry.cmd.v2;
import java.util.List; import java.util.List;

7
common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -16,6 +16,7 @@
package org.thingsboard.server.dao.entity; package org.thingsboard.server.dao.entity;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
@ -29,8 +30,8 @@ public interface EntityService {
void deleteEntityRelations(TenantId tenantId, EntityId entityId); void deleteEntityRelations(TenantId tenantId, EntityId entityId);
long countEntitiesByQuery(TenantId tenantId, EntityCountQuery query); long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query);
PageData<EntityData> findEntityDataByQuery(TenantId tenantId, EntityDataQuery query); PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query);
} }

32
common/data/src/main/java/org/thingsboard/server/common/data/query/AssetSearchQueryFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import java.util.List;
@Data
public class AssetSearchQueryFilter extends EntitySearchQueryFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ASSET_SEARCH_QUERY;
}
private List<String> assetTypes;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/AssetTypeFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class AssetTypeFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ASSET_TYPE;
}
private String assetType;
private String assetNameFilter;
}

35
common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class BooleanFilterPredicate implements KeyFilterPredicate {
private BooleanOperation operation;
private boolean value;
@Override
public FilterPredicateType getType() {
return FilterPredicateType.BOOLEAN;
}
public enum BooleanOperation {
EQUAL,
NOT_EQUAL
}
}

37
common/data/src/main/java/org/thingsboard/server/common/data/query/ComplexFilterPredicate.java

@ -0,0 +1,37 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import java.util.List;
@Data
public class ComplexFilterPredicate implements KeyFilterPredicate {
private ComplexOperation operation;
private List<KeyFilterPredicate> predicates;
@Override
public FilterPredicateType getType() {
return FilterPredicateType.COMPLEX;
}
public enum ComplexOperation {
AND,
OR
}
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/DeviceSearchQueryFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import java.util.List;
@Data
public class DeviceSearchQueryFilter extends EntitySearchQueryFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.DEVICE_SEARCH_QUERY;
}
private List<String> deviceTypes;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/DeviceTypeFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class DeviceTypeFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.DEVICE_TYPE;
}
private String deviceType;
private String deviceNameFilter;
}

15
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Getter; import lombok.Getter;

15
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Data; import lombok.Data;

18
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataPageLink.java

@ -1,13 +1,27 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.page.SortOrder;
@Data @Data
public class EntityDataPageLink { public class EntityDataPageLink {
private final int pageSize; private final int pageSize;
private final int page; private final int page;
private final SortOrder sortOrder; private final EntityDataSortOrder sortOrder;
} }

24
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataQuery.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Getter; import lombok.Getter;
@ -12,11 +27,18 @@ public class EntityDataQuery extends EntityCountQuery {
private final List<EntityKey> entityFields; private final List<EntityKey> entityFields;
@Getter @Getter
private final List<EntityKey> latestValues; private final List<EntityKey> latestValues;
@Getter
private final List<KeyFilter> keyFilters;
public EntityDataQuery(EntityFilter entityFilter, EntityDataPageLink pageLink, List<EntityKey> entityFields, List<EntityKey> latestValues) { public EntityDataQuery(EntityFilter entityFilter,
EntityDataPageLink pageLink,
List<EntityKey> entityFields,
List<EntityKey> latestValues,
List<KeyFilter> keyFilters) {
super(entityFilter); super(entityFilter);
this.pageLink = pageLink; this.pageLink = pageLink;
this.entityFields = entityFields; this.entityFields = entityFields;
this.latestValues = latestValues; this.latestValues = latestValues;
this.keyFilters = keyFilters;
} }
} }

39
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityDataSortOrder.java

@ -0,0 +1,39 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class EntityDataSortOrder {
private final EntityKey key;
private final Direction direction;
public EntityDataSortOrder(EntityKey key) {
this(key, Direction.ASC);
}
public EntityDataSortOrder(EntityKey key, Direction direction) {
this.key = key;
this.direction = direction;
}
public enum Direction {
ASC, DESC
}
}

15
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityFilter.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
public interface EntityFilter { public interface EntityFilter {

32
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityFilterType.java

@ -1,17 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
public enum EntityFilterType { public enum EntityFilterType {
SINGLE_ENTITY("singleEntity"), SINGLE_ENTITY("singleEntity"),
ENTITY_LIST("entityList"), ENTITY_LIST("entityList"),
ENTITY_NAME("entityName"); ENTITY_NAME("entityName"),
// stateEntity = 'stateEntity', ASSET_TYPE("assetType"),
// assetType = 'assetType', DEVICE_TYPE("deviceType"),
// deviceType = 'deviceType', ENTITY_VIEW_TYPE("entityViewType"),
// entityViewType = 'entityViewType', RELATIONS_QUERY("relationsQuery"),
// relationsQuery = 'relationsQuery', ASSET_SEARCH_QUERY("assetSearchQuery"),
// assetSearchQuery = 'assetSearchQuery', DEVICE_SEARCH_QUERY("deviceSearchQuery"),
// deviceSearchQuery = 'deviceSearchQuery', ENTITY_VIEW_SEARCH_QUERY("entityViewSearchQuery");
// entityViewSearchQuery = 'entityViewSearchQuery'
private final String label; private final String label;

18
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java

@ -1,5 +1,23 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class EntityKey { public class EntityKey {
private EntityKeyType type; private EntityKeyType type;
private String key; private String key;

18
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKeyType.java

@ -1,9 +1,25 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
public enum EntityKeyType { public enum EntityKeyType {
ATTRIBUTE,
CLIENT_ATTRIBUTE, CLIENT_ATTRIBUTE,
SHARED_ATTRIBUTE, SHARED_ATTRIBUTE,
SERVER_ATTRIBUTE, SERVER_ATTRIBUTE,
TIMESERIES, TIME_SERIES,
ENTITY_FIELD; ENTITY_FIELD;
} }

35
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityListFilter.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId;
import java.util.List;
@Data
public class EntityListFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ENTITY_LIST;
}
private EntityType entityType;
private List<String> entityList;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityNameFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
@Data
public class EntityNameFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ENTITY_NAME;
}
private EntityType entityType;
private String entityNameFilter;
}

31
common/data/src/main/java/org/thingsboard/server/common/data/query/EntitySearchQueryFilter.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
@Data
public abstract class EntitySearchQueryFilter implements EntityFilter {
private EntityId rootEntity;
private String relationType;
private EntitySearchDirection direction;
private int maxLevel;
private boolean fetchLastLevelOnly;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityViewSearchQueryFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import java.util.List;
@Data
public class EntityViewSearchQueryFilter extends EntitySearchQueryFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ENTITY_VIEW_SEARCH_QUERY;
}
private List<String> entityViewTypes;
}

32
common/data/src/main/java/org/thingsboard/server/common/data/query/EntityViewTypeFilter.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class EntityViewTypeFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.ENTITY_VIEW_TYPE;
}
private String entityViewType;
private String entityViewNameFilter;
}

23
common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateType.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
public enum FilterPredicateType {
STRING,
NUMERIC,
BOOLEAN,
COMPLEX
}

26
common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java

@ -0,0 +1,26 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class KeyFilter {
private EntityKey key;
private KeyFilterPredicate predicate;
}

22
common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilterPredicate.java

@ -0,0 +1,22 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
public interface KeyFilterPredicate {
FilterPredicateType getType();
}

39
common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java

@ -0,0 +1,39 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class NumericFilterPredicate implements KeyFilterPredicate {
private NumericOperation operation;
private double value;
@Override
public FilterPredicateType getType() {
return FilterPredicateType.NUMERIC;
}
public enum NumericOperation {
EQUAL,
NOT_EQUAL,
GREATER,
LESS,
GREATER_OR_EQUAL,
LESS_OR_EQUAL
}
}

39
common/data/src/main/java/org/thingsboard/server/common/data/query/RelationsQueryFilter.java

@ -0,0 +1,39 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.common.data.relation.EntityTypeFilter;
import java.util.List;
@Data
public class RelationsQueryFilter implements EntityFilter {
@Override
public EntityFilterType getType() {
return EntityFilterType.RELATIONS_QUERY;
}
private EntityId rootEntity;
private EntitySearchDirection direction;
private List<EntityTypeFilter> filters;
private int maxLevel;
private boolean fetchLastLevelOnly;
}

15
common/data/src/main/java/org/thingsboard/server/common/data/query/SingleEntityFilter.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Data; import lombok.Data;

40
common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java

@ -0,0 +1,40 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query;
import lombok.Data;
@Data
public class StringFilterPredicate implements KeyFilterPredicate {
private StringOperation operation;
private String value;
private boolean ignoreCase;
@Override
public FilterPredicateType getType() {
return FilterPredicateType.STRING;
}
public enum StringOperation {
EQUAL,
NOT_EQUAL,
STARTS_WITH,
ENDS_WITH,
CONTAINS,
NOT_CONTAINS
}
}

15
common/data/src/main/java/org/thingsboard/server/common/data/query/TsValue.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.query; package org.thingsboard.server.common.data.query;
import lombok.Data; import lombok.Data;

55
dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java

@ -33,6 +33,10 @@ import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataPageLink;
import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.asset.AssetService;
@ -40,10 +44,13 @@ import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserService;
import static org.thingsboard.server.dao.service.Validator.validateId;
/** /**
* Created by ashvayka on 04.05.17. * Created by ashvayka on 04.05.17.
*/ */
@ -51,6 +58,9 @@ import org.thingsboard.server.dao.user.UserService;
@Slf4j @Slf4j
public class BaseEntityService extends AbstractEntityService implements EntityService { public class BaseEntityService extends AbstractEntityService implements EntityService {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId ";
@Autowired @Autowired
private AssetService assetService; private AssetService assetService;
@ -78,14 +88,30 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
@Autowired @Autowired
private RuleChainService ruleChainService; private RuleChainService ruleChainService;
@Autowired
private EntityQueryDao entityQueryDao;
@Override @Override
public void deleteEntityRelations(TenantId tenantId, EntityId entityId) { public void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
super.deleteEntityRelations(tenantId, entityId); super.deleteEntityRelations(tenantId, entityId);
} }
@Override @Override
public long countEntitiesByQuery(TenantId tenantId, EntityDataQuery query) { public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) {
return 0; log.trace("Executing countEntitiesByQuery, tenantId [{}], customerId [{}], query [{}]", tenantId, customerId, query);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
validateEntityCountQuery(query);
return this.entityQueryDao.countEntitiesByQuery(tenantId, customerId, query);
}
@Override
public PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
log.trace("Executing findEntityDataByQuery, tenantId [{}], customerId [{}], query [{}]", tenantId, customerId, query);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
validateEntityDataQuery(query);
return this.entityQueryDao.findEntityDataByQuery(tenantId, customerId, query);
} }
@Override @Override
@ -128,4 +154,29 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
return entityName; return entityName;
} }
private static void validateEntityCountQuery(EntityCountQuery query) {
if (query == null) {
throw new IncorrectParameterException("Query must be specified.");
} else if (query.getEntityFilter() == null) {
throw new IncorrectParameterException("Query entity filter must be specified.");
} else if (query.getEntityFilter().getType() == null) {
throw new IncorrectParameterException("Query entity filter type must be specified.");
}
}
private static void validateEntityDataQuery(EntityDataQuery query) {
validateEntityCountQuery(query);
validateEntityDataPageLink(query.getPageLink());
}
private static void validateEntityDataPageLink(EntityDataPageLink pageLink) {
if (pageLink == null) {
throw new IncorrectParameterException("Entity Data Page link must be specified.");
} else if (pageLink.getPageSize() < 1) {
throw new IncorrectParameterException("Incorrect entity data page link page size '"+pageLink.getPageSize()+"'. Page size must be greater than zero.");
} else if (pageLink.getPage() < 0) {
throw new IncorrectParameterException("Incorrect entity data page link page '"+pageLink.getPage()+"'. Page must be positive integer.");
}
}
} }

31
dao/src/main/java/org/thingsboard/server/dao/entity/EntityQueryDao.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.entity;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
public interface EntityQueryDao {
long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query);
PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query);
}

1
dao/src/main/java/org/thingsboard/server/dao/service/Validator.java

@ -114,7 +114,6 @@ public class Validator {
* <code>IncorrectParameterException</code> exception * <code>IncorrectParameterException</code> exception
* *
* @param pageLink the page link * @param pageLink the page link
* @param errorMessage the error message for exception
*/ */
public static void validatePageLink(PageLink pageLink) { public static void validatePageLink(PageLink pageLink) {
if (pageLink == null) { if (pageLink == null) {

551
dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java

@ -0,0 +1,551 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.query;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.AssetTypeFilter;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
import org.thingsboard.server.common.data.query.ComplexFilterPredicate;
import org.thingsboard.server.common.data.query.DeviceTypeFilter;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataPageLink;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.common.data.query.EntityFilter;
import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.common.data.query.EntityListFilter;
import org.thingsboard.server.common.data.query.EntityNameFilter;
import org.thingsboard.server.common.data.query.EntityViewTypeFilter;
import org.thingsboard.server.common.data.query.FilterPredicateType;
import org.thingsboard.server.common.data.query.KeyFilter;
import org.thingsboard.server.common.data.query.KeyFilterPredicate;
import org.thingsboard.server.common.data.query.NumericFilterPredicate;
import org.thingsboard.server.common.data.query.SingleEntityFilter;
import org.thingsboard.server.common.data.query.StringFilterPredicate;
import org.thingsboard.server.common.data.query.TsValue;
import org.thingsboard.server.dao.util.SqlDao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@SqlDao
@Repository
@Slf4j
public class DefaultEntityQueryRepository implements EntityQueryRepository {
private static final Map<String, String> entityFieldColumnMap = new HashMap<>();
static {
entityFieldColumnMap.put("createdTime", "id");
entityFieldColumnMap.put("name", "name");
entityFieldColumnMap.put("type", "type");
entityFieldColumnMap.put("label", "label");
entityFieldColumnMap.put("firstName", "first_name");
entityFieldColumnMap.put("lastName", "last_name");
entityFieldColumnMap.put("email", "email");
entityFieldColumnMap.put("title", "title");
entityFieldColumnMap.put("country", "country");
entityFieldColumnMap.put("state", "state");
entityFieldColumnMap.put("city", "city");
entityFieldColumnMap.put("address", "address");
entityFieldColumnMap.put("address2", "address2");
entityFieldColumnMap.put("zip", "zip");
entityFieldColumnMap.put("phone", "phone");
}
private static final Map<EntityType, String> entityTableMap = new HashMap<>();
static {
entityTableMap.put(EntityType.ASSET, "asset");
entityTableMap.put(EntityType.DEVICE, "device");
entityTableMap.put(EntityType.ENTITY_VIEW, "entity_view");
entityTableMap.put(EntityType.DASHBOARD, "dashboard");
entityTableMap.put(EntityType.CUSTOMER, "customer");
entityTableMap.put(EntityType.USER, "tb_user");
entityTableMap.put(EntityType.TENANT, "tenant");
}
@PersistenceContext
private EntityManager entityManager;
@Override
public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) {
EntityType entityType = resolveEntityType(query.getEntityFilter());
String countQuery = String.format("select count(e.id) from %s e where %s",
entityTableMap.get(entityType), this.buildEntityWhere(tenantId, customerId, query.getEntityFilter(),
Collections.emptyList(), entityType));
return ((BigInteger)entityManager.createNativeQuery(countQuery)
.getSingleResult()).longValue();
}
@Override
public PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
EntityType entityType = resolveEntityType(query.getEntityFilter());
List<EntityKeyMapping> mappings = prepareKeyMapping(query);
List<EntityKeyMapping> selectionMapping = mappings.stream().filter(mapping -> mapping.isSelection())
.collect(Collectors.toList());
List<EntityKeyMapping> entityFieldsSelectionMapping = selectionMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> latestSelectionMapping = selectionMapping.stream().filter(mapping -> mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> filterMapping = mappings.stream().filter(mapping -> mapping.hasFilter())
.collect(Collectors.toList());
List<EntityKeyMapping> entityFieldsFiltersMapping = filterMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> latestFiltersMapping = filterMapping.stream().filter(mapping -> mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> allLatestMappings = mappings.stream().filter(mapping -> mapping.isLatest())
.collect(Collectors.toList());
String entityWhereClause = this.buildEntityWhere(tenantId, customerId, query.getEntityFilter(), entityFieldsFiltersMapping, entityType);
String latestJoins = this.buildLatestJoins(entityType, allLatestMappings);
String latestFilters = this.buildLatestQuery(latestFiltersMapping);
String countQuery = String.format("select count(*) from (select e.id from %s e where %s) entities %s",
entityTableMap.get(entityType), entityWhereClause, latestJoins);
if (!StringUtils.isEmpty(latestFilters)) {
countQuery = String.format("%s where %s", countQuery, latestFilters);
}
int totalElements = ((BigInteger)entityManager.createNativeQuery(countQuery)
.getSingleResult()).intValue();
String entityFieldsSelection = this.buildEntityFieldsSelection(entityFieldsSelectionMapping);
if (!StringUtils.isEmpty(entityFieldsSelection)) {
entityFieldsSelection = String.format("e.id, %s", entityFieldsSelection);
} else {
entityFieldsSelection = "e.id";
}
String latestSelection = this.buildLatestSelections(latestSelectionMapping);
String topSelection = "entities.*";
if (!StringUtils.isEmpty(latestSelection)) {
topSelection = topSelection + ", " + latestSelection;
}
String dataQuery = String.format("select %s from (select %s from %s e where %s) entities %s", topSelection,
entityFieldsSelection,
entityTableMap.get(entityType),
entityWhereClause,
latestJoins);
if (!StringUtils.isEmpty(latestFilters)) {
dataQuery = String.format("%s where %s", dataQuery, latestFilters);
}
EntityDataPageLink pageLink = query.getPageLink();
// TODO: order by
int startIndex = pageLink.getPageSize() * pageLink.getPage();
if (pageLink.getPageSize() > 0) {
dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex);
}
List result = entityManager.createNativeQuery(dataQuery).getResultList();
int totalPages = pageLink.getPageSize() > 0 ? (int)Math.ceil((float)totalElements / pageLink.getPageSize()) : 1;
boolean hasNext = pageLink.getPageSize() > 0 && totalElements > startIndex + result.size();
List<EntityData> entitiesData = convertListToEntityData(result, entityType, selectionMapping);
return new PageData<>(entitiesData, totalPages, totalElements, hasNext);
}
private List<EntityData> convertListToEntityData(List<Object> result, EntityType entityType, List<EntityKeyMapping> selectionMapping) {
return result.stream().map(obj -> this.toEntityData(obj, entityType, selectionMapping)).collect(Collectors.toList());
}
private EntityData toEntityData(Object obj, EntityType entityType, List<EntityKeyMapping> selectionMapping) {
String id = obj instanceof String ? (String)obj : (String)((Object[]) obj)[0];
EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, UUIDConverter.fromString(id));
Map<EntityKeyType, Map<String, TsValue>> latest = new HashMap<>();
Map<String, TsValue[]> timeseries = new HashMap<>();
EntityData entityData = new EntityData(entityId, latest, timeseries);
for (EntityKeyMapping mapping: selectionMapping) {
Object value = ((Object[]) obj)[mapping.getIndex()];
// TODO:
}
return entityData;
}
private List<EntityKeyMapping> prepareKeyMapping(EntityDataQuery query) {
List<EntityKey> entityFields = query.getEntityFields() != null ? query.getEntityFields() : Collections.emptyList();
List<EntityKey> latestValues = query.getLatestValues() != null ? query.getLatestValues() : Collections.emptyList();
Map<EntityKey, List<KeyFilter>> filters =
query.getKeyFilters() != null ?
query.getKeyFilters().stream().collect(Collectors.groupingBy(KeyFilter::getKey)) : Collections.emptyMap();
int index = 1;
List<EntityKeyMapping> mappings = new ArrayList<>();
for (EntityKey entityField : entityFields) {
EntityKeyMapping mapping = new EntityKeyMapping();
mapping.setIndex(index);
mapping.setAlias(String.format("alias%s", index));
mapping.setKeyFilters(filters.remove(entityField));
mapping.setLatest(false);
mapping.setSelection(true);
mapping.setEntityKey(entityField);
mappings.add(mapping);
index++;
}
for (EntityKey latestField : latestValues) {
EntityKeyMapping mapping = new EntityKeyMapping();
mapping.setIndex(index);
mapping.setAlias(String.format("alias%s", index));
mapping.setKeyFilters(filters.remove(latestField));
mapping.setLatest(true);
mapping.setSelection(true);
mapping.setEntityKey(latestField);
mappings.add(mapping);
index +=2;
}
if (!filters.isEmpty()) {
for (EntityKey filterField : filters.keySet()) {
EntityKeyMapping mapping = new EntityKeyMapping();
mapping.setIndex(index);
mapping.setAlias(String.format("alias%s", index));
mapping.setKeyFilters(filters.get(filterField));
mapping.setLatest(!filterField.getType().equals(EntityKeyType.ENTITY_FIELD));
mapping.setSelection(false);
mapping.setEntityKey(filterField);
mappings.add(mapping);
index +=1;
}
}
return mappings;
}
private String buildEntityFieldsSelection(List<EntityKeyMapping> entityFieldsSelectionMapping) {
return entityFieldsSelectionMapping.stream().map(mapping -> {
String column = entityFieldColumnMap.get(mapping.getEntityKey().getKey());
return String.format("e.%s as %s", column, mapping.getAlias());
}).collect(
Collectors.joining(", "));
}
private String buildLatestSelections(List<EntityKeyMapping> latestSelectionMapping) {
return latestSelectionMapping.stream().map(mapping -> this.buildLatestSelection(mapping))
.collect(
Collectors.joining(", "));
}
private String buildLatestSelection(EntityKeyMapping mapping) {
if (mapping.getEntityKey().getType().equals(EntityKeyType.TIME_SERIES)) {
return buildTimeseriesSelection(mapping);
} else {
return buildAttributeSelection(mapping);
}
}
private String buildAttributeSelection(EntityKeyMapping mapping) {
String alias = mapping.getAlias();
String attrValAlias = alias + "_value";
String attrTsAlias = alias + "_ts";
String attrTsSelection = String.format("%s.last_update_ts as %s", alias, attrTsAlias);
String attrValSelection =
String.format("coalesce(cast(%s.bool_v as varchar), '') || " +
"coalesce(%s.str_v, '') || " +
"coalesce(cast(%s.long_v as varchar), '') || " +
"coalesce(cast(%s.dbl_v as varchar), '') || " +
"coalesce(cast(%s.json_v as varchar), '')) as %s", alias, alias, alias, alias, alias, attrValAlias);
return String.join(", ", attrTsSelection, attrValSelection);
}
private String buildTimeseriesSelection(EntityKeyMapping mapping) {
// TODO:
String alias = mapping.getAlias();
String attrValAlias = alias + "_value";
String attrTsAlias = alias + "_ts";
return String.format("(select 1) as %s, (select '') as %s", attrTsAlias, attrValAlias);
}
private String buildLatestJoins(EntityType entityType, List<EntityKeyMapping> latestMappings) {
return latestMappings.stream().map(mapping -> this.buildLatestJoin(entityType, mapping)).collect(
Collectors.joining(" "));
}
private String buildLatestJoin(EntityType entityType, EntityKeyMapping mapping) {
String join = mapping.hasFilter() ? "left join" : "left outer join";
if (mapping.getEntityKey().getType().equals(EntityKeyType.TIME_SERIES)) {
// TODO:
throw new RuntimeException("Not implemented!");
} else {
String alias = mapping.getAlias();
String query = String.format("%s attribute_kv %s ON %s.entity_id=entities.id AND %s.entity_type='%s' AND %s.attribute_key='%s'",
join, alias, alias, alias, entityType.name(), alias, mapping.getEntityKey().getKey());
if (!mapping.getEntityKey().getType().equals(EntityKeyType.ATTRIBUTE)) {
String scope;
if (mapping.getEntityKey().getType().equals(EntityKeyType.CLIENT_ATTRIBUTE)) {
scope = DataConstants.CLIENT_SCOPE;
} else if (mapping.getEntityKey().getType().equals(EntityKeyType.SHARED_ATTRIBUTE)) {
scope = DataConstants.SHARED_SCOPE;
} else {
scope = DataConstants.SERVER_SCOPE;
}
query = String.format("%s AND %s.attribute_type=%s", query, alias, scope);
}
return query;
}
}
private String buildEntityWhere(TenantId tenantId,
CustomerId customerId,
EntityFilter entityFilter,
List<EntityKeyMapping> entityFieldsFilters,
EntityType entityType) {
String permissionQuery = this.buildPermissionQuery(tenantId, customerId, entityType);
String entityFilterQuery = this.buildEntityFilterQuery(entityFilter);
if (!entityFieldsFilters.isEmpty()) {
String entityFieldsQuery = this.buildEntityFieldsQuery(entityFieldsFilters);
return String.join(" and ", permissionQuery, entityFilterQuery, entityFieldsQuery);
} else {
return String.join(" and ", permissionQuery, entityFilterQuery);
}
}
private String buildPermissionQuery(TenantId tenantId, CustomerId customerId, EntityType entityType) {
String permissionQuery = String.format("e.tenant_id=%s", UUIDConverter.fromTimeUUID(tenantId.getId()));
if (entityType != EntityType.TENANT && entityType != EntityType.CUSTOMER) {
permissionQuery = String.format("%s and e.customerId=%s", permissionQuery, UUIDConverter.fromTimeUUID(customerId.getId()));
}
return permissionQuery;
}
private String buildEntityFilterQuery(EntityFilter entityFilter) {
switch (entityFilter.getType()) {
case SINGLE_ENTITY:
return this.singleEntityQuery((SingleEntityFilter) entityFilter);
case ENTITY_LIST:
return this.entityListQuery((EntityListFilter) entityFilter);
case ENTITY_NAME:
return this.entityNameQuery((EntityNameFilter) entityFilter);
case ASSET_TYPE:
case DEVICE_TYPE:
case ENTITY_VIEW_TYPE:
return this.typeQuery(entityFilter);
default:
throw new RuntimeException("Not implemented!");
}
}
private String buildLatestQuery(List<EntityKeyMapping> latestFilters) {
List<String> latestQueries = new ArrayList<>();
for (EntityKeyMapping mapping: latestFilters) {
latestQueries.addAll(mapping.getKeyFilters().stream().map(keyFilter ->
this.buildKeyQuery(mapping.getAlias(), keyFilter))
.collect(Collectors.toList()));
}
return latestQueries.stream().collect(Collectors.joining(" AND "));
}
private String buildEntityFieldsQuery(List<EntityKeyMapping> entityFieldsFilters) {
return entityFieldsFilters.stream().flatMap(mapping -> mapping.getKeyFilters().stream())
.map(keyFilter -> this.buildKeyQuery("e", keyFilter)).collect(
Collectors.joining(" AND ")
);
}
private String buildKeyQuery(String alias, KeyFilter keyFilter) {
return this.buildPredicateQuery(alias, keyFilter.getKey(), keyFilter.getPredicate());
}
private String buildPredicateQuery(String alias, EntityKey key, KeyFilterPredicate predicate) {
if (predicate.getType().equals(FilterPredicateType.COMPLEX)) {
return this.buildComplexPredicateQuery(alias, key, (ComplexFilterPredicate)predicate);
} else {
return this.buildSimplePredicateQuery(alias, key, predicate);
}
}
private String buildComplexPredicateQuery(String alias, EntityKey key, ComplexFilterPredicate predicate) {
return predicate.getPredicates().stream()
.map(keyFilterPredicate -> this.buildPredicateQuery(alias, key, keyFilterPredicate)).collect(Collectors.joining(
" " + predicate.getOperation().name() + " "
));
}
private String buildSimplePredicateQuery(String alias, EntityKey key, KeyFilterPredicate predicate) {
if (predicate.getType().equals(FilterPredicateType.NUMERIC)) {
if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
String column = entityFieldColumnMap.get(key.getKey());
return this.buildNumericPredicateQuery(alias + "." + column, (NumericFilterPredicate)predicate);
} else {
String longQuery = this.buildNumericPredicateQuery(alias + ".long_v", (NumericFilterPredicate)predicate);
String doubleQuery = this.buildNumericPredicateQuery(alias + ".dbl_v", (NumericFilterPredicate)predicate);
return String.format("(%s or %s)", longQuery, doubleQuery);
}
} else {
String column;
if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
column = entityFieldColumnMap.get(key.getKey());
} else {
column = predicate.getType().equals(FilterPredicateType.STRING) ? "str_v" : "bool_v";
}
String field = alias + "." + column;
if (predicate.getType().equals(FilterPredicateType.STRING)) {
return this.buildStringPredicateQuery(field, (StringFilterPredicate)predicate);
} else {
return this.buildBooleanPredicateQuery(field, (BooleanFilterPredicate)predicate);
}
}
}
private String buildStringPredicateQuery(String field, StringFilterPredicate stringFilterPredicate) {
String operationField = field;
String value = stringFilterPredicate.getValue();
String stringOperationQuery = "";
if (stringFilterPredicate.isIgnoreCase()) {
value.toLowerCase();
operationField = String.format("lower(%s)", operationField);
}
switch (stringFilterPredicate.getOperation()) {
case EQUAL:
stringOperationQuery = String.format("%s = '%s'", operationField, value);
break;
case NOT_EQUAL:
stringOperationQuery = String.format("%s != '%s'", operationField, value);
break;
case STARTS_WITH:
stringOperationQuery = String.format("%s like '%s%'", operationField, value);
break;
case ENDS_WITH:
stringOperationQuery = String.format("%s like '%%s'", operationField, value);
break;
case CONTAINS:
stringOperationQuery = String.format("%s like '%%s%'", operationField, value);
break;
case NOT_CONTAINS:
stringOperationQuery = String.format("%s not like '%%s%'", operationField, value);
break;
}
return String.format("(%s is not null and %s)", field, stringOperationQuery);
}
private String buildNumericPredicateQuery(String field, NumericFilterPredicate numericFilterPredicate) {
double value = numericFilterPredicate.getValue();
String numericOperationQuery = "";
switch (numericFilterPredicate.getOperation()) {
case EQUAL:
numericOperationQuery = String.format("%s = %s", field, value);
break;
case NOT_EQUAL:
numericOperationQuery = String.format("%s != '%s'", field, value);
break;
case GREATER:
numericOperationQuery = String.format("%s > %s", field, value);
break;
case GREATER_OR_EQUAL:
numericOperationQuery = String.format("%s >= %s", field, value);
break;
case LESS:
numericOperationQuery = String.format("%s < %s", field, value);
break;
case LESS_OR_EQUAL:
numericOperationQuery = String.format("%s <= %s", field, value);
break;
}
return String.format("(%s is not null and %s)", field, numericOperationQuery);
}
private String buildBooleanPredicateQuery(String field,
BooleanFilterPredicate booleanFilterPredicate) {
boolean value = booleanFilterPredicate.isValue();
String booleanOperationQuery = "";
switch (booleanFilterPredicate.getOperation()) {
case EQUAL:
booleanOperationQuery = String.format("%s = %s", field, value);
break;
case NOT_EQUAL:
booleanOperationQuery = String.format("%s != %s", field, value);
break;
}
return String.format("(%s is not null and %s)", field, booleanOperationQuery);
}
private String singleEntityQuery(SingleEntityFilter filter) {
return String.format("e.id=%s", UUIDConverter.fromTimeUUID(filter.getSingleEntity().getId()));
}
private String entityListQuery(EntityListFilter filter) {
return String.format("e.id in (%s)",
filter.getEntityList().stream().map(UUID::fromString).map(UUIDConverter::fromTimeUUID).collect(Collectors.joining(",")));
}
private String entityNameQuery(EntityNameFilter filter) {
return String.format("lower(e.searchText) like lower(concat(%s, '%'))", filter.getEntityNameFilter());
}
private String typeQuery(EntityFilter filter) {
String type;
String name;
switch (filter.getType()) {
case ASSET_TYPE:
type = ((AssetTypeFilter)filter).getAssetType();
name = ((AssetTypeFilter)filter).getAssetNameFilter();
break;
case DEVICE_TYPE:
type = ((DeviceTypeFilter)filter).getDeviceType();
name = ((DeviceTypeFilter)filter).getDeviceNameFilter();
break;
case ENTITY_VIEW_TYPE:
type = ((EntityViewTypeFilter)filter).getEntityViewType();
name = ((EntityViewTypeFilter)filter).getEntityViewNameFilter();
break;
default:
throw new RuntimeException("Not supported!");
}
return String.format("e.type = %s and lower(e.searchText) like lower(concat(%s, '%'))", type, name);
}
private EntityType resolveEntityType(EntityFilter entityFilter) {
switch (entityFilter.getType()) {
case SINGLE_ENTITY:
return ((SingleEntityFilter)entityFilter).getSingleEntity().getEntityType();
case ENTITY_LIST:
return ((EntityListFilter)entityFilter).getEntityType();
case ENTITY_NAME:
return ((EntityNameFilter)entityFilter).getEntityType();
case ASSET_TYPE:
case ASSET_SEARCH_QUERY:
return EntityType.ASSET;
case DEVICE_TYPE:
case DEVICE_SEARCH_QUERY:
return EntityType.DEVICE;
case ENTITY_VIEW_TYPE:
case ENTITY_VIEW_SEARCH_QUERY:
return EntityType.ENTITY_VIEW;
default:
throw new RuntimeException("Not implemented!");
}
}
}

36
dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.query;
import lombok.Data;
import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.KeyFilter;
import java.util.List;
@Data
public class EntityKeyMapping {
private int index;
private String alias;
private boolean isLatest;
private boolean isSelection;
private List<KeyFilter> keyFilters;
private EntityKey entityKey;
public boolean hasFilter() {
return keyFilters != null && !keyFilters.isEmpty();
}
}

31
dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryRepository.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.query;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
public interface EntityQueryRepository {
long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query);
PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query);
}

45
dao/src/main/java/org/thingsboard/server/dao/sql/query/JpaEntityQueryDao.java

@ -0,0 +1,45 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* 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
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.dao.entity.EntityQueryDao;
import org.thingsboard.server.dao.util.SqlDao;
@Component
@SqlDao
public class JpaEntityQueryDao implements EntityQueryDao {
@Autowired
private EntityQueryRepository entityQueryRepository;
@Override
public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) {
return entityQueryRepository.countEntitiesByQuery(tenantId, customerId, query);
}
@Override
public PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
return entityQueryRepository.findEntityDataByQuery(tenantId, customerId, query);
}
}
Loading…
Cancel
Save