Browse Source
* Experiments with CSV * CSV Loader v1 * EDQ tests * Volatile variables instead of final * Improvements * updated loader with new entities * Fix double memory usage issue * Basic data structures and load * Minor improvements * Snappy + Large String reuse * added EntityFields classes for each entity * Basic implementation * Minor improvements to KeyFilters * implemented RepositoryUtils.checkKeyFilters * Generic query implementation * New structure * Refactoring and few processors implementation * extended DeviceData with shared/client attributes and device profile * Minor refactoring of attribute scopes * DeviceTypeFilter support * Strong types of fields for each entity data class * DeviceType and AssetType filters * EntityView and Edge queries * Relations Query * Relation Query Implementation * Update EDQS module version * Sync with EDQS via Kafka * EDQS: major refactoring * EDQS API requests via Kafka * EDQS: full sync with the database * Refactoring for EDQS sync * EDQS: major refactoring and new features * EDQS refactoring, count query support, fix tests * EDQS: refactoring for query processors * Fix EDQS pom version * Cleanup edqs.yml * EDQS: tenant partitioning strategy; refactoring * EDQS: latest events queue * EDQS: support for monolith setup; RocksDB; other improvements * EDQS: merge sync and events topics, introduce state topic * EDQS: dynamic repartitioning * implemented entity data query filters for edqs * EdqsEntityQueryControllerTest - use in-memory queue * edqs-filter fixes, added test * EDQS: blob entity support * EdqsEntityQueryControllerTest - use in-memory queue * Use DummyEdqsService when disabled * Fixes for EDQS * Refactoring for EDQS tests * Fix edqs requests partitioning * EDQS: Fix for attributes handling * Fix attributes saving in EntityServiceTest * EDQS: refactoring, fixes * Minor refactoring for query processor * added ownerName/ownerType support * fixed relation query processor * fixed EntityServiceTest * refactoring * added support for parentId for relation query result * Get rid of EntityNameFetcher * Add fixme for relation query processor * db restore with select all edqs fields * fixed entity deletion * fixed FieldUtils with new EntityFields * dao method renamed * EDQS: instance groups with same partitions; automatic sync; multiple fixes * Refactoring for EDQS sync * EDQS: refactoring * Fix startup with Kafka * fixed EntityQueryControllerTest * fixed EdqsEntityServiceTest * Separate queue admin for EDQS request template * Implement new EDQS partitioning strategy * EDQS: multiple fixes and refactoring * Add mock EdqsRocksDb beans to tests * added edqs stats for inmemory/grafana * fixed filter tests * Update todos * Refactoring for QueueConfig * Improvements and refactoring for EDQS consumers * implemented TODOs * test fixes * Consume state topic up to end offsets * edqs stats refactoring * EDQS: cleanup on partitions removal; refactoring * EDQS: minor refactoring * EDQS: remove CSV loader --------- Co-authored-by: Andrii Shvaika <ashvayka@thingsboard.io> Co-authored-by: dashevchenko <dshevchenko@thingsboard.io>pull/12580/head
committed by
ViacheslavKlimov
358 changed files with 18294 additions and 675 deletions
@ -0,0 +1,340 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.google.common.util.concurrent.Futures; |
||||
|
import com.google.common.util.concurrent.ListenableFuture; |
||||
|
import com.google.common.util.concurrent.MoreExecutors; |
||||
|
import com.google.protobuf.ByteString; |
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import jakarta.annotation.PreDestroy; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.SneakyThrows; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.context.annotation.Lazy; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.common.util.JacksonUtil; |
||||
|
import org.thingsboard.common.util.ThingsBoardExecutors; |
||||
|
import org.thingsboard.server.cluster.TbClusterService; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.edqs.EdqsEventType; |
||||
|
import org.thingsboard.server.common.data.edqs.EdqsObject; |
||||
|
import org.thingsboard.server.common.data.edqs.EdqsSyncRequest; |
||||
|
import org.thingsboard.server.common.data.edqs.Entity; |
||||
|
import org.thingsboard.server.common.data.edqs.ToCoreEdqsMsg; |
||||
|
import org.thingsboard.server.common.data.edqs.ToCoreEdqsRequest; |
||||
|
import org.thingsboard.server.common.data.edqs.query.EdqsRequest; |
||||
|
import org.thingsboard.server.common.data.edqs.query.EdqsResponse; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.JsonDataEntry; |
||||
|
import org.thingsboard.server.common.data.kv.KvEntry; |
||||
|
import org.thingsboard.server.common.msg.edqs.EdqsService; |
||||
|
import org.thingsboard.server.common.msg.queue.ServiceType; |
||||
|
import org.thingsboard.server.dao.attributes.AttributesService; |
||||
|
import org.thingsboard.server.edqs.processor.EdqsConverter; |
||||
|
import org.thingsboard.server.edqs.processor.EdqsProducer; |
||||
|
import org.thingsboard.server.edqs.util.EdqsPartitionService; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.EdqsEventMsg; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.EdqsRequestMsg; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.FromEdqsMsg; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsCoreServiceMsg; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg; |
||||
|
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
||||
|
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
||||
|
import org.thingsboard.server.queue.discovery.HashPartitionService; |
||||
|
import org.thingsboard.server.queue.edqs.EdqsQueue; |
||||
|
import org.thingsboard.server.queue.environment.DistributedLock; |
||||
|
import org.thingsboard.server.queue.environment.DistributedLockService; |
||||
|
import org.thingsboard.server.queue.provider.EdqsClientQueueFactory; |
||||
|
import org.thingsboard.server.queue.util.AfterStartUp; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ExecutorService; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
@ConditionalOnProperty(value = "queue.edqs.sync_enabled", havingValue = "true") |
||||
|
public class DefaultEdqsService implements EdqsService { |
||||
|
|
||||
|
private final EdqsClientQueueFactory queueFactory; |
||||
|
private final EdqsConverter edqsConverter; |
||||
|
private final EdqsSyncService edqsSyncService; |
||||
|
private final DistributedLockService distributedLockService; |
||||
|
private final AttributesService attributesService; |
||||
|
private final EdqsPartitionService edqsPartitionService; |
||||
|
@Autowired @Lazy |
||||
|
private TbClusterService clusterService; |
||||
|
@Autowired @Lazy |
||||
|
private HashPartitionService hashPartitionService; |
||||
|
|
||||
|
@Value("${queue.edqs.api_enabled:false}") |
||||
|
private Boolean apiEnabled; |
||||
|
|
||||
|
private EdqsProducer eventsProducer; |
||||
|
private TbQueueRequestTemplate<TbProtoQueueMsg<ToEdqsMsg>, TbProtoQueueMsg<FromEdqsMsg>> requestTemplate; |
||||
|
private ExecutorService executor; |
||||
|
private DistributedLock<EdqsSyncState> syncLock; |
||||
|
|
||||
|
@PostConstruct |
||||
|
private void init() { |
||||
|
executor = ThingsBoardExecutors.newWorkStealingPool(12, getClass()); |
||||
|
eventsProducer = EdqsProducer.builder() |
||||
|
.queue(EdqsQueue.EVENTS) |
||||
|
.partitionService(edqsPartitionService) |
||||
|
.producer(queueFactory.createEdqsMsgProducer(EdqsQueue.EVENTS)) |
||||
|
.build(); |
||||
|
if (apiEnabled) { |
||||
|
apiEnabled = null; |
||||
|
} |
||||
|
|
||||
|
requestTemplate = queueFactory.createEdqsRequestTemplate(); |
||||
|
requestTemplate.init(); |
||||
|
syncLock = distributedLockService.getLock("edqs_sync"); |
||||
|
} |
||||
|
|
||||
|
@AfterStartUp(order = AfterStartUp.REGULAR_SERVICE) |
||||
|
public void onStartUp() { |
||||
|
executor.submit(() -> { |
||||
|
try { |
||||
|
EdqsSyncState syncState = getSyncState(); |
||||
|
if (edqsSyncService.isSyncNeeded() || syncState == null || syncState.getStatus() != EdqsSyncStatus.FINISHED) { |
||||
|
if (hashPartitionService.isSystemPartitionMine(ServiceType.TB_CORE)) { |
||||
|
processSystemRequest(ToCoreEdqsRequest.builder() |
||||
|
.syncRequest(new EdqsSyncRequest()) |
||||
|
.build()); |
||||
|
} |
||||
|
} else { // only if topic/RocksDB is not empty and sync is finished
|
||||
|
if (apiEnabled == null) { |
||||
|
log.info("EDQS is already synced, enabling API"); |
||||
|
apiEnabled = true; |
||||
|
} else { |
||||
|
log.info("EDQS is already synced"); |
||||
|
} |
||||
|
} |
||||
|
} catch (Throwable e) { |
||||
|
log.error("Failed to start EDQS service", e); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void processSystemRequest(ToCoreEdqsRequest request) { |
||||
|
log.info("Processing system request {}", request); |
||||
|
if (request.getSyncRequest() != null) { |
||||
|
saveSyncState(EdqsSyncStatus.REQUESTED); |
||||
|
} |
||||
|
broadcast(request.toInternalMsg()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void processSystemMsg(ToCoreEdqsMsg msg) { |
||||
|
executor.submit(() -> { |
||||
|
log.info("Processing system msg {}", msg); |
||||
|
try { |
||||
|
if (msg.getApiEnabled() != null) { |
||||
|
apiEnabled = msg.getApiEnabled(); |
||||
|
} |
||||
|
|
||||
|
if (msg.getSyncRequest() != null) { |
||||
|
syncLock.lock(); |
||||
|
try { |
||||
|
EdqsSyncState syncState = getSyncState(); |
||||
|
if (syncState != null && syncState.getStatus() == EdqsSyncStatus.FINISHED) { |
||||
|
log.info("EDQS sync is already finished"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
saveSyncState(EdqsSyncStatus.STARTED); |
||||
|
edqsSyncService.sync(); |
||||
|
|
||||
|
saveSyncState(EdqsSyncStatus.FINISHED); |
||||
|
if (apiEnabled == null) { |
||||
|
broadcast(ToCoreEdqsMsg.builder() |
||||
|
.apiEnabled(Boolean.TRUE) |
||||
|
.build()); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.error("Failed to complete sync", e); |
||||
|
saveSyncState(EdqsSyncStatus.FAILED); |
||||
|
} finally { |
||||
|
syncLock.unlock(); |
||||
|
} |
||||
|
} |
||||
|
} catch (Throwable e) { |
||||
|
log.error("Failed to process msg {}", msg, e); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onUpdate(TenantId tenantId, EntityId entityId, Object entity) { |
||||
|
EntityType entityType = entityId.getEntityType(); |
||||
|
ObjectType objectType = ObjectType.fromEntityType(entityType); |
||||
|
if (!isEdqsType(tenantId, objectType)) { |
||||
|
log.trace("[{}][{}] Ignoring update event, type {} not supported", tenantId, entityId, entityType); |
||||
|
return; |
||||
|
} |
||||
|
onUpdate(tenantId, objectType, edqsConverter.toEntity(entityType, entity)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onUpdate(TenantId tenantId, ObjectType objectType, EdqsObject object) { |
||||
|
processEvent(tenantId, objectType, EdqsEventType.UPDATED, object); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onDelete(TenantId tenantId, EntityId entityId) { |
||||
|
EntityType entityType = entityId.getEntityType(); |
||||
|
ObjectType objectType = ObjectType.fromEntityType(entityType); |
||||
|
if (!isEdqsType(tenantId, objectType)) { |
||||
|
log.trace("[{}][{}] Ignoring deletion event, type {} not supported", tenantId, entityId, entityType); |
||||
|
return; |
||||
|
} |
||||
|
onDelete(tenantId, objectType, new Entity(entityType, entityId.getId(), Long.MAX_VALUE)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onDelete(TenantId tenantId, ObjectType objectType, EdqsObject object) { |
||||
|
processEvent(tenantId, objectType, EdqsEventType.DELETED, object); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ListenableFuture<EdqsResponse> processRequest(TenantId tenantId, CustomerId customerId, EdqsRequest request) { |
||||
|
var requestMsg = newEdqsMsg(tenantId) |
||||
|
.setRequestMsg(EdqsRequestMsg.newBuilder() |
||||
|
.setValue(JacksonUtil.toString(request)) |
||||
|
.build()); |
||||
|
if (customerId != null && !customerId.isNullUid()) { |
||||
|
requestMsg.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); |
||||
|
requestMsg.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); |
||||
|
} |
||||
|
|
||||
|
Integer partition = edqsPartitionService.resolvePartition(tenantId); |
||||
|
ListenableFuture<TbProtoQueueMsg<FromEdqsMsg>> resultFuture = requestTemplate.send(new TbProtoQueueMsg<>(UUID.randomUUID(), requestMsg.build()), partition); |
||||
|
return Futures.transform(resultFuture, msg -> { |
||||
|
TransportProtos.EdqsResponseMsg responseMsg = msg.getValue().getResponseMsg(); |
||||
|
return JacksonUtil.fromString(responseMsg.getValue(), EdqsResponse.class); |
||||
|
}, MoreExecutors.directExecutor()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isApiEnabled() { |
||||
|
return Boolean.TRUE.equals(apiEnabled); |
||||
|
} |
||||
|
|
||||
|
protected void processEvent(TenantId tenantId, ObjectType objectType, EdqsEventType eventType, EdqsObject object) { |
||||
|
executor.submit(() -> { |
||||
|
try { |
||||
|
String key = object.key(); |
||||
|
Long version = object.version(); |
||||
|
EdqsEventMsg.Builder eventMsg = EdqsEventMsg.newBuilder() |
||||
|
.setKey(key) |
||||
|
.setObjectType(objectType.name()) |
||||
|
.setData(ByteString.copyFrom(edqsConverter.serialize(objectType, object))) |
||||
|
.setEventType(eventType.name()); |
||||
|
if (version != null) { |
||||
|
eventMsg.setVersion(version); |
||||
|
} |
||||
|
eventsProducer.send(tenantId, objectType, key, newEdqsMsg(tenantId) |
||||
|
.setEventMsg(eventMsg) |
||||
|
.build()); |
||||
|
} catch (Throwable e) { |
||||
|
log.error("[{}] Failed to push {} event for {} {}", tenantId, eventType, objectType, object, e); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private boolean isEdqsType(TenantId tenantId, ObjectType objectType) { |
||||
|
if (objectType == null) { |
||||
|
return false; |
||||
|
} |
||||
|
if (!tenantId.isSysTenantId()) { |
||||
|
return ObjectType.edqsTypes.contains(objectType); |
||||
|
} else { |
||||
|
return ObjectType.edqsSystemTypes.contains(objectType); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void broadcast(ToCoreEdqsMsg msg) { |
||||
|
clusterService.broadcastToCore(ToCoreNotificationMsg.newBuilder() |
||||
|
.setToEdqsCoreServiceMsg(ToEdqsCoreServiceMsg.newBuilder() |
||||
|
.setValue(ByteString.copyFrom(JacksonUtil.writeValueAsBytes(msg)))) |
||||
|
.build()); |
||||
|
} |
||||
|
|
||||
|
private static ToEdqsMsg.Builder newEdqsMsg(TenantId tenantId) { |
||||
|
return ToEdqsMsg.newBuilder() |
||||
|
.setTenantIdMSB(tenantId.getId().getMostSignificantBits()) |
||||
|
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) |
||||
|
.setTs(System.currentTimeMillis()); |
||||
|
} |
||||
|
|
||||
|
@PreDestroy |
||||
|
private void preDestroy() { |
||||
|
executor.shutdown(); |
||||
|
eventsProducer.stop(); |
||||
|
requestTemplate.stop(); |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
private EdqsSyncState getSyncState() { |
||||
|
EdqsSyncState state = attributesService.find(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, AttributeScope.SERVER_SCOPE, "edqsSyncState").get(30, TimeUnit.SECONDS) |
||||
|
.flatMap(KvEntry::getJsonValue) |
||||
|
.map(value -> JacksonUtil.fromString(value, EdqsSyncState.class)) |
||||
|
.orElse(null); |
||||
|
log.info("getSyncState = {}", state); |
||||
|
return state; |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
private void saveSyncState(EdqsSyncStatus status) { |
||||
|
EdqsSyncState state = new EdqsSyncState(status); |
||||
|
log.info("saveSyncState {}", state); |
||||
|
attributesService.save(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, AttributeScope.SERVER_SCOPE, new BaseAttributeKvEntry( |
||||
|
new JsonDataEntry("edqsSyncState", JacksonUtil.toString(state)), |
||||
|
System.currentTimeMillis())).get(30, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
private static class EdqsSyncState { |
||||
|
private EdqsSyncStatus status; |
||||
|
} |
||||
|
|
||||
|
private enum EdqsSyncStatus { |
||||
|
REQUESTED, |
||||
|
STARTED, |
||||
|
FINISHED, |
||||
|
FAILED |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,539 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.MappingIterator; |
||||
|
import com.fasterxml.jackson.dataformat.csv.CsvMapper; |
||||
|
import com.fasterxml.jackson.dataformat.csv.CsvSchema; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.thingsboard.common.util.ThingsBoardThreadFactory; |
||||
|
import org.thingsboard.server.common.data.ApiUsageState; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.Customer; |
||||
|
import org.thingsboard.server.common.data.Dashboard; |
||||
|
import org.thingsboard.server.common.data.Device; |
||||
|
import org.thingsboard.server.common.data.DeviceProfile; |
||||
|
import org.thingsboard.server.common.data.DeviceProfileType; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.EntityView; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.StringUtils; |
||||
|
import org.thingsboard.server.common.data.Tenant; |
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.asset.Asset; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.converter.Converter; |
||||
|
import org.thingsboard.server.common.data.converter.ConverterType; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
import org.thingsboard.server.common.data.edqs.AttributeKv; |
||||
|
import org.thingsboard.server.common.data.edqs.LatestTsKv; |
||||
|
import org.thingsboard.server.common.data.group.EntityGroup; |
||||
|
import org.thingsboard.server.common.data.id.ApiUsageStateId; |
||||
|
import org.thingsboard.server.common.data.id.AssetId; |
||||
|
import org.thingsboard.server.common.data.id.AssetProfileId; |
||||
|
import org.thingsboard.server.common.data.id.ConverterId; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
import org.thingsboard.server.common.data.id.DashboardId; |
||||
|
import org.thingsboard.server.common.data.id.DeviceId; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.EdgeId; |
||||
|
import org.thingsboard.server.common.data.id.EntityGroupId; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.EntityIdFactory; |
||||
|
import org.thingsboard.server.common.data.id.EntityViewId; |
||||
|
import org.thingsboard.server.common.data.id.IntegrationId; |
||||
|
import org.thingsboard.server.common.data.id.RoleId; |
||||
|
import org.thingsboard.server.common.data.id.RuleChainId; |
||||
|
import org.thingsboard.server.common.data.id.SchedulerEventId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.id.TenantProfileId; |
||||
|
import org.thingsboard.server.common.data.id.UserId; |
||||
|
import org.thingsboard.server.common.data.id.WidgetTypeId; |
||||
|
import org.thingsboard.server.common.data.id.WidgetsBundleId; |
||||
|
import org.thingsboard.server.common.data.integration.Integration; |
||||
|
import org.thingsboard.server.common.data.integration.IntegrationType; |
||||
|
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
||||
|
import org.thingsboard.server.common.data.kv.DoubleDataEntry; |
||||
|
import org.thingsboard.server.common.data.kv.JsonDataEntry; |
||||
|
import org.thingsboard.server.common.data.kv.KvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.LongDataEntry; |
||||
|
import org.thingsboard.server.common.data.kv.StringDataEntry; |
||||
|
import org.thingsboard.server.common.data.relation.EntityRelation; |
||||
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
||||
|
import org.thingsboard.server.common.data.role.Role; |
||||
|
import org.thingsboard.server.common.data.role.RoleType; |
||||
|
import org.thingsboard.server.common.data.rule.RuleChain; |
||||
|
import org.thingsboard.server.common.data.scheduler.SchedulerEvent; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetType; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle; |
||||
|
import org.thingsboard.server.common.msg.edqs.EdqsService; |
||||
|
import org.thingsboard.server.edqs.processor.EdqsConverter; |
||||
|
|
||||
|
import java.io.FileReader; |
||||
|
import java.util.Map; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ExecutorService; |
||||
|
import java.util.concurrent.Executors; |
||||
|
import java.util.function.Consumer; |
||||
|
|
||||
|
import static org.thingsboard.common.util.JacksonUtil.toJsonNode; |
||||
|
|
||||
|
|
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
//@Service
|
||||
|
public class EdqsDataLoader { |
||||
|
|
||||
|
private final EdqsService edqsService; |
||||
|
private final EdqsConverter edqsConverter; |
||||
|
|
||||
|
public final static TenantId MAIN = TenantId.fromUUID(UUID.fromString("2a209df0-c7ff-11ea-a3e0-f321b0429d60")); |
||||
|
|
||||
|
private final String folder = "/home/viacheslav/Downloads/schwarz"; |
||||
|
|
||||
|
private ExecutorService executor = Executors.newFixedThreadPool(5, ThingsBoardThreadFactory.forName("edqs-publisher")); |
||||
|
|
||||
|
// @AfterStartUp(order = 100)
|
||||
|
public void load() throws Exception { |
||||
|
loadCustomers(); |
||||
|
loadDeviceProfile(); |
||||
|
loadDevices(); |
||||
|
loadAssets(); |
||||
|
loadEdges(); |
||||
|
loadEntityViews(); |
||||
|
loadTenants(); |
||||
|
loadUsers(); |
||||
|
loadDashboards(); |
||||
|
loadRuleChains(); |
||||
|
loadWidgetType(); |
||||
|
loadWidgetBundle(); |
||||
|
loadConverters(); |
||||
|
loadIntegrations(); |
||||
|
loadSchedulerEvents(); |
||||
|
loadRoles(); |
||||
|
loadApiUsageStates(); |
||||
|
loadAssetProfile(); |
||||
|
loadEntityGroups(); |
||||
|
loadRelations(); |
||||
|
|
||||
|
loadAttributes(); |
||||
|
loadTs(); |
||||
|
} |
||||
|
|
||||
|
private void loadCustomers() throws Exception { |
||||
|
load("customer.csv", (values) -> { |
||||
|
Customer customer = new Customer(); |
||||
|
customer.setTitle(values.get("title")); |
||||
|
customer.setId(new CustomerId(UUID.fromString(values.get("id")))); |
||||
|
customer.setCreatedTime(Long.parseLong(values.get("created_time"))); |
||||
|
customer.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
var parentCustomerId = values.get("parent_customer_id"); |
||||
|
if (StringUtils.isNotEmpty(parentCustomerId)) { |
||||
|
customer.setParentCustomerId(new CustomerId(UUID.fromString(parentCustomerId))); |
||||
|
} |
||||
|
edqsService.onUpdate(customer.getTenantId(), customer.getId(), customer); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadDevices() throws Exception { |
||||
|
load("device.csv", (values) -> { |
||||
|
Device device = new Device(); |
||||
|
device.setType(values.get("type")); |
||||
|
device.setName(values.get("name")); |
||||
|
device.setLabel(values.get("label")); |
||||
|
device.setId(new DeviceId(uuid(values.get("id")))); |
||||
|
device.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
device.setCustomerId(customerId(values.get("customer_id"))); |
||||
|
device.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
device.setDeviceProfileId(new DeviceProfileId(uuid(values.get("device_profile_id")))); |
||||
|
device.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(device.getTenantId(), device.getId(), device); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadAssets() throws Exception { |
||||
|
load("asset.csv", (values) -> { |
||||
|
Asset asset = new Asset(); |
||||
|
asset.setType(values.get("type")); |
||||
|
asset.setName(values.get("name")); |
||||
|
asset.setLabel(values.get("label")); |
||||
|
asset.setId(new AssetId(uuid(values.get("id")))); |
||||
|
asset.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
asset.setCustomerId(customerId(values.get("customer_id"))); |
||||
|
asset.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
asset.setAssetProfileId(new AssetProfileId(uuid(values.get("asset_profile_id")))); |
||||
|
asset.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(asset.getTenantId(), asset.getId(), asset); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadEdges() throws Exception { |
||||
|
load("edge.csv", (values) -> { |
||||
|
Edge edge = new Edge(); |
||||
|
edge.setId(new EdgeId(uuid(values.get("id")))); |
||||
|
edge.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
edge.setType(values.get("type")); |
||||
|
edge.setName(values.get("name")); |
||||
|
edge.setLabel(values.get("label")); |
||||
|
edge.setCustomerId(customerId(values.get("customer_id"))); |
||||
|
edge.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
edge.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(edge.getTenantId(), edge.getId(), edge); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadEntityViews() throws Exception { |
||||
|
load("entity_view.csv", (values) -> { |
||||
|
EntityView entityView = new EntityView(); |
||||
|
entityView.setId(new EntityViewId(uuid(values.get("id")))); |
||||
|
entityView.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
entityView.setType(values.get("type")); |
||||
|
entityView.setName(values.get("name")); |
||||
|
entityView.setCustomerId(customerId(values.get("customer_id"))); |
||||
|
entityView.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
entityView.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(entityView.getTenantId(), entityView.getId(), entityView); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadTenants() throws Exception { |
||||
|
load("tenant.csv", (values) -> { |
||||
|
Tenant tenant = new Tenant(); |
||||
|
tenant.setId(new TenantId(uuid(values.get("id")))); |
||||
|
tenant.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
tenant.setEmail(values.get("email")); |
||||
|
tenant.setTitle(values.get("title")); |
||||
|
tenant.setCountry(values.get("country")); |
||||
|
tenant.setState(values.get("state")); |
||||
|
tenant.setCity(values.get("city")); |
||||
|
tenant.setAddress(values.get("address")); |
||||
|
tenant.setAddress2(values.get("address2")); |
||||
|
tenant.setZip(values.get("zip")); |
||||
|
tenant.setPhone(values.get("phone")); |
||||
|
tenant.setRegion(values.get("region")); |
||||
|
tenant.setTenantProfileId(new TenantProfileId(uuid(values.get("tenant_profile_id")))); |
||||
|
tenant.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
edqsService.onUpdate(MAIN, tenant.getId(), tenant); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadUsers() throws Exception { |
||||
|
load("user.csv", (values) -> { |
||||
|
User user = new User(); |
||||
|
user.setId(new UserId(uuid(values.get("id")))); |
||||
|
user.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
user.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
user.setFirstName(values.get("first_name")); |
||||
|
user.setLastName(values.get("last_name")); |
||||
|
user.setEmail(values.get("email")); |
||||
|
user.setPhone(values.get("phone")); |
||||
|
user.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(user.getTenantId(), user.getId(), user); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadDashboards() throws Exception { |
||||
|
load("dashboard.csv", (values) -> { |
||||
|
Dashboard dashboard = new Dashboard(); |
||||
|
dashboard.setId(new DashboardId(uuid(values.get("id")))); |
||||
|
dashboard.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
dashboard.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
dashboard.setTitle(values.get("title")); |
||||
|
|
||||
|
edqsService.onUpdate(dashboard.getTenantId(), dashboard.getId(), dashboard); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadEntityGroups() throws Exception { |
||||
|
load("entity_group.csv", (values) -> { |
||||
|
EntityGroup entityGroup = new EntityGroup(); |
||||
|
entityGroup.setId(new EntityGroupId(uuid(values.get("id")))); |
||||
|
entityGroup.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
entityGroup.setName(values.get("name")); |
||||
|
entityGroup.setOwnerId(entityId(values.get("owner_type"), values.get("owner_id"))); |
||||
|
entityGroup.setType(EntityType.valueOf(values.get("type"))); |
||||
|
edqsService.onUpdate(MAIN, entityGroup.getId(), entityGroup); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadRelations() throws Exception { |
||||
|
load("relation.csv", (values) -> { |
||||
|
EntityRelation entityRelation = new EntityRelation(); |
||||
|
entityRelation.setFrom(entityId(values.get("from_type"), values.get("from_id"))); |
||||
|
entityRelation.setTo(entityId(values.get("to_type"), values.get("to_id"))); |
||||
|
entityRelation.setTypeGroup(RelationTypeGroup.valueOf(values.get("relation_type_group"))); |
||||
|
entityRelation.setType(values.get("relation_type")); |
||||
|
edqsService.onUpdate(MAIN, ObjectType.RELATION, entityRelation); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadRuleChains() throws Exception { |
||||
|
load("rule_chain.csv", (values) -> { |
||||
|
RuleChain ruleChain = new RuleChain(); |
||||
|
ruleChain.setId(new RuleChainId(uuid(values.get("id")))); |
||||
|
ruleChain.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
ruleChain.setName(values.get("name")); |
||||
|
ruleChain.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
ruleChain.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(ruleChain.getTenantId(), ruleChain.getId(), ruleChain); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadWidgetType() throws Exception { |
||||
|
load("widget_type.csv", (values) -> { |
||||
|
WidgetType widgetType = new WidgetType(); |
||||
|
widgetType.setId(new WidgetTypeId(uuid(values.get("id")))); |
||||
|
widgetType.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
widgetType.setName(values.get("name")); |
||||
|
widgetType.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
|
||||
|
edqsService.onUpdate(widgetType.getTenantId(), widgetType.getId(), widgetType); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadWidgetBundle() throws Exception { |
||||
|
load("widgets_bundle.csv", (values) -> { |
||||
|
WidgetsBundle widgetsBundle = new WidgetsBundle(); |
||||
|
widgetsBundle.setId(new WidgetsBundleId(uuid(values.get("id")))); |
||||
|
widgetsBundle.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
widgetsBundle.setTitle(values.get("title")); |
||||
|
widgetsBundle.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
|
||||
|
edqsService.onUpdate(widgetsBundle.getTenantId(), widgetsBundle.getId(), widgetsBundle); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadConverters() throws Exception { |
||||
|
load("converter.csv", (values) -> { |
||||
|
Converter converter = new Converter(); |
||||
|
converter.setId(new ConverterId(uuid(values.get("id")))); |
||||
|
converter.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
converter.setName(values.get("name")); |
||||
|
converter.setType(ConverterType.valueOf(values.get("type"))); |
||||
|
converter.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
converter.setEdgeTemplate(parseBoolean(values.get("is_edge_template"))); |
||||
|
converter.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(converter.getTenantId(), converter.getId(), converter); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadIntegrations() throws Exception { |
||||
|
load("integration.csv", (values) -> { |
||||
|
Integration integration = new Integration(); |
||||
|
integration.setId(new IntegrationId(uuid(values.get("id")))); |
||||
|
integration.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
integration.setName(values.get("name")); |
||||
|
integration.setType(IntegrationType.valueOf(values.get("type"))); |
||||
|
integration.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
integration.setEdgeTemplate(parseBoolean(values.get("is_edge_template"))); |
||||
|
integration.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(integration.getTenantId(), integration.getId(), integration); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadSchedulerEvents() throws Exception { |
||||
|
load("scheduler_event.csv", (values) -> { |
||||
|
SchedulerEvent schedulerEvent = new SchedulerEvent(); |
||||
|
schedulerEvent.setId(new SchedulerEventId(uuid(values.get("id")))); |
||||
|
schedulerEvent.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
schedulerEvent.setName(values.get("name")); |
||||
|
schedulerEvent.setType(values.get("type")); |
||||
|
schedulerEvent.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
schedulerEvent.setConfiguration(toJsonNode(values.get("configuration"))); |
||||
|
schedulerEvent.setSchedule(toJsonNode(values.get("schedule"))); |
||||
|
schedulerEvent.setOriginatorId(entityId(values.get("originator_type"), values.get("originator_id"))); |
||||
|
schedulerEvent.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(schedulerEvent.getTenantId(), schedulerEvent.getId(), schedulerEvent); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadRoles() throws Exception { |
||||
|
load("role.csv", (values) -> { |
||||
|
Role role = new Role(); |
||||
|
role.setId(new RoleId(uuid(values.get("id")))); |
||||
|
role.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
role.setName(values.get("name")); |
||||
|
role.setType(RoleType.valueOf(values.get("type"))); |
||||
|
role.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
role.setAdditionalInfo(toJsonNode(values.get("additional_info"))); |
||||
|
|
||||
|
edqsService.onUpdate(role.getTenantId(), role.getId(), role); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadApiUsageStates() throws Exception { |
||||
|
load("api_usage_state.csv", (values) -> { |
||||
|
ApiUsageState apiUsageState = new ApiUsageState(); |
||||
|
apiUsageState.setId(new ApiUsageStateId(uuid(values.get("id")))); |
||||
|
apiUsageState.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
apiUsageState.setEntityId(entityId(values.get("entity_type"), values.get("entity_id"))); |
||||
|
apiUsageState.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
|
||||
|
edqsService.onUpdate(apiUsageState.getTenantId(), apiUsageState.getId(), apiUsageState); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadDeviceProfile() throws Exception { |
||||
|
load("device_profile.csv", (values) -> { |
||||
|
DeviceProfile deviceProfile = new DeviceProfile(); |
||||
|
deviceProfile.setId(new DeviceProfileId(uuid(values.get("id")))); |
||||
|
deviceProfile.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
deviceProfile.setName(values.get("name")); |
||||
|
deviceProfile.setType(DeviceProfileType.valueOf(values.get("type"))); |
||||
|
deviceProfile.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
|
||||
|
edqsService.onUpdate(deviceProfile.getTenantId(), deviceProfile.getId(), deviceProfile); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadAssetProfile() throws Exception { |
||||
|
load("asset_profile.csv", (values) -> { |
||||
|
AssetProfile assetProfile = new AssetProfile(); |
||||
|
assetProfile.setId(new AssetProfileId(uuid(values.get("id")))); |
||||
|
assetProfile.setCreatedTime(parseLong(values.get("created_time"))); |
||||
|
assetProfile.setName(values.get("name")); |
||||
|
assetProfile.setTenantId(tenantId(values.get("tenant_id"))); |
||||
|
|
||||
|
edqsService.onUpdate(assetProfile.getTenantId(), assetProfile.getId(), assetProfile); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadAttributes() throws Exception { |
||||
|
load("attribute.csv", (values) -> { |
||||
|
EntityId entityId = EntityIdFactory.getByTypeAndId(values.get("entity_type"), values.get("entity_id")); |
||||
|
long ts = parseLong(values.get("last_update_ts")); |
||||
|
AttributeScope scope = AttributeScope.valueOf(values.get("attribute_type")); |
||||
|
String key = values.get("attribute_key"); |
||||
|
KvEntry kvEntry; |
||||
|
if (StringUtils.isNotEmpty(values.get("bool_v"))) { |
||||
|
kvEntry = new BooleanDataEntry(key, "t".equals(values.get("bool_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("str_v"))) { |
||||
|
kvEntry = new StringDataEntry(key, values.get("str_v")); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("long_v"))) { |
||||
|
kvEntry = new LongDataEntry(key, parseLong(values.get("long_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("dbl_v"))) { |
||||
|
kvEntry = new DoubleDataEntry(key, Double.parseDouble(values.get("dbl_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("json_v"))) { |
||||
|
kvEntry = new JsonDataEntry(key, values.get("json_v")); |
||||
|
} else { |
||||
|
kvEntry = new StringDataEntry(key, ""); |
||||
|
} |
||||
|
AttributeKvEntry attributeKvEntry = new BaseAttributeKvEntry(ts, kvEntry); |
||||
|
AttributeKv attributeKv = new AttributeKv(entityId, scope, attributeKvEntry, 0); |
||||
|
edqsService.onUpdate(MAIN, ObjectType.ATTRIBUTE_KV, attributeKv); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void loadTs() throws Exception { |
||||
|
load("ts_kv.csv", (values) -> { |
||||
|
var entityTypeStr = values.get("find_entity_type"); |
||||
|
if (StringUtils.isEmpty(entityTypeStr)) { |
||||
|
return; |
||||
|
} |
||||
|
EntityId entityId = EntityIdFactory.getByTypeAndId(values.get("find_entity_type"), values.get("entity_id")); |
||||
|
long ts = parseLong(values.get("ts")); |
||||
|
String key = values.get("key"); |
||||
|
KvEntry kvEntry; |
||||
|
if (StringUtils.isNotEmpty(values.get("bool_v"))) { |
||||
|
kvEntry = new BooleanDataEntry(key, "t".equals(values.get("bool_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("str_v"))) { |
||||
|
kvEntry = new StringDataEntry(key, values.get("str_v")); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("long_v"))) { |
||||
|
kvEntry = new LongDataEntry(key, parseLong(values.get("long_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("dbl_v"))) { |
||||
|
kvEntry = new DoubleDataEntry(key, Double.parseDouble(values.get("dbl_v"))); |
||||
|
} else if (StringUtils.isNotEmpty(values.get("json_v"))) { |
||||
|
kvEntry = new JsonDataEntry(key, values.get("json_v")); |
||||
|
} else { |
||||
|
kvEntry = new StringDataEntry(key, ""); |
||||
|
} |
||||
|
BasicTsKvEntry tsKvEntry = new BasicTsKvEntry(ts, kvEntry); |
||||
|
edqsService.onUpdate(MAIN, ObjectType.LATEST_TS_KV, new LatestTsKv(entityId, tsKvEntry, 0L)); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void load(String file, Consumer<Map<String, String>> function) throws Exception { |
||||
|
Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("loader-" + file)).submit(() -> { |
||||
|
try { |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
CsvSchema schema = CsvSchema.emptySchema().withHeader().withColumnSeparator('|'); |
||||
|
CsvMapper mapper = new CsvMapper(); |
||||
|
MappingIterator<Map<String, String>> it = mapper |
||||
|
.readerFor(Map.class) |
||||
|
.with(schema) |
||||
|
.readValues(new FileReader(folder + "/" + file)); |
||||
|
|
||||
|
int success = 0; |
||||
|
int failure = 0; |
||||
|
while (it.hasNextValue()) { |
||||
|
Map<String, String> row = it.nextValue(); |
||||
|
try { |
||||
|
function.accept(row); |
||||
|
success++; |
||||
|
if (success % 1000 == 0) { |
||||
|
log.info("Loaded [{}] from [{}]", success, file); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.error("Failed to parse str: [{}]", row, e); |
||||
|
failure++; |
||||
|
} |
||||
|
} |
||||
|
log.info("Loaded [{}] from [{}] in {}ms. Failures {}", success, file, (System.currentTimeMillis() - ts), failure); |
||||
|
} catch (Throwable t) { |
||||
|
log.error("Failed to load data from [{}]", file, t); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private static TenantId tenantId(String id) { |
||||
|
return TenantId.fromUUID(UUID.fromString(id)); |
||||
|
} |
||||
|
|
||||
|
private static CustomerId customerId(String id) { |
||||
|
var c = new CustomerId(UUID.fromString(id)); |
||||
|
return c.isNullUid() ? null : c; |
||||
|
} |
||||
|
|
||||
|
private static EntityId entityId(String type, String id) { |
||||
|
return EntityIdFactory.getByTypeAndId(type, id); |
||||
|
} |
||||
|
|
||||
|
private static UUID uuid(String id) { |
||||
|
return UUID.fromString(id); |
||||
|
} |
||||
|
|
||||
|
private static long parseLong(String time) { |
||||
|
return Long.parseLong(time); |
||||
|
} |
||||
|
|
||||
|
private static boolean parseBoolean(String value) { |
||||
|
return Boolean.parseBoolean(value); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.event.TransactionalEventListener; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.audit.ActionType; |
||||
|
import org.thingsboard.server.common.msg.edqs.EdqsService; |
||||
|
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; |
||||
|
import org.thingsboard.server.dao.eventsourcing.RelationActionEvent; |
||||
|
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; |
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@ConditionalOnProperty(value = "queue.edqs.sync_enabled", havingValue = "true") |
||||
|
public class EdqsListener { |
||||
|
|
||||
|
private final EdqsService edqsService; |
||||
|
|
||||
|
@TransactionalEventListener(fallbackExecution = true) |
||||
|
public void onUpdate(SaveEntityEvent<?> event) { |
||||
|
if (event.getEntityId() == null || event.getEntity() == null) { |
||||
|
return; |
||||
|
} |
||||
|
edqsService.onUpdate(event.getTenantId(), event.getEntityId(), event.getEntity()); |
||||
|
} |
||||
|
|
||||
|
@TransactionalEventListener(fallbackExecution = true) |
||||
|
public void onDelete(DeleteEntityEvent<?> event) { |
||||
|
if (event.getEntityId() == null) { |
||||
|
return; |
||||
|
} |
||||
|
edqsService.onDelete(event.getTenantId(), event.getEntityId()); |
||||
|
} |
||||
|
|
||||
|
@TransactionalEventListener(fallbackExecution = true) |
||||
|
public void handleEvent(RelationActionEvent relationEvent) { |
||||
|
if (relationEvent.getActionType() == ActionType.RELATION_ADD_OR_UPDATE) { |
||||
|
edqsService.onUpdate(relationEvent.getTenantId(), ObjectType.RELATION, relationEvent.getRelation()); |
||||
|
} else if (relationEvent.getActionType() == ActionType.RELATION_DELETED) { |
||||
|
edqsService.onDelete(relationEvent.getTenantId(), ObjectType.RELATION, relationEvent.getRelation()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,275 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.context.annotation.Lazy; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.edqs.AttributeKv; |
||||
|
import org.thingsboard.server.common.data.edqs.EdqsEventType; |
||||
|
import org.thingsboard.server.common.data.edqs.EdqsObject; |
||||
|
import org.thingsboard.server.common.data.edqs.Entity; |
||||
|
import org.thingsboard.server.common.data.edqs.LatestTsKv; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.TenantFields; |
||||
|
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.PageDataIterable; |
||||
|
import org.thingsboard.server.common.data.page.SortOrder; |
||||
|
import org.thingsboard.server.common.data.relation.EntityRelation; |
||||
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
||||
|
import org.thingsboard.server.dao.Dao; |
||||
|
import org.thingsboard.server.dao.attributes.AttributesDao; |
||||
|
import org.thingsboard.server.dao.dictionary.KeyDictionaryDao; |
||||
|
import org.thingsboard.server.dao.entity.EntityDaoRegistry; |
||||
|
import org.thingsboard.server.dao.group.EntityGroupDao; |
||||
|
import org.thingsboard.server.dao.model.sql.AttributeKvEntity; |
||||
|
import org.thingsboard.server.dao.model.sqlts.dictionary.KeyDictionaryEntry; |
||||
|
import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestEntity; |
||||
|
import org.thingsboard.server.dao.relation.RelationDao; |
||||
|
import org.thingsboard.server.dao.tenant.TenantDao; |
||||
|
import org.thingsboard.server.dao.timeseries.TimeseriesLatestDao; |
||||
|
|
||||
|
import java.util.EnumSet; |
||||
|
import java.util.Map; |
||||
|
import java.util.Set; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
import java.util.concurrent.atomic.AtomicInteger; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.ObjectType.API_USAGE_STATE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ASSET; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ASSET_PROFILE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ATTRIBUTE_KV; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.BLOB_ENTITY; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.CONVERTER; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.CUSTOMER; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.DASHBOARD; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.DEVICE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.DEVICE_PROFILE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.EDGE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ENTITY_GROUP; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ENTITY_VIEW; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.INTEGRATION; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.LATEST_TS_KV; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.QUEUE_STATS; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.RELATION; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.ROLE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.RULE_CHAIN; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.SCHEDULER_EVENT; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.TENANT; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.TENANT_PROFILE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.USER; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.WIDGETS_BUNDLE; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.WIDGET_TYPE; |
||||
|
|
||||
|
@Slf4j |
||||
|
public abstract class EdqsSyncService { |
||||
|
|
||||
|
@Autowired |
||||
|
private EntityDaoRegistry entityDaoRegistry; |
||||
|
@Autowired |
||||
|
private TenantDao tenantDao; |
||||
|
@Autowired |
||||
|
private AttributesDao attributesDao; |
||||
|
@Autowired |
||||
|
private KeyDictionaryDao keyDictionaryDao; |
||||
|
@Autowired |
||||
|
private RelationDao relationDao; |
||||
|
@Autowired |
||||
|
private EntityGroupDao entityGroupDao; |
||||
|
@Autowired |
||||
|
private TimeseriesLatestDao timeseriesLatestDao; |
||||
|
@Autowired |
||||
|
@Lazy |
||||
|
private DefaultEdqsService edqsService; |
||||
|
|
||||
|
private final ConcurrentHashMap<UUID, EntityIdInfo> entityInfoMap = new ConcurrentHashMap<>(); |
||||
|
private final ConcurrentHashMap<Integer, String> keys = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
private final Map<ObjectType, AtomicInteger> counters = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
public static final Set<ObjectType> edqsTenantTypes = EnumSet.of( |
||||
|
TENANT_PROFILE, CUSTOMER, DEVICE_PROFILE, DEVICE, ASSET_PROFILE, ASSET, EDGE, ENTITY_VIEW, USER, DASHBOARD, |
||||
|
RULE_CHAIN, WIDGET_TYPE, WIDGETS_BUNDLE, CONVERTER, INTEGRATION, SCHEDULER_EVENT, ROLE, |
||||
|
BLOB_ENTITY, API_USAGE_STATE, QUEUE_STATS |
||||
|
); |
||||
|
|
||||
|
public abstract boolean isSyncNeeded(); |
||||
|
|
||||
|
public void sync() { |
||||
|
log.info("Synchronizing data to EDQS"); |
||||
|
long startTs = System.currentTimeMillis(); |
||||
|
counters.clear(); |
||||
|
|
||||
|
syncTenants(); |
||||
|
syncTenantEntities(); |
||||
|
syncEntityGroups(); |
||||
|
syncRelations(); |
||||
|
loadKeyDictionary(); |
||||
|
syncAttributes(); |
||||
|
syncLatestTimeseries(); |
||||
|
|
||||
|
counters.clear(); |
||||
|
log.info("Finishing synchronizing data to EDQS in {} ms", (System.currentTimeMillis() - startTs)); |
||||
|
} |
||||
|
|
||||
|
private void process(TenantId tenantId, ObjectType type, EdqsObject object) { |
||||
|
AtomicInteger counter = counters.computeIfAbsent(type, t -> new AtomicInteger()); |
||||
|
if (counter.incrementAndGet() % 10000 == 0) { |
||||
|
log.info("Processed {} {} objects", counter.get(), type); |
||||
|
} |
||||
|
edqsService.processEvent(tenantId, type, EdqsEventType.UPDATED, object); |
||||
|
} |
||||
|
|
||||
|
private void syncTenants() { |
||||
|
log.info("Synchronizing tenants to EDQS"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var tenants = new PageDataIterable<>(tenantDao::findAllFields, 10000); |
||||
|
for (EntityFields entityFields : tenants) { |
||||
|
TenantId tenantId = TenantId.fromUUID(entityFields.getId()); |
||||
|
entityInfoMap.put(entityFields.getId(), new EntityIdInfo(EntityType.TENANT, tenantId)); |
||||
|
process(tenantId, TENANT, new Entity(EntityType.TENANT, entityFields)); |
||||
|
} |
||||
|
process(TenantId.SYS_TENANT_ID, TENANT, new Entity(EntityType.TENANT, new TenantFields(TenantId.SYS_TENANT_ID.getId(), Long.MAX_VALUE))); |
||||
|
log.info("Finished synchronizing tenants to EDQS in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private void syncTenantEntities() { |
||||
|
for (ObjectType type : edqsTenantTypes) { |
||||
|
log.info("Synchronizing tenant {} entities to EDQS", type); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
EntityType entityType = type.toEntityType(); |
||||
|
Dao<?> dao = entityDaoRegistry.getDao(entityType); |
||||
|
var entities = new PageDataIterable<>(dao::findAllFields, 10000); |
||||
|
for (EntityFields entityFields : entities) { |
||||
|
TenantId tenantId = TenantId.fromUUID(entityFields.getTenantId()); |
||||
|
entityInfoMap.put(entityFields.getId(), new EntityIdInfo(entityType, tenantId)); |
||||
|
process(tenantId, type, new Entity(type.toEntityType(), entityFields)); |
||||
|
} |
||||
|
log.info("Finished synchronizing tenant {} entities to EDQS in {} ms", type, (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void syncEntityGroups() { |
||||
|
log.info("Synchronizing entity groups to EDQS"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var entityGroups = new PageDataIterable<>(entityGroupDao::findAllFields, 10000); |
||||
|
for (EntityFields groupFields : entityGroups) { |
||||
|
EntityIdInfo entityIdInfo = entityInfoMap.get(groupFields.getOwnerId()); |
||||
|
if (entityIdInfo != null) { |
||||
|
entityInfoMap.put(groupFields.getId(), new EntityIdInfo(EntityType.ENTITY_GROUP, entityIdInfo.tenantId())); |
||||
|
process(entityIdInfo.tenantId(), ENTITY_GROUP, new Entity(EntityType.ENTITY_GROUP, groupFields)); |
||||
|
} else { |
||||
|
log.info("Entity group owner not found: " + groupFields.getOwnerId()); |
||||
|
} |
||||
|
} |
||||
|
log.info("Finished synchronizing entity groups to EDQS in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private void syncRelations() { |
||||
|
log.info("Synchronizing relations to EDQS"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var relations = new PageDataIterable<>(relationDao::findAll, 10000); |
||||
|
for (EntityRelation relation : relations) { |
||||
|
if (relation.getTypeGroup() == RelationTypeGroup.COMMON || relation.getTypeGroup() == RelationTypeGroup.FROM_ENTITY_GROUP) { |
||||
|
EntityIdInfo entityIdInfo = entityInfoMap.get(relation.getFrom().getId()); |
||||
|
if (entityIdInfo != null) { |
||||
|
process(entityIdInfo.tenantId(), RELATION, relation); |
||||
|
} else { |
||||
|
log.info("Relation from entity not found: " + relation.getFrom()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
log.info("Finished synchronizing relations to EDQS in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private void loadKeyDictionary() { |
||||
|
log.info("Loading key dictionary"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var keyDictionaryEntries = new PageDataIterable<>(keyDictionaryDao::findAll, 10000); |
||||
|
for (KeyDictionaryEntry keyDictionaryEntry : keyDictionaryEntries) { |
||||
|
keys.put(keyDictionaryEntry.getKeyId(), keyDictionaryEntry.getKey()); |
||||
|
} |
||||
|
log.info("Finished loading key dictionary in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private void syncAttributes() { |
||||
|
log.info("Synchronizing attributes to EDQS"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var attributes = new PageDataIterable<>(attributesDao::findAll, 10000); |
||||
|
for (AttributeKvEntity attribute : attributes) { |
||||
|
attribute.setStrKey(getStrKeyOrFetchFromDb(attribute.getId().getAttributeKey())); |
||||
|
UUID entityId = attribute.getId().getEntityId(); |
||||
|
EntityIdInfo entityIdInfo = entityInfoMap.get(entityId); |
||||
|
if (entityIdInfo == null) { |
||||
|
log.debug("Skipping attribute with entity UUID {} as it is not found in entityInfoMap", entityId); |
||||
|
continue; |
||||
|
} |
||||
|
AttributeKv attributeKv = new AttributeKv( |
||||
|
EntityIdFactory.getByTypeAndUuid(entityIdInfo.entityType(), entityId), |
||||
|
AttributeScope.valueOf(attribute.getId().getAttributeType()), |
||||
|
attribute.toData(), |
||||
|
attribute.getVersion()); |
||||
|
process(entityIdInfo.tenantId(), ATTRIBUTE_KV, attributeKv); |
||||
|
} |
||||
|
log.info("Finished synchronizing attributes to EDQS in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private void syncLatestTimeseries() { |
||||
|
log.info("Synchronizing latest timeseries to EDQS"); |
||||
|
long ts = System.currentTimeMillis(); |
||||
|
var tsKvLatestEntities = new PageDataIterable<>(pageLink -> timeseriesLatestDao.findAllLatest(pageLink), 10000); |
||||
|
for (TsKvLatestEntity tsKvLatestEntity : tsKvLatestEntities) { |
||||
|
try { |
||||
|
String strKey = getStrKeyOrFetchFromDb(tsKvLatestEntity.getKey()); |
||||
|
if (strKey == null) { |
||||
|
log.debug("Skipping latest timeseries with key {} as it is not found in key dictionary", tsKvLatestEntity.getKey()); |
||||
|
continue; |
||||
|
} |
||||
|
tsKvLatestEntity.setStrKey(strKey); |
||||
|
UUID entityUuid = tsKvLatestEntity.getEntityId(); |
||||
|
EntityIdInfo entityIdInfo = entityInfoMap.get(entityUuid); |
||||
|
if (entityIdInfo != null) { |
||||
|
EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityIdInfo.entityType(), entityUuid); |
||||
|
LatestTsKv latestTsKv = new LatestTsKv(entityId, tsKvLatestEntity.toData(), tsKvLatestEntity.getVersion()); |
||||
|
process(entityIdInfo.tenantId(), LATEST_TS_KV, latestTsKv); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.error("Failed to sync latest timeseries: {}", tsKvLatestEntity, e); |
||||
|
} |
||||
|
} |
||||
|
log.info("Finished synchronizing latest timeseries to EDQS in {} ms", (System.currentTimeMillis() - ts)); |
||||
|
} |
||||
|
|
||||
|
private String getStrKeyOrFetchFromDb(int key) { |
||||
|
String strKey = keys.get(key); |
||||
|
if (strKey != null) { |
||||
|
return strKey; |
||||
|
} else { |
||||
|
strKey = keyDictionaryDao.getKey(key); |
||||
|
keys.putIfAbsent(key, strKey); |
||||
|
} |
||||
|
return strKey; |
||||
|
} |
||||
|
|
||||
|
public record EntityIdInfo(EntityType entityType, TenantId tenantId) {} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.queue.edqs.EdqsQueue; |
||||
|
import org.thingsboard.server.queue.kafka.TbKafkaAdmin; |
||||
|
import org.thingsboard.server.queue.kafka.TbKafkaSettings; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@ConditionalOnExpression("'${queue.edqs.sync_enabled:true}' == 'true' && '${queue.type:null}' == 'kafka'") |
||||
|
public class KafkaEdqsSyncService extends EdqsSyncService { |
||||
|
|
||||
|
private final TbKafkaSettings kafkaSettings; |
||||
|
private TbKafkaAdmin kafkaAdmin; |
||||
|
|
||||
|
@PostConstruct |
||||
|
private void init() { |
||||
|
kafkaAdmin = new TbKafkaAdmin(kafkaSettings, Collections.emptyMap()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isSyncNeeded() { |
||||
|
return kafkaAdmin.isTopicEmpty(EdqsQueue.STATE.getTopic()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.edqs.util.EdqsRocksDb; |
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@ConditionalOnExpression("'${queue.edqs.sync_enabled:true}' == 'true' && '${queue.type:null}' == 'in-memory'") |
||||
|
public class LocalEdqsSyncService extends EdqsSyncService { |
||||
|
|
||||
|
private final EdqsRocksDb db; |
||||
|
|
||||
|
@Override |
||||
|
public boolean isSyncNeeded() { |
||||
|
return db.isNew(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,224 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.sync.tenant; |
||||
|
|
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import lombok.Data; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.SneakyThrows; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.Tenant; |
||||
|
import org.thingsboard.server.common.data.audit.AuditLog; |
||||
|
import org.thingsboard.server.common.data.event.Event; |
||||
|
import org.thingsboard.server.common.data.event.EventType; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.HasId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.edqs.AttributeKv; |
||||
|
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
||||
|
import org.thingsboard.server.common.data.edqs.LatestTsKv; |
||||
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
||||
|
import org.thingsboard.server.common.data.page.PageDataIterable; |
||||
|
import org.thingsboard.server.common.data.page.TimePageLink; |
||||
|
import org.thingsboard.server.common.data.relation.EntityRelation; |
||||
|
import org.thingsboard.server.dao.TenantEntityDao; |
||||
|
import org.thingsboard.server.dao.attributes.AttributesDao; |
||||
|
import org.thingsboard.server.dao.audit.AuditLogDao; |
||||
|
import org.thingsboard.server.dao.entity.EntityDaoRegistry; |
||||
|
import org.thingsboard.server.dao.event.EventDao; |
||||
|
import org.thingsboard.server.dao.model.ModelConstants; |
||||
|
import org.thingsboard.server.dao.relation.RelationDao; |
||||
|
import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; |
||||
|
import org.thingsboard.server.dao.tenant.TenantDao; |
||||
|
import org.thingsboard.server.dao.timeseries.TimeseriesLatestDao; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.EnumSet; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Set; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
import java.util.function.BiConsumer; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.ObjectType.ATTRIBUTE_KV; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.AUDIT_LOG; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.EVENT; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.LATEST_TS_KV; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.RELATION; |
||||
|
import static org.thingsboard.server.common.data.ObjectType.TENANT; |
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class TenantExportService { |
||||
|
|
||||
|
private final EntityDaoRegistry entityDaoRegistry; |
||||
|
private final TenantDao tenantDao; |
||||
|
private final EventDao eventDao; |
||||
|
private final AuditLogDao auditLogDao; |
||||
|
private final AttributesDao attributesDao; |
||||
|
private final RelationDao relationDao; |
||||
|
private final TimeseriesLatestDao timeseriesLatestDao; |
||||
|
private final SqlPartitioningRepository partitioningRepository; |
||||
|
|
||||
|
private Map<ObjectType, BiConsumer<TenantId, BiConsumer<ObjectType, Object>>> customExporters; |
||||
|
private Map<ObjectType, Exporter> relatedEntitiesExporters; |
||||
|
|
||||
|
private static final Set<ObjectType> RELATED = EnumSet.of(EVENT, RELATION, ATTRIBUTE_KV, LATEST_TS_KV); |
||||
|
|
||||
|
@PostConstruct |
||||
|
private void init() { |
||||
|
relatedEntitiesExporters = Map.of( |
||||
|
RELATION, this::exportRelations, |
||||
|
EVENT, this::exportEvents, // todo: query by tenant
|
||||
|
ATTRIBUTE_KV, this::exportAttributes, |
||||
|
LATEST_TS_KV, this::exportLatestTelemetry |
||||
|
); |
||||
|
customExporters = Map.of( |
||||
|
AUDIT_LOG, this::exportAuditLogs |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public void exportTenant(TenantId tenantId, ExportConfig config, BiConsumer<ObjectType, Object> processor) { |
||||
|
log.info("[{}] Exporting tenant", tenantId); |
||||
|
Tenant tenant = tenantDao.findById(TenantId.SYS_TENANT_ID, tenantId.getId()); |
||||
|
if (tenant == null) { |
||||
|
throw new IllegalArgumentException("Tenant with id " + tenantId + " not found"); |
||||
|
} |
||||
|
|
||||
|
Set<ObjectType> objectTypes = config.getIncludedObjectTypes(); |
||||
|
if (objectTypes.contains(TENANT)) { |
||||
|
exportEntity(tenantId, TENANT, tenant, config, processor); |
||||
|
} |
||||
|
|
||||
|
for (ObjectType type : objectTypes) { |
||||
|
if (RELATED.contains(type) || type == TENANT) { |
||||
|
continue; |
||||
|
} |
||||
|
log.debug("[{}] Exporting {} entities", tenantId, type); |
||||
|
if (!customExporters.containsKey(type)) { |
||||
|
TenantEntityDao<?> dao = entityDaoRegistry.getTenantEntityDao(type); |
||||
|
var entities = new PageDataIterable<>(pageLink -> dao.findAllByTenantId(tenantId, pageLink), 100); |
||||
|
for (Object entity : entities) { |
||||
|
exportEntity(tenantId, type, entity, config, processor); |
||||
|
} |
||||
|
} else { |
||||
|
customExporters.get(type).accept(tenantId, processor); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void exportEntity(TenantId tenantId, ObjectType type, Object entity, ExportConfig config, BiConsumer<ObjectType, Object> processor) { |
||||
|
processor.accept(type, entity); |
||||
|
if (entity instanceof HasId<?> hasId && hasId.getId() instanceof EntityId entityId) { |
||||
|
relatedEntitiesExporters.forEach((relatedEntityType, exporter) -> { |
||||
|
if (config.getIncludedObjectTypes().contains(relatedEntityType)) { |
||||
|
exporter.export(tenantId, entityId, processor); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Map<Long, Long> getPartitions(String table) { |
||||
|
List<Long> partitionsStartTime = partitioningRepository.fetchPartitions(table).stream().sorted().toList(); |
||||
|
if (partitionsStartTime.isEmpty()) { |
||||
|
return Collections.emptyMap(); |
||||
|
} |
||||
|
|
||||
|
Map<Long, Long> partitions = new HashMap<>(); |
||||
|
for (int i = 0; i < partitionsStartTime.size(); i++) { |
||||
|
Long startTime = partitionsStartTime.get(i); |
||||
|
Long endTime; |
||||
|
if (partitionsStartTime.size() - 1 == i) { |
||||
|
endTime = System.currentTimeMillis(); |
||||
|
} else { |
||||
|
endTime = partitionsStartTime.get(i + 1) - 1; |
||||
|
} |
||||
|
partitions.put(startTime, endTime); |
||||
|
} |
||||
|
return partitions; |
||||
|
} |
||||
|
|
||||
|
private void exportAuditLogs(TenantId tenantId, BiConsumer<ObjectType, Object> processor) { |
||||
|
Map<Long, Long> partitions = getPartitions(ModelConstants.AUDIT_LOG_TABLE_NAME); |
||||
|
partitions.forEach((startTime, endTime) -> { |
||||
|
PageDataIterable<AuditLog> auditLogs = new PageDataIterable<>(pageLink -> { |
||||
|
return auditLogDao.findAuditLogsByTenantId(tenantId.getId(), null, new TimePageLink(pageLink, startTime, endTime)); |
||||
|
}, 512); |
||||
|
for (AuditLog auditLog : auditLogs) { |
||||
|
processor.accept(AUDIT_LOG, auditLog); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void exportAttributes(TenantId tenantId, EntityId entityId, BiConsumer<ObjectType, Object> processor) { |
||||
|
for (AttributeScope attributeScope : AttributeScope.values()) { |
||||
|
List<AttributeKvEntry> attributes = attributesDao.findAll(tenantId, entityId, attributeScope); |
||||
|
for (AttributeKvEntry entry : attributes) { |
||||
|
AttributeKv attributeKv = new AttributeKv(entityId, attributeScope, entry, entry.getVersion()); |
||||
|
processor.accept(ATTRIBUTE_KV, attributeKv); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void exportRelations(TenantId tenantId, EntityId entityId, BiConsumer<ObjectType, Object> processor) { |
||||
|
List<EntityRelation> relations = relationDao.findAllByFrom(tenantId, entityId); |
||||
|
for (EntityRelation relation : relations) { |
||||
|
processor.accept(RELATION, relation); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
private void exportLatestTelemetry(TenantId tenantId, EntityId entityId, BiConsumer<ObjectType, Object> processor) { |
||||
|
List<TsKvEntry> latestTelemetry = timeseriesLatestDao.findAllLatest(tenantId, entityId).get(30, TimeUnit.SECONDS); |
||||
|
for (TsKvEntry tsKvEntry : latestTelemetry) { |
||||
|
LatestTsKv latestTsKv = new LatestTsKv(entityId, tsKvEntry, tsKvEntry.getVersion()); |
||||
|
processor.accept(LATEST_TS_KV, latestTsKv); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void exportEvents(TenantId tenantId, EntityId entityId, BiConsumer<ObjectType, Object> processor) { |
||||
|
for (EventType eventType : EventType.values()) { |
||||
|
Map<Long, Long> partitions = getPartitions(eventType.getTable()); |
||||
|
partitions.forEach((startTime, endTime) -> { |
||||
|
PageDataIterable<? extends Event> events = new PageDataIterable<>(pageLink -> { |
||||
|
return eventDao.findEvents(tenantId.getId(), entityId.getId(), eventType, new TimePageLink(pageLink, startTime, endTime)); |
||||
|
}, 512); |
||||
|
for (Event event : events) { |
||||
|
processor.accept(EVENT, event); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private interface Exporter { |
||||
|
|
||||
|
void export(TenantId tenantId, EntityId entityId, BiConsumer<ObjectType, Object> processor); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Data |
||||
|
public static class ExportConfig { |
||||
|
|
||||
|
private Set<ObjectType> includedObjectTypes; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.junit.Before; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.test.mock.mockito.MockBean; |
||||
|
import org.springframework.test.context.TestPropertySource; |
||||
|
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.common.msg.edqs.EdqsService; |
||||
|
import org.thingsboard.server.dao.service.DaoSqlTest; |
||||
|
import org.thingsboard.server.edqs.util.EdqsRocksDb; |
||||
|
|
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
import static org.awaitility.Awaitility.await; |
||||
|
|
||||
|
@DaoSqlTest |
||||
|
@TestPropertySource(properties = { |
||||
|
"queue.type=kafka", // uncomment to use Kafka
|
||||
|
"queue.kafka.bootstrap.servers=10.7.1.254:9092", |
||||
|
"queue.edqs.sync_enabled=true", |
||||
|
"queue.edqs.api_enabled=true", |
||||
|
"queue.edqs.mode=local" |
||||
|
}) |
||||
|
public class EdqsEntityQueryControllerTest extends EntityQueryControllerTest { |
||||
|
|
||||
|
@Autowired |
||||
|
private EdqsService edqsService; |
||||
|
|
||||
|
@MockBean |
||||
|
private EdqsRocksDb edqsRocksDb; |
||||
|
|
||||
|
@Before |
||||
|
public void before() { |
||||
|
await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> edqsService.isApiEnabled()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected PageData<EntityData> findByQueryAndCheck(EntityDataQuery query, int expectedResultSize) { |
||||
|
return await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> findByQuery(query), |
||||
|
result -> result.getTotalElements() == expectedResultSize); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected Long countByQueryAndCheck(EntityCountQuery query, long expectedResult) { |
||||
|
return await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> countByQuery(query), |
||||
|
result -> result == expectedResult); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.entitiy; |
||||
|
|
||||
|
import org.junit.Before; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.test.mock.mockito.MockBean; |
||||
|
import org.springframework.test.context.TestPropertySource; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.permission.MergedUserPermissions; |
||||
|
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.common.msg.edqs.EdqsService; |
||||
|
import org.thingsboard.server.dao.service.DaoSqlTest; |
||||
|
import org.thingsboard.server.edqs.util.EdqsRocksDb; |
||||
|
|
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
import static org.awaitility.Awaitility.await; |
||||
|
|
||||
|
@DaoSqlTest |
||||
|
@TestPropertySource(properties = { |
||||
|
"queue.edqs.sync_enabled=true", |
||||
|
"queue.edqs.api_enabled=true", |
||||
|
"queue.edqs.mode=local" |
||||
|
}) |
||||
|
public class EdqsEntityServiceTest extends EntityServiceTest { |
||||
|
|
||||
|
@Autowired |
||||
|
private EdqsService edqsService; |
||||
|
|
||||
|
@MockBean |
||||
|
private EdqsRocksDb edqsRocksDb; |
||||
|
|
||||
|
@Before |
||||
|
public void beforeEach() { |
||||
|
await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> edqsService.isApiEnabled()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected PageData<EntityData> findByQueryAndCheck(CustomerId customerId, MergedUserPermissions permissions, EntityDataQuery query, long expectedResultSize) { |
||||
|
return await().atMost(15, TimeUnit.SECONDS).until(() -> findByQuery(customerId, permissions, query), |
||||
|
result -> result.getTotalElements() == expectedResultSize); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected long countByQueryAndCheck(EntityCountQuery countQuery, int expectedResult) { |
||||
|
return countByQueryAndCheck(new CustomerId(CustomerId.NULL_UUID), mergedUserPermissionsPE, countQuery, expectedResult); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected long countByQueryAndCheck(CustomerId customerId, MergedUserPermissions permissions, EntityCountQuery query, int expectedResult) { |
||||
|
return await().atMost(15, TimeUnit.SECONDS).until(() -> countByQuery(customerId, permissions, query), |
||||
|
result -> result == expectedResult); |
||||
|
} |
||||
|
|
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,102 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
import java.util.EnumSet; |
||||
|
import java.util.HashSet; |
||||
|
import java.util.Set; |
||||
|
|
||||
|
public enum ObjectType { |
||||
|
TENANT, |
||||
|
TENANT_PROFILE, |
||||
|
CUSTOMER, |
||||
|
ADMIN_SETTINGS, |
||||
|
QUEUE, |
||||
|
RPC, |
||||
|
RULE_CHAIN, |
||||
|
OTA_PACKAGE, |
||||
|
RESOURCE, |
||||
|
ROLE, |
||||
|
ENTITY_GROUP, |
||||
|
DEVICE_GROUP_OTA_PACKAGE, |
||||
|
GROUP_PERMISSION, |
||||
|
BLOB_ENTITY, |
||||
|
SCHEDULER_EVENT, |
||||
|
EVENT, |
||||
|
RULE_NODE, |
||||
|
CONVERTER, |
||||
|
INTEGRATION, |
||||
|
USER, |
||||
|
USER_CREDENTIALS, |
||||
|
USER_AUTH_SETTINGS, |
||||
|
EDGE, |
||||
|
WIDGETS_BUNDLE, |
||||
|
WIDGET_TYPE, |
||||
|
DASHBOARD, |
||||
|
DEVICE_PROFILE, |
||||
|
DEVICE, |
||||
|
DEVICE_CREDENTIALS, |
||||
|
ASSET_PROFILE, |
||||
|
ASSET, |
||||
|
ENTITY_VIEW, |
||||
|
ALARM, |
||||
|
ENTITY_ALARM, |
||||
|
OAUTH2_CLIENT, |
||||
|
OAUTH2_DOMAIN, |
||||
|
OAUTH2_MOBILE, |
||||
|
USER_SETTINGS, |
||||
|
NOTIFICATION_TARGET, |
||||
|
NOTIFICATION_TEMPLATE, |
||||
|
NOTIFICATION_RULE, |
||||
|
WHITE_LABELING, |
||||
|
CUSTOM_TRANSLATION, |
||||
|
ALARM_COMMENT, |
||||
|
ALARM_TYPE, |
||||
|
API_USAGE_STATE, |
||||
|
QUEUE_STATS, |
||||
|
|
||||
|
AUDIT_LOG, |
||||
|
RELATION, |
||||
|
ATTRIBUTE_KV, |
||||
|
LATEST_TS_KV; |
||||
|
|
||||
|
public static final Set<ObjectType> edqsTenantTypes = EnumSet.of( |
||||
|
TENANT_PROFILE, CUSTOMER, DEVICE_PROFILE, DEVICE, ASSET_PROFILE, ASSET, EDGE, ENTITY_VIEW, USER, DASHBOARD, |
||||
|
RULE_CHAIN, WIDGET_TYPE, WIDGETS_BUNDLE, CONVERTER, INTEGRATION, SCHEDULER_EVENT, ROLE, |
||||
|
BLOB_ENTITY, API_USAGE_STATE, QUEUE_STATS |
||||
|
); |
||||
|
public static final Set<ObjectType> edqsTypes = new HashSet<>(edqsTenantTypes); |
||||
|
public static final Set<ObjectType> edqsSystemTypes = EnumSet.of(TENANT, TENANT_PROFILE, USER, DASHBOARD, |
||||
|
API_USAGE_STATE, ATTRIBUTE_KV, LATEST_TS_KV); |
||||
|
|
||||
|
static { |
||||
|
edqsTypes.addAll(Arrays.asList(TENANT, ENTITY_GROUP, RELATION, ATTRIBUTE_KV, LATEST_TS_KV)); |
||||
|
} |
||||
|
|
||||
|
public EntityType toEntityType() { |
||||
|
return EntityType.valueOf(name()); |
||||
|
} |
||||
|
|
||||
|
public static ObjectType fromEntityType(EntityType entityType) { |
||||
|
try { |
||||
|
return ObjectType.valueOf(entityType.name()); |
||||
|
} catch (Exception e) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.alarm; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
|
||||
|
@Data |
||||
|
public class AlarmType { |
||||
|
|
||||
|
private TenantId tenantId; |
||||
|
private String type; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.KvEntry; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Builder |
||||
|
public class AttributeKv implements EdqsObject { |
||||
|
|
||||
|
private EntityId entityId; |
||||
|
private AttributeScope scope; |
||||
|
private String key; |
||||
|
private Long version; |
||||
|
|
||||
|
private Long lastUpdateTs; // optional (on deletion)
|
||||
|
private KvEntry value; // optional (on deletion)
|
||||
|
|
||||
|
public AttributeKv(EntityId entityId, AttributeScope scope, AttributeKvEntry attributeKvEntry, long version) { |
||||
|
this.entityId = entityId; |
||||
|
this.scope = scope; |
||||
|
this.key = attributeKvEntry.getKey(); |
||||
|
this.version = version; |
||||
|
this.lastUpdateTs = attributeKvEntry.getLastUpdateTs(); |
||||
|
this.value = attributeKvEntry; |
||||
|
} |
||||
|
|
||||
|
public AttributeKv(EntityId entityId, AttributeScope scope, String key, long version) { |
||||
|
this.entityId = entityId; |
||||
|
this.scope = scope; |
||||
|
this.key = key; |
||||
|
this.version = version; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String key() { |
||||
|
return "a_" + entityId + "_" + scope + "_" + key; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Long version() { |
||||
|
return version; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import org.thingsboard.server.common.data.ObjectType; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@Builder |
||||
|
public class EdqsEvent { |
||||
|
|
||||
|
private final TenantId tenantId; |
||||
|
private final ObjectType objectType; |
||||
|
private final EdqsEventType eventType; |
||||
|
private final EdqsObject object; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
public enum EdqsEventType { |
||||
|
UPDATED, |
||||
|
DELETED |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
|
|
||||
|
public interface EdqsObject { |
||||
|
|
||||
|
@JsonIgnore |
||||
|
String key(); |
||||
|
|
||||
|
@JsonIgnore |
||||
|
Long version(); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
@JsonIgnoreProperties |
||||
|
public class EdqsSyncRequest { |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityIdFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
public class Entity implements EdqsObject { |
||||
|
|
||||
|
private EntityType type; |
||||
|
|
||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) |
||||
|
private EntityFields fields; |
||||
|
|
||||
|
public Entity(EntityType type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
public Entity(EntityType type, EntityFields fields) { |
||||
|
this.type = type; |
||||
|
this.fields = fields; |
||||
|
} |
||||
|
|
||||
|
public Entity(EntityType entityType, UUID id, long version) { |
||||
|
this.type = entityType; |
||||
|
this.fields = new EntityIdFields(id, version); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String key() { |
||||
|
return "e_" + fields.getId().toString(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Long version() { |
||||
|
return fields.getVersion(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.kv.KvEntry; |
||||
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Builder |
||||
|
public class LatestTsKv implements EdqsObject { |
||||
|
|
||||
|
private EntityId entityId; |
||||
|
private String key; |
||||
|
private Long version; |
||||
|
|
||||
|
private Long ts; // optional (on deletion)
|
||||
|
private KvEntry value; // optional (on deletion)
|
||||
|
|
||||
|
public LatestTsKv(EntityId entityId, TsKvEntry tsKvEntry, Long version) { |
||||
|
this.entityId = entityId; |
||||
|
this.key = tsKvEntry.getKey(); |
||||
|
this.ts = tsKvEntry.getTs(); |
||||
|
this.version = version != null ? version : 0L; |
||||
|
this.value = tsKvEntry; |
||||
|
} |
||||
|
|
||||
|
public LatestTsKv(EntityId entityId, String key, Long version) { |
||||
|
this.entityId = entityId; |
||||
|
this.key = key; |
||||
|
this.version = version != null ? version : 0L; |
||||
|
} |
||||
|
|
||||
|
public String key() { |
||||
|
return "l_" + entityId + "_" + key; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Long version() { |
||||
|
return version; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Builder |
||||
|
public class ToCoreEdqsMsg { |
||||
|
|
||||
|
private EdqsSyncRequest syncRequest; |
||||
|
private Boolean apiEnabled; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
@Builder |
||||
|
public class ToCoreEdqsRequest { |
||||
|
|
||||
|
private EdqsSyncRequest syncRequest; |
||||
|
private Boolean apiEnabled; |
||||
|
|
||||
|
@JsonIgnore |
||||
|
public ToCoreEdqsMsg toInternalMsg() { |
||||
|
return new ToCoreEdqsMsg(syncRequest, apiEnabled); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@SuperBuilder |
||||
|
public class AbstractEntityFields implements EntityFields { |
||||
|
|
||||
|
private UUID id; |
||||
|
private long createdTime; |
||||
|
private UUID tenantId; |
||||
|
private UUID customerId; |
||||
|
private String name; |
||||
|
private Long version; |
||||
|
|
||||
|
public AbstractEntityFields(UUID id, long createdTime, UUID tenantId, UUID customerId, String name, Long version) { |
||||
|
this.id = id; |
||||
|
this.createdTime = createdTime; |
||||
|
this.tenantId = tenantId; |
||||
|
this.customerId = (customerId != null && customerId != CustomerId.NULL_UUID) ? customerId : null; |
||||
|
this.name = name; |
||||
|
this.version = version; |
||||
|
} |
||||
|
|
||||
|
public AbstractEntityFields() { |
||||
|
} |
||||
|
|
||||
|
public AbstractEntityFields(UUID id, long createdTime, UUID tenantId, String name, Long version) { |
||||
|
this(id, createdTime, tenantId, null, name, version); |
||||
|
} |
||||
|
|
||||
|
public AbstractEntityFields(UUID id, long createdTime, UUID tenantId, UUID customerId, Long version) { |
||||
|
this(id, createdTime, tenantId, customerId, null, version); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public AbstractEntityFields(UUID id, long createdTime, String name, Long version) { |
||||
|
this(id, createdTime, null, name, version); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public AbstractEntityFields(UUID id, long createdTime, UUID tenantId) { |
||||
|
this(id, createdTime, tenantId, null, null, null); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
import org.thingsboard.server.common.data.ApiUsageStateValue; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.EntityIdFactory; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class ApiUsageStateFields extends AbstractEntityFields { |
||||
|
|
||||
|
private EntityId entityId; |
||||
|
private ApiUsageStateValue transportState; |
||||
|
private ApiUsageStateValue dbStorageState; |
||||
|
private ApiUsageStateValue reExecState; |
||||
|
private ApiUsageStateValue jsExecState; |
||||
|
private ApiUsageStateValue tbelExecState; |
||||
|
private ApiUsageStateValue emailExecState; |
||||
|
private ApiUsageStateValue smsExecState; |
||||
|
private ApiUsageStateValue alarmExecState; |
||||
|
|
||||
|
public ApiUsageStateFields(UUID id, long createdTime, UUID tenantId, UUID entityId, String entityType, ApiUsageStateValue transportState, ApiUsageStateValue dbStorageState, |
||||
|
ApiUsageStateValue reExecState, ApiUsageStateValue jsExecState, ApiUsageStateValue tbelExecState, |
||||
|
ApiUsageStateValue emailExecState, ApiUsageStateValue smsExecState, ApiUsageStateValue alarmExecState) { |
||||
|
super(id, createdTime, tenantId); |
||||
|
this.entityId = (entityType != null && entityId != null) ? EntityIdFactory.getByTypeAndUuid(entityType, entityId) : null; |
||||
|
this.transportState = transportState; |
||||
|
this.dbStorageState = dbStorageState; |
||||
|
this.reExecState = reExecState; |
||||
|
this.jsExecState = jsExecState; |
||||
|
this.tbelExecState = tbelExecState; |
||||
|
this.emailExecState = emailExecState; |
||||
|
this.smsExecState = smsExecState; |
||||
|
this.alarmExecState = alarmExecState; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class AssetFields extends AbstractEntityFields implements ProfileAwareFields { |
||||
|
|
||||
|
private String type; |
||||
|
private UUID assetProfileId; |
||||
|
private String label; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
@JsonIgnore |
||||
|
@Override |
||||
|
public String getProfileName() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
@JsonIgnore |
||||
|
@Override |
||||
|
public UUID getProfileId() { |
||||
|
return assetProfileId; |
||||
|
} |
||||
|
|
||||
|
public AssetFields(UUID id, long createdTime, UUID tenantId, UUID customerId, String name, |
||||
|
Long version, String type, String label, UUID assetProfileId, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, customerId, name, version); |
||||
|
this.type = type; |
||||
|
this.assetProfileId = assetProfileId; |
||||
|
this.label = label; |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class AssetProfileFields extends AbstractEntityFields { |
||||
|
|
||||
|
private boolean isDefault; |
||||
|
|
||||
|
public AssetProfileFields(UUID id, long createdTime, UUID tenantId, String name, Long version, boolean isDefault) { |
||||
|
super(id, createdTime, tenantId, null, name, version); |
||||
|
this.isDefault = isDefault; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class CustomerFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String additionalInfo; |
||||
|
private String country; |
||||
|
private String state; |
||||
|
private String city; |
||||
|
private String address; |
||||
|
private String address2; |
||||
|
private String zip; |
||||
|
private String phone; |
||||
|
private String email; |
||||
|
|
||||
|
public CustomerFields(UUID id, long createdTime, UUID tenantId, String name, Long version, JsonNode additionalInfo, |
||||
|
String country, String state, String city, String address, String address2, String zip, String phone, String email) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
this.country = country; |
||||
|
this.state = state; |
||||
|
this.city = city; |
||||
|
this.address = address; |
||||
|
this.address2 = address2; |
||||
|
this.zip = zip; |
||||
|
this.phone = phone; |
||||
|
this.email = email; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class DashboardFields extends AbstractEntityFields { |
||||
|
|
||||
|
public DashboardFields(UUID id, long createdTime, UUID tenantId, UUID customerId, String name, Long version) { |
||||
|
super(id, createdTime, tenantId, customerId, name, version); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class DeviceFields extends AbstractEntityFields implements ProfileAwareFields { |
||||
|
|
||||
|
private String label; |
||||
|
private String type; |
||||
|
private UUID deviceProfileId; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
@JsonIgnore |
||||
|
@Override |
||||
|
public String getProfileName() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
@JsonIgnore |
||||
|
@Override |
||||
|
public UUID getProfileId() { |
||||
|
return deviceProfileId; |
||||
|
} |
||||
|
|
||||
|
public DeviceFields(UUID id, long createdTime, UUID tenantId, UUID customerId, String name, Long version, String type, |
||||
|
String label, UUID deviceProfileId, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, customerId, name, version); |
||||
|
this.label = label; |
||||
|
this.type = type; |
||||
|
this.deviceProfileId = deviceProfileId; |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
import org.thingsboard.server.common.data.DeviceProfileType; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class DeviceProfileFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String type; |
||||
|
private boolean isDefault; |
||||
|
|
||||
|
public DeviceProfileFields(UUID id, long createdTime, UUID tenantId, String name, Long version, DeviceProfileType type, boolean isDefault) { |
||||
|
super(id, createdTime, tenantId, null, name, version); |
||||
|
this.type = type.name(); |
||||
|
this.isDefault = isDefault; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class EdgeFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String type; |
||||
|
private String label; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
public EdgeFields(UUID id, long createdTime, UUID tenantId, UUID customerId, String name, Long version, |
||||
|
String type, String label, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, customerId, name, version); |
||||
|
this.type = type; |
||||
|
this.label = label; |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,171 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public interface EntityFields { |
||||
|
|
||||
|
Logger log = LoggerFactory.getLogger(EntityFields.class); |
||||
|
|
||||
|
default UUID getId() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default UUID getTenantId() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default UUID getCustomerId() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default long getCreatedTime() { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
default String getName() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getType() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getLabel() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getAdditionalInfo() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getEmail() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getCountry() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getState() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getCity() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getAddress() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getAddress2() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getZip() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getPhone() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getRegion() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getFirstName() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getLastName() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default boolean isEdgeTemplate() { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
default String getConfiguration() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getSchedule() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default EntityId getOriginatorId() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default String getQueueName() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default String getServiceId() { |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
default boolean isDefault() { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
default UUID getOwnerId() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default Long getVersion() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
default String getAsString(String key) { |
||||
|
return switch (key) { |
||||
|
case "createdTime" -> Long.toString(getCreatedTime()); |
||||
|
case "type" -> getType(); |
||||
|
case "label" -> getLabel(); |
||||
|
case "additionalInfo" -> getAdditionalInfo(); |
||||
|
case "email" -> getEmail(); |
||||
|
case "country" -> getCountry(); |
||||
|
case "state" -> getState(); |
||||
|
case "city" -> getCity(); |
||||
|
case "address" -> getAddress(); |
||||
|
case "address2" -> getAddress2(); |
||||
|
case "zip" -> getZip(); |
||||
|
case "phone" -> getPhone(); |
||||
|
case "region" -> getRegion(); |
||||
|
case "firstName" -> getFirstName(); |
||||
|
case "lastName" -> getLastName(); |
||||
|
case "edgeTemplate" -> Boolean.toString(isEdgeTemplate()); |
||||
|
case "configuration" -> getConfiguration(); |
||||
|
case "schedule" -> getSchedule(); |
||||
|
case "originatorId" -> getOriginatorId().getId().toString(); |
||||
|
case "originatorType" -> getOriginatorId().getEntityType().toString(); |
||||
|
case "queueName" -> getQueueName(); |
||||
|
case "serviceId" -> getServiceId(); |
||||
|
default -> { |
||||
|
log.warn("Unknown field '{}'", key); |
||||
|
yield null; |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class EntityIdFields implements EntityFields { |
||||
|
|
||||
|
private UUID id; |
||||
|
private Long version; |
||||
|
|
||||
|
public EntityIdFields(UUID id, Long version) { |
||||
|
this.id = id; |
||||
|
this.version = version; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class EntityViewFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String type; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,298 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import org.thingsboard.server.common.data.ApiUsageState; |
||||
|
import org.thingsboard.server.common.data.Customer; |
||||
|
import org.thingsboard.server.common.data.Dashboard; |
||||
|
import org.thingsboard.server.common.data.Device; |
||||
|
import org.thingsboard.server.common.data.DeviceProfile; |
||||
|
import org.thingsboard.server.common.data.DeviceProfileType; |
||||
|
import org.thingsboard.server.common.data.EntityView; |
||||
|
import org.thingsboard.server.common.data.Tenant; |
||||
|
import org.thingsboard.server.common.data.TenantProfile; |
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.asset.Asset; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
import org.thingsboard.server.common.data.queue.QueueStats; |
||||
|
import org.thingsboard.server.common.data.rule.RuleChain; |
||||
|
import org.thingsboard.server.common.data.rule.RuleNode; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetType; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public class FieldsUtil { |
||||
|
|
||||
|
public static EntityFields toFields(Object entity) { |
||||
|
if (entity instanceof Customer customer) { |
||||
|
return toFields(customer); |
||||
|
} else if (entity instanceof Tenant tenant) { |
||||
|
return toFields(tenant); |
||||
|
} else if (entity instanceof TenantProfile tenantProfile) { |
||||
|
return toFields(tenantProfile); |
||||
|
} else if (entity instanceof Device device) { |
||||
|
return toFields(device); |
||||
|
} else if (entity instanceof Asset asset) { |
||||
|
return toFields(asset); |
||||
|
} else if (entity instanceof Edge edge) { |
||||
|
return toFields(edge); |
||||
|
} else if (entity instanceof EntityView entityView) { |
||||
|
return toFields(entityView); |
||||
|
} else if (entity instanceof User user) { |
||||
|
return toFields(user); |
||||
|
} else if (entity instanceof Dashboard dashboard) { |
||||
|
return toFields(dashboard); |
||||
|
} else if (entity instanceof RuleChain ruleChain) { |
||||
|
return toFields(ruleChain); |
||||
|
} else if (entity instanceof RuleNode ruleNode) { |
||||
|
return toFields(ruleNode); |
||||
|
} else if (entity instanceof WidgetType widgetType) { |
||||
|
return toFields(widgetType); |
||||
|
} else if (entity instanceof WidgetsBundle widgetsBundle) { |
||||
|
return toFields(widgetsBundle); |
||||
|
} else if (entity instanceof DeviceProfile deviceProfile) { |
||||
|
return toFields(deviceProfile); |
||||
|
} else if (entity instanceof AssetProfile assetProfile) { |
||||
|
return toFields(assetProfile); |
||||
|
} else if (entity instanceof QueueStats queueStats) { |
||||
|
return toFields(queueStats); |
||||
|
} else if (entity instanceof ApiUsageState apiUsageState) { |
||||
|
return toFields(apiUsageState); |
||||
|
} else { |
||||
|
throw new IllegalArgumentException("Unsupported entity type: " + entity.getClass().getName()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static CustomerFields toFields(Customer entity) { |
||||
|
return CustomerFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getTitle()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.email(entity.getEmail()) |
||||
|
.country(entity.getCountry()) |
||||
|
.state(entity.getState()) |
||||
|
.city(entity.getCity()) |
||||
|
.address(entity.getAddress()) |
||||
|
.address2(entity.getAddress2()) |
||||
|
.zip(entity.getZip()) |
||||
|
.phone(entity.getPhone()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static TenantFields toFields(Tenant entity) { |
||||
|
return TenantFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getTitle()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.email(entity.getEmail()) |
||||
|
.country(entity.getCountry()) |
||||
|
.state(entity.getState()) |
||||
|
.city(entity.getCity()) |
||||
|
.address(entity.getAddress()) |
||||
|
.address2(entity.getAddress2()) |
||||
|
.zip(entity.getZip()) |
||||
|
.phone(entity.getPhone()) |
||||
|
.region(entity.getRegion()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static TenantProfileFields toFields(TenantProfile tenantProfile) { |
||||
|
return TenantProfileFields.builder() |
||||
|
.id(tenantProfile.getUuidId()) |
||||
|
.createdTime(tenantProfile.getCreatedTime()) |
||||
|
.name(tenantProfile.getName()) |
||||
|
.isDefault(tenantProfile.isDefault()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static DeviceFields toFields(Device entity) { |
||||
|
return DeviceFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getName()) |
||||
|
.type(entity.getType()) |
||||
|
.deviceProfileId(entity.getDeviceProfileId().getId()) |
||||
|
.label(entity.getLabel()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static AssetFields toFields(Asset entity) { |
||||
|
return AssetFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getName()) |
||||
|
.type(entity.getType()) |
||||
|
.assetProfileId(entity.getAssetProfileId().getId()) |
||||
|
.label(entity.getLabel()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static EdgeFields toFields(Edge entity) { |
||||
|
return EdgeFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getName()) |
||||
|
.type(entity.getType()) |
||||
|
.label(entity.getLabel()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static EntityViewFields toFields(EntityView entity) { |
||||
|
return EntityViewFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getName()) |
||||
|
.type(entity.getType()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static UserFields toFields(User entity) { |
||||
|
return UserFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.firstName(entity.getFirstName()) |
||||
|
.lastName(entity.getLastName()) |
||||
|
.email(entity.getEmail()) |
||||
|
.phone(entity.getPhone()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static DashboardFields toFields(Dashboard entity) { |
||||
|
return DashboardFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.customerId(getCustomerId(entity.getCustomerId())) |
||||
|
.name(entity.getTitle()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static RuleChainFields toFields(RuleChain entity) { |
||||
|
return RuleChainFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static RuleNodeFields toFields(RuleNode entity) { |
||||
|
return RuleNodeFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.additionalInfo(getText(entity.getAdditionalInfo())) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static WidgetTypeFields toFields(WidgetType entity) { |
||||
|
return WidgetTypeFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static WidgetsBundleFields toFields(WidgetsBundle entity) { |
||||
|
return WidgetsBundleFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static AssetProfileFields toFields(DeviceProfile entity) { |
||||
|
return AssetProfileFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.isDefault(entity.isDefault()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static DeviceProfileFields toFields(AssetProfile entity) { |
||||
|
return DeviceProfileFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.name(entity.getName()) |
||||
|
.type(DeviceProfileType.DEFAULT.name()) |
||||
|
.isDefault(entity.isDefault()) |
||||
|
.version(entity.getVersion()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static QueueStatsFields toFields(QueueStats entity) { |
||||
|
return QueueStatsFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.queueName(entity.getQueueName()) |
||||
|
.serviceId(entity.getServiceId()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private static ApiUsageStateFields toFields(ApiUsageState entity) { |
||||
|
return ApiUsageStateFields.builder() |
||||
|
.id(entity.getUuidId()) |
||||
|
.createdTime(entity.getCreatedTime()) |
||||
|
.entityId(entity.getEntityId()) |
||||
|
.transportState(entity.getTransportState()) |
||||
|
.dbStorageState(entity.getDbStorageState()) |
||||
|
.reExecState(entity.getReExecState()) |
||||
|
.jsExecState(entity.getJsExecState()) |
||||
|
.tbelExecState(entity.getTbelExecState()) |
||||
|
.emailExecState(entity.getEmailExecState()) |
||||
|
.smsExecState(entity.getSmsExecState()) |
||||
|
.alarmExecState(entity.getAlarmExecState()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
public static String getText(JsonNode node) { |
||||
|
return node != null ? node.asText() : ""; |
||||
|
} |
||||
|
|
||||
|
private static UUID getCustomerId(CustomerId customerId) { |
||||
|
return (customerId != null && !customerId.getId().equals(CustomerId.NULL_UUID)) ? customerId.getId() : null; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class GenericFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String additionalInfo; |
||||
|
|
||||
|
public GenericFields(UUID id, long createdTime, UUID tenantId, String name, Long version, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
|
||||
|
public GenericFields(UUID id, long createdTime, UUID tenantId, String name, Long version) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public interface ProfileAwareFields extends EntityFields { |
||||
|
|
||||
|
String getProfileName(); |
||||
|
|
||||
|
UUID getProfileId(); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class QueueStatsFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String queueName; |
||||
|
private String serviceId; |
||||
|
|
||||
|
@Override |
||||
|
public String getName() { |
||||
|
return queueName + '_' + serviceId; |
||||
|
} |
||||
|
|
||||
|
public QueueStatsFields(UUID id, long createdTime, UUID tenantId, String queueName, String serviceId) { |
||||
|
super(id, createdTime, tenantId); |
||||
|
this.queueName = queueName; |
||||
|
this.serviceId = serviceId; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class RuleChainFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String additionalInfo; |
||||
|
|
||||
|
public RuleChainFields(UUID id, long createdTime, UUID tenantId, String name, Long version, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class RuleNodeFields implements EntityFields { |
||||
|
|
||||
|
private UUID id; |
||||
|
private long createdTime; |
||||
|
private String name; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
public RuleNodeFields(UUID id, long createdTime, String name, JsonNode additionalInfo) { |
||||
|
this.id = id; |
||||
|
this.createdTime = createdTime; |
||||
|
this.name = name; |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class TenantFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String additionalInfo; |
||||
|
private String country; |
||||
|
private String state; |
||||
|
private String city; |
||||
|
private String address; |
||||
|
private String address2; |
||||
|
private String zip; |
||||
|
private String phone; |
||||
|
private String email; |
||||
|
private String region; |
||||
|
|
||||
|
public TenantFields(UUID id, long createdTime, String name, Long version, |
||||
|
JsonNode additionalInfo, String country, String state, String city, String address, |
||||
|
String address2, String zip, String phone, String email, String region) { |
||||
|
super(id, createdTime, name, version); |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
this.country = country; |
||||
|
this.state = state; |
||||
|
this.city = city; |
||||
|
this.address = address; |
||||
|
this.address2 = address2; |
||||
|
this.zip = zip; |
||||
|
this.phone = phone; |
||||
|
this.email = email; |
||||
|
this.region = region; |
||||
|
} |
||||
|
|
||||
|
public TenantFields(UUID id, Long version) { |
||||
|
super(id, 0L, null, version); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class TenantProfileFields extends AbstractEntityFields { |
||||
|
|
||||
|
private boolean isDefault; |
||||
|
|
||||
|
public TenantProfileFields(UUID id, long createdTime, String name, boolean isDefault) { |
||||
|
super(id, createdTime, TenantId.SYS_TENANT_ID.getId(), null, name, 0L); |
||||
|
this.isDefault = isDefault; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class UserFields extends AbstractEntityFields { |
||||
|
|
||||
|
private String firstName; |
||||
|
private String lastName; |
||||
|
private String email; |
||||
|
private String phone; |
||||
|
private String additionalInfo; |
||||
|
|
||||
|
public UserFields(UUID id, long createdTime, UUID tenantId, UUID customerId, |
||||
|
Long version, String firstName, String lastName, String email, |
||||
|
String phone, JsonNode additionalInfo) { |
||||
|
super(id, createdTime, tenantId, customerId, version); |
||||
|
this.firstName = firstName; |
||||
|
this.lastName = lastName; |
||||
|
this.email = email; |
||||
|
this.phone = phone; |
||||
|
this.additionalInfo = getText(additionalInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class WidgetTypeFields extends AbstractEntityFields { |
||||
|
|
||||
|
public WidgetTypeFields(UUID id, long createdTime, UUID tenantId, String name, Long version) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.fields; |
||||
|
|
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.experimental.SuperBuilder; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@NoArgsConstructor |
||||
|
@SuperBuilder |
||||
|
public class WidgetsBundleFields extends AbstractEntityFields { |
||||
|
|
||||
|
public WidgetsBundleFields(UUID id, long createdTime, UUID tenantId, String name, Long version) { |
||||
|
super(id, createdTime, tenantId, name, version); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.query; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIncludeProperties; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.permission.MergedUserPermissions; |
||||
|
import org.thingsboard.server.common.data.query.EntityCountQuery; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataQuery; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Builder |
||||
|
public class EdqsRequest { |
||||
|
|
||||
|
private EntityDataQuery entityDataQuery; |
||||
|
private EntityCountQuery entityCountQuery; |
||||
|
@JsonIncludeProperties({"genericPermissions", "groupPermissions"}) |
||||
|
private MergedUserPermissions userPermissions; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.query; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.query.EntityData; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||
|
public class EdqsResponse { |
||||
|
|
||||
|
private PageData<EntityData> entityDataQueryResult; |
||||
|
private Long entityCountQueryResult; |
||||
|
private String error; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 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.edqs.query; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.query.EntityData; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.common.data.query.TsValue; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Data |
||||
|
@RequiredArgsConstructor |
||||
|
public class QueryResult { |
||||
|
|
||||
|
private final EntityId entityId; |
||||
|
private final boolean readAttrs; |
||||
|
private final boolean readTs; |
||||
|
private final Map<EntityKeyType, Map<String, TsValue>> latest; |
||||
|
|
||||
|
public EntityData toOldEntityData() { |
||||
|
return new EntityData(entityId, readAttrs, readTs, latest, Collections.emptyMap(), Collections.emptyMap()); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,97 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<parent> |
||||
|
<groupId>org.thingsboard</groupId> |
||||
|
<version>4.0.0PE-SNAPSHOT</version> |
||||
|
<artifactId>common</artifactId> |
||||
|
</parent> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>edqs</artifactId> |
||||
|
<packaging>jar</packaging> |
||||
|
|
||||
|
<name>Thingsboard Server EDQS API</name> |
||||
|
<url>https://thingsboard.io</url> |
||||
|
|
||||
|
<properties> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
<main.dir>${basedir}/../..</main.dir> |
||||
|
</properties> |
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.rocksdb</groupId> |
||||
|
<artifactId>rocksdbjni</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>proto</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>data</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>util</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>message</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>stats</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>cluster-api</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.thingsboard.common</groupId> |
||||
|
<artifactId>queue</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.kafka</groupId> |
||||
|
<artifactId>kafka-clients</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.github.ben-manes.caffeine</groupId> |
||||
|
<artifactId>caffeine</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework</groupId> |
||||
|
<artifactId>spring-context-support</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-autoconfigure</artifactId> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
<distributionManagement> |
||||
|
<repository> |
||||
|
<id>thingsboard-repo-deploy</id> |
||||
|
<name>ThingsBoard Repo Deployment</name> |
||||
|
<url>https://repo.thingsboard.io/artifactory/libs-release-public</url> |
||||
|
</repository> |
||||
|
</distributionManagement> |
||||
|
|
||||
|
</project> |
||||
@ -0,0 +1,46 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.ApiUsageStateFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@ToString(callSuper = true) |
||||
|
public class ApiUsageStateData extends BaseEntityData<ApiUsageStateFields> { |
||||
|
|
||||
|
public ApiUsageStateData(UUID entityId) { |
||||
|
super(entityId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.API_USAGE_STATE; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getEntityName() { |
||||
|
return getEntityOwnerName(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getEntityOwnerName() { |
||||
|
return repo.getOwnerName(fields.getEntityId()); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.AssetFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@ToString(callSuper = true) |
||||
|
public class AssetData extends ProfileAwareData<AssetFields> { |
||||
|
|
||||
|
public AssetData(UUID id) { |
||||
|
super(id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.ASSET; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,180 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
import org.thingsboard.server.common.data.permission.QueryContext; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.edqs.data.dp.BoolDataPoint; |
||||
|
import org.thingsboard.server.edqs.data.dp.DataPoint; |
||||
|
import org.thingsboard.server.edqs.data.dp.LongDataPoint; |
||||
|
import org.thingsboard.server.edqs.data.dp.StringDataPoint; |
||||
|
import org.thingsboard.server.edqs.query.DataKey; |
||||
|
import org.thingsboard.server.edqs.repo.TenantRepo; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
import java.util.Objects; |
||||
|
import java.util.Optional; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
@ToString |
||||
|
public abstract class BaseEntityData<T extends EntityFields> implements EntityData<T> { |
||||
|
|
||||
|
@Getter |
||||
|
private final UUID id; |
||||
|
@Getter |
||||
|
protected final Map<Integer, DataPoint> serverAttrMap; |
||||
|
@Getter |
||||
|
private final Map<Integer, DataPoint> tMap; |
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
private volatile UUID customerId; |
||||
|
|
||||
|
@Setter |
||||
|
protected TenantRepo repo; |
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
protected volatile T fields; |
||||
|
|
||||
|
public BaseEntityData(UUID id) { |
||||
|
this.id = id; |
||||
|
this.serverAttrMap = new ConcurrentHashMap<>(); |
||||
|
this.tMap = new ConcurrentHashMap<>(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataPoint getAttr(Integer keyId, EntityKeyType entityKeyType) { |
||||
|
return switch (entityKeyType) { |
||||
|
case ATTRIBUTE, SERVER_ATTRIBUTE -> serverAttrMap.get(keyId); |
||||
|
default -> null; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean putAttr(Integer keyId, AttributeScope scope, DataPoint value) { |
||||
|
return serverAttrMap.put(keyId, value) == null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean removeAttr(Integer keyId, AttributeScope scope) { |
||||
|
return serverAttrMap.remove(keyId) != null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataPoint getTs(Integer keyId) { |
||||
|
return tMap.get(keyId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean putTs(Integer keyId, DataPoint value) { |
||||
|
return tMap.put(keyId, value) == null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean removeTs(Integer keyId) { |
||||
|
return tMap.remove(keyId) != null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getOwnerType() { |
||||
|
return customerId != null ? EntityType.CUSTOMER : EntityType.TENANT; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataPoint getDataPoint(DataKey key, QueryContext ctx) { |
||||
|
return switch (key.type()) { |
||||
|
case TIME_SERIES -> getTs(key.keyId()); |
||||
|
case ATTRIBUTE, SERVER_ATTRIBUTE, CLIENT_ATTRIBUTE, SHARED_ATTRIBUTE -> getAttr(key.keyId(), key.type()); |
||||
|
case ENTITY_FIELD -> getField(key, ctx); |
||||
|
default -> throw new RuntimeException(key.type() + " not supported"); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private DataPoint getField(DataKey newKey, QueryContext ctx) { |
||||
|
if (fields == null) { |
||||
|
return null; |
||||
|
} |
||||
|
String key = newKey.key(); |
||||
|
return switch (key) { |
||||
|
case "createdTime" -> new LongDataPoint(System.currentTimeMillis(), fields.getCreatedTime()); |
||||
|
case "edgeTemplate" -> new BoolDataPoint(System.currentTimeMillis(), fields.isEdgeTemplate()); |
||||
|
case "parentId" -> new StringDataPoint(System.currentTimeMillis(), getRelatedParentId(ctx)); |
||||
|
default -> new StringDataPoint(System.currentTimeMillis(), getField(key), false); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getField(String name) { |
||||
|
if (fields == null) { |
||||
|
return null; |
||||
|
} |
||||
|
return switch (name) { |
||||
|
case "name" -> getEntityName(); |
||||
|
case "ownerName" -> getEntityOwnerName(); |
||||
|
case "ownerType" -> customerId != null ? EntityType.CUSTOMER.name() : EntityType.TENANT.name(); |
||||
|
case "entityType" -> Optional.ofNullable(getEntityType()).map(EntityType::name).orElse(""); |
||||
|
default -> fields.getAsString(name); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public String getEntityOwnerName() { |
||||
|
return repo.getOwnerName(getCustomerId() == null || CustomerId.NULL_UUID.equals(getCustomerId()) ? null : |
||||
|
new CustomerId(getCustomerId())); |
||||
|
} |
||||
|
|
||||
|
public String getEntityName() { |
||||
|
return getFields().getName(); |
||||
|
} |
||||
|
|
||||
|
private String getRelatedParentId(QueryContext ctx) { |
||||
|
return Optional.ofNullable(ctx.getRelatedParentIdMap().get(getId())) |
||||
|
.map(UUID::toString) |
||||
|
.orElse(""); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isEmpty() { |
||||
|
return fields == null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean equals(Object o) { |
||||
|
if (this == o) return true; |
||||
|
if (o == null || getClass() != o.getClass()) return false; |
||||
|
BaseEntityData<?> that = (BaseEntityData<?>) o; |
||||
|
return Objects.equals(id, that.id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int hashCode() { |
||||
|
return Objects.hash(id); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.CustomerFields; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.Collections; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
import java.util.concurrent.ConcurrentMap; |
||||
|
|
||||
|
public class CustomerData extends BaseEntityData<CustomerFields> { |
||||
|
|
||||
|
private final ConcurrentMap<EntityType, ConcurrentMap<UUID, EntityData<?>>> entitiesById = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
public CustomerData(UUID entityId) { |
||||
|
super(entityId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.CUSTOMER; |
||||
|
} |
||||
|
|
||||
|
public Collection<EntityData<?>> getEntities(EntityType entityType) { |
||||
|
var map = entitiesById.get(entityType); |
||||
|
if (map == null) { |
||||
|
return Collections.emptyList(); |
||||
|
} else { |
||||
|
return map.values(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void addOrUpdate(EntityData<?> ed) { |
||||
|
entitiesById.computeIfAbsent(ed.getEntityType(), et -> new ConcurrentHashMap<>()).put(ed.getId(), ed); |
||||
|
} |
||||
|
|
||||
|
public boolean remove(EntityData<?> ed) { |
||||
|
var map = entitiesById.get(ed.getEntityType()); |
||||
|
if (map != null) { |
||||
|
return map.remove(ed.getId()) != null; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.DeviceFields; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.edqs.data.dp.DataPoint; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
@ToString(callSuper = true) |
||||
|
public class DeviceData extends ProfileAwareData<DeviceFields> { |
||||
|
|
||||
|
private final Map<Integer, DataPoint> clientAttrMap; |
||||
|
private final Map<Integer, DataPoint> sharedAttrMap; |
||||
|
|
||||
|
public DeviceData(UUID entityId) { |
||||
|
super(entityId); |
||||
|
this.clientAttrMap = new ConcurrentHashMap<>(); |
||||
|
this.sharedAttrMap = new ConcurrentHashMap<>(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.DEVICE; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataPoint getAttr(Integer keyId, EntityKeyType entityKeyType) { |
||||
|
return switch (entityKeyType) { |
||||
|
case ATTRIBUTE -> getAttributeDataPoint(keyId); |
||||
|
case SERVER_ATTRIBUTE -> serverAttrMap.get(keyId); |
||||
|
case CLIENT_ATTRIBUTE -> clientAttrMap.get(keyId); |
||||
|
case SHARED_ATTRIBUTE -> sharedAttrMap.get(keyId); |
||||
|
default -> throw new RuntimeException(entityKeyType + " not implemented"); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean putAttr(Integer keyId, AttributeScope scope, DataPoint value) { |
||||
|
return switch (scope) { |
||||
|
case SERVER_SCOPE -> serverAttrMap.put(keyId, value) == null; |
||||
|
case CLIENT_SCOPE -> clientAttrMap.put(keyId, value) == null; |
||||
|
case SHARED_SCOPE -> sharedAttrMap.put(keyId, value) == null; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean removeAttr(Integer keyId, AttributeScope scope) { |
||||
|
return switch (scope) { |
||||
|
case SERVER_SCOPE -> serverAttrMap.remove(keyId) != null; |
||||
|
case CLIENT_SCOPE -> clientAttrMap.remove(keyId) != null; |
||||
|
case SHARED_SCOPE -> sharedAttrMap.remove(keyId) != null; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private DataPoint getAttributeDataPoint(Integer keyId) { |
||||
|
DataPoint dp = serverAttrMap.get(keyId); |
||||
|
if (dp == null) { |
||||
|
dp = sharedAttrMap.get(keyId); |
||||
|
if (dp == null) { |
||||
|
dp = clientAttrMap.get(keyId); |
||||
|
} |
||||
|
} |
||||
|
return dp; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.AttributeScope; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
import org.thingsboard.server.common.data.permission.QueryContext; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.edqs.data.dp.DataPoint; |
||||
|
import org.thingsboard.server.edqs.query.DataKey; |
||||
|
import org.thingsboard.server.edqs.repo.TenantRepo; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public interface EntityData<T extends EntityFields> { |
||||
|
|
||||
|
UUID getId(); |
||||
|
|
||||
|
EntityType getEntityType(); |
||||
|
|
||||
|
UUID getCustomerId(); |
||||
|
|
||||
|
void setCustomerId(UUID customerId); |
||||
|
|
||||
|
void setRepo(TenantRepo repo); |
||||
|
|
||||
|
T getFields(); |
||||
|
|
||||
|
void setFields(T fields); |
||||
|
|
||||
|
DataPoint getAttr(Integer keyId, EntityKeyType entityKeyType); |
||||
|
|
||||
|
boolean putAttr(Integer keyId, AttributeScope scope, DataPoint value); |
||||
|
|
||||
|
boolean removeAttr(Integer keyId, AttributeScope scope); |
||||
|
|
||||
|
DataPoint getTs(Integer keyId); |
||||
|
|
||||
|
boolean putTs(Integer keyId, DataPoint value); |
||||
|
|
||||
|
boolean removeTs(Integer keyId); |
||||
|
|
||||
|
EntityType getOwnerType(); |
||||
|
|
||||
|
DataPoint getDataPoint(DataKey key, QueryContext queryContext); |
||||
|
|
||||
|
String getField(String name); |
||||
|
|
||||
|
boolean isEmpty(); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityGroupFields; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
import java.util.concurrent.ConcurrentMap; |
||||
|
|
||||
|
public class EntityGroupData extends BaseEntityData<EntityGroupFields> { |
||||
|
|
||||
|
private final ConcurrentMap<UUID, EntityData<?>> entitiesById = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
public EntityGroupData(UUID entityId) { |
||||
|
super(entityId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.ENTITY_GROUP; |
||||
|
} |
||||
|
|
||||
|
public Collection<EntityData<?>> getEntities() { |
||||
|
return entitiesById.values(); |
||||
|
} |
||||
|
|
||||
|
public boolean addOrUpdate(EntityData<?> ed) { |
||||
|
return entitiesById.put(ed.getId(), ed) == null; |
||||
|
} |
||||
|
|
||||
|
public boolean remove(EntityData<?> ed) { |
||||
|
return entitiesById.remove(ed.getId()) != null; |
||||
|
} |
||||
|
|
||||
|
public EntityData<?> getEntity(UUID entityId) { |
||||
|
return entitiesById.get(entityId); |
||||
|
} |
||||
|
|
||||
|
public boolean remove(UUID toId) { |
||||
|
return entitiesById.remove(toId) != null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@ToString(callSuper = true) |
||||
|
public class EntityProfileData extends BaseEntityData<EntityFields> { |
||||
|
|
||||
|
private final EntityType entityType; |
||||
|
|
||||
|
public EntityProfileData(UUID entityId, EntityType entityType) { |
||||
|
super(entityId); |
||||
|
this.entityType = entityType; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return entityType; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.ToString; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.EntityFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@ToString(callSuper = true) |
||||
|
public class GenericData extends BaseEntityData<EntityFields> { |
||||
|
|
||||
|
private final EntityType entityType; |
||||
|
|
||||
|
public GenericData(EntityType entityType, UUID entityId) { |
||||
|
super(entityId); |
||||
|
this.entityType = entityType; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return entityType; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.edqs.fields.ProfileAwareFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public abstract class ProfileAwareData<T> extends BaseEntityData<ProfileAwareFields> { |
||||
|
|
||||
|
public ProfileAwareData(UUID id) { |
||||
|
super(id); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public record RelationData(UUID fromId, EntityType fromType, UUID toId, EntityType toType, String type, |
||||
|
RelationTypeGroup typeGroup) { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class RelationInfo { |
||||
|
|
||||
|
private final String type; |
||||
|
private final EntityData<?> target; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.Set; |
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
import java.util.concurrent.ConcurrentMap; |
||||
|
|
||||
|
@NoArgsConstructor |
||||
|
public class RelationsRepo { |
||||
|
|
||||
|
private final ConcurrentMap<UUID, Set<RelationInfo>> fromRelations = new ConcurrentHashMap<>(); |
||||
|
private final ConcurrentMap<UUID, Set<RelationInfo>> toRelations = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
public boolean add(EntityData<?> from, EntityData<?> to, String type) { |
||||
|
boolean addedFromRelation = fromRelations.computeIfAbsent(from.getId(), k -> ConcurrentHashMap.newKeySet()).add(new RelationInfo(type, to)); |
||||
|
boolean addedToRelation = toRelations.computeIfAbsent(to.getId(), k -> ConcurrentHashMap.newKeySet()).add(new RelationInfo(type, from)); |
||||
|
return addedFromRelation || addedToRelation; |
||||
|
} |
||||
|
|
||||
|
public Set<RelationInfo> getFrom(UUID entityId) { |
||||
|
var result = fromRelations.get(entityId); |
||||
|
return result == null ? Collections.emptySet() : result; |
||||
|
} |
||||
|
|
||||
|
public Set<RelationInfo> getTo(UUID entityId) { |
||||
|
var result = toRelations.get(entityId); |
||||
|
return result == null ? Collections.emptySet() : result; |
||||
|
} |
||||
|
|
||||
|
public boolean remove(UUID from, UUID to, String type) { |
||||
|
boolean removedFromRelation = false; |
||||
|
boolean removedToRelation = false; |
||||
|
Set<RelationInfo> fromRelations = this.fromRelations.get(from); |
||||
|
if (fromRelations != null) { |
||||
|
removedFromRelation = fromRelations.removeIf(relationInfo -> relationInfo.getTarget().getId().equals(to) && relationInfo.getType().equals(type)); |
||||
|
} |
||||
|
Set<RelationInfo> toRelations = this.toRelations.get(to); |
||||
|
if (toRelations != null) { |
||||
|
removedToRelation = toRelations.removeIf(relationInfo -> relationInfo.getTarget().getId().equals(from) && relationInfo.getType().equals(type)); |
||||
|
} |
||||
|
return removedFromRelation || removedToRelation; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.edqs.fields.TenantFields; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public class TenantData extends BaseEntityData<TenantFields> { |
||||
|
|
||||
|
public TenantData(UUID entityId) { |
||||
|
super(entityId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public EntityType getEntityType() { |
||||
|
return EntityType.TENANT; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
|
||||
|
@RequiredArgsConstructor |
||||
|
public abstract class AbstractDataPoint implements DataPoint { |
||||
|
|
||||
|
@Getter |
||||
|
private final long ts; |
||||
|
|
||||
|
@Override |
||||
|
public String getStr() { |
||||
|
throw new RuntimeException(NOT_SUPPORTED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public long getLong() { |
||||
|
throw new RuntimeException(NOT_SUPPORTED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getDouble() { |
||||
|
throw new RuntimeException(NOT_SUPPORTED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean getBool() { |
||||
|
throw new RuntimeException(NOT_SUPPORTED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getJson() { |
||||
|
throw new RuntimeException(NOT_SUPPORTED); |
||||
|
} |
||||
|
|
||||
|
public String toString() { |
||||
|
return valueToString(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
|
||||
|
public class BoolDataPoint extends AbstractDataPoint { |
||||
|
|
||||
|
@Getter |
||||
|
private final boolean value; |
||||
|
|
||||
|
public BoolDataPoint(long ts, boolean value) { |
||||
|
super(ts); |
||||
|
this.value = value; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataType getType() { |
||||
|
return DataType.BOOLEAN; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean getBool() { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String valueToString() { |
||||
|
return Boolean.toString(value); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
|
||||
|
public class CompressedJsonDataPoint extends CompressedStringDataPoint { |
||||
|
|
||||
|
public CompressedJsonDataPoint(long ts, String value) { |
||||
|
super(ts, value); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataType getType() { |
||||
|
return DataType.JSON; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import lombok.SneakyThrows; |
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
import org.thingsboard.server.edqs.repo.TbBytePool; |
||||
|
import org.xerial.snappy.Snappy; |
||||
|
|
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.concurrent.atomic.AtomicInteger; |
||||
|
import java.util.concurrent.atomic.AtomicLong; |
||||
|
|
||||
|
public class CompressedStringDataPoint extends AbstractDataPoint { |
||||
|
|
||||
|
public static final int MIN_STR_SIZE_TO_COMPRESS = 512; |
||||
|
@Getter |
||||
|
private final byte[] value; |
||||
|
|
||||
|
public static final AtomicInteger cnt = new AtomicInteger(); |
||||
|
public static final AtomicLong uncompressedLength = new AtomicLong(); |
||||
|
public static final AtomicLong compressedLength = new AtomicLong(); |
||||
|
|
||||
|
@SneakyThrows |
||||
|
public CompressedStringDataPoint(long ts, String value) { |
||||
|
super(ts); |
||||
|
cnt.incrementAndGet(); |
||||
|
uncompressedLength.addAndGet(value.getBytes(StandardCharsets.UTF_8).length); |
||||
|
this.value = TbBytePool.intern(Snappy.compress(value)); |
||||
|
compressedLength.addAndGet(this.value.length); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataType getType() { |
||||
|
return DataType.STRING; |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
@Override |
||||
|
public String getStr() { |
||||
|
return Snappy.uncompressString(value); |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
@Override |
||||
|
public String valueToString() { |
||||
|
return Snappy.uncompressString(value); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
|
||||
|
public interface DataPoint { |
||||
|
|
||||
|
String NOT_SUPPORTED = "Not supported!"; |
||||
|
|
||||
|
long getTs(); |
||||
|
|
||||
|
DataType getType(); |
||||
|
|
||||
|
String getStr(); |
||||
|
|
||||
|
long getLong(); |
||||
|
|
||||
|
double getDouble(); |
||||
|
|
||||
|
boolean getBool(); |
||||
|
|
||||
|
String getJson(); |
||||
|
|
||||
|
String valueToString(); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
|
||||
|
public class DoubleDataPoint extends AbstractDataPoint { |
||||
|
|
||||
|
@Getter |
||||
|
private final double value; |
||||
|
|
||||
|
public DoubleDataPoint(long ts, double value) { |
||||
|
super(ts); |
||||
|
this.value = value; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataType getType() { |
||||
|
return DataType.DOUBLE; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getDouble() { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String valueToString() { |
||||
|
return Double.toString(value); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 ThingsBoard, Inc. |
||||
|
* |
||||
|
* 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.edqs.data.dp; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import org.thingsboard.server.common.data.kv.DataType; |
||||
|
import org.thingsboard.server.edqs.repo.TbStringPool; |
||||
|
|
||||
|
public class JsonDataPoint extends AbstractDataPoint { |
||||
|
|
||||
|
@Getter |
||||
|
private final String value; |
||||
|
|
||||
|
public JsonDataPoint(long ts, String value) { |
||||
|
super(ts); |
||||
|
this.value = TbStringPool.intern(value); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public DataType getType() { |
||||
|
return DataType.JSON; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getJson() { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String valueToString() { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue