Browse Source

Get rid of boilerplate for export

pull/6357/head
Viacheslav Klimov 5 years ago
parent
commit
a35b16d7cb
  1. 18
      application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java
  2. 40
      application/src/main/java/org/thingsboard/server/service/sync/DefaultEntitiesExportImportService.java
  3. 3
      application/src/main/java/org/thingsboard/server/service/sync/exporting/EntityExportService.java
  4. 32
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/AssetExportData.java
  5. 32
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/CustomerExportData.java
  6. 32
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DashboardExportData.java
  7. 6
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DeviceExportData.java
  8. 32
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DeviceProfileExportData.java
  9. 31
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/EntityExportData.java
  10. 6
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/RuleChainExportData.java
  11. 6
      application/src/main/java/org/thingsboard/server/service/sync/exporting/data/request/EntityExportSettings.java
  12. 39
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/AssetExportService.java
  13. 60
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/BaseEntityExportService.java
  14. 39
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/CustomerExportService.java
  15. 39
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DashboardExportService.java
  16. 90
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DefaultEntityExportService.java
  17. 6
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DeviceExportService.java
  18. 39
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DeviceProfileExportService.java
  19. 6
      application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/RuleChainExportService.java
  20. 3
      application/src/main/java/org/thingsboard/server/service/sync/importing/data/EntityImportResult.java
  21. 9
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/AssetImportService.java
  22. 3
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/BaseEntityImportService.java
  23. 9
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/CustomerImportService.java
  24. 9
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DashboardImportService.java
  25. 3
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DeviceImportService.java
  26. 9
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DeviceProfileImportService.java
  27. 3
      application/src/main/java/org/thingsboard/server/service/sync/importing/impl/RuleChainImportService.java
  28. 62
      application/src/test/java/org/thingsboard/server/controller/BaseEntitiesExportImportControllerTest.java
  29. 60
      application/src/test/java/org/thingsboard/server/controller/sql/EntitiesExportImportControllerSqlTest.java

18
application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java

@ -16,6 +16,7 @@
package org.thingsboard.server.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -52,6 +53,7 @@ import org.thingsboard.server.service.sync.importing.data.request.ImportRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@ -61,6 +63,7 @@ import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME
@RequestMapping("/api/entities")
@TbCoreComponent
@RequiredArgsConstructor
@Slf4j
public class EntitiesExportImportController extends BaseController {
private final EntitiesExportImportService exportImportService;
@ -160,7 +163,20 @@ public class EntitiesExportImportController extends BaseController {
public List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(@RequestBody ImportRequest importRequest) throws ThingsboardException {
SecurityUser user = getCurrentUser();
try {
return exportImportService.importEntities(user, importRequest.getExportDataList(), importRequest.getImportSettings());
List<EntityImportResult<ExportableEntity<EntityId>>> importResults = exportImportService.importEntities(user, importRequest.getExportDataList(), importRequest.getImportSettings());
importResults.stream()
.map(EntityImportResult::getPushEventsCallback)
.filter(Objects::nonNull)
.forEach(pushEventsCallback -> {
try {
pushEventsCallback.run();
} catch (Exception e) {
log.error("Failed to send event for entity", e);
}
});
return importResults;
} catch (Exception e) {
throw handleException(e);
}

40
application/src/main/java/org/thingsboard/server/service/sync/DefaultEntitiesExportImportService.java

@ -16,7 +16,6 @@
package org.thingsboard.server.service.sync;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -39,6 +38,8 @@ import org.thingsboard.server.service.sync.exporting.EntityExportService;
import org.thingsboard.server.service.sync.exporting.ExportableEntitiesService;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
import org.thingsboard.server.service.sync.exporting.impl.BaseEntityExportService;
import org.thingsboard.server.service.sync.exporting.impl.DefaultEntityExportService;
import org.thingsboard.server.service.sync.importing.EntityImportService;
import org.thingsboard.server.service.sync.importing.data.EntityImportResult;
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
@ -56,7 +57,6 @@ import java.util.stream.Collectors;
@Service
@TbCoreComponent
@RequiredArgsConstructor
@Slf4j
public class DefaultEntitiesExportImportService implements EntitiesExportImportService, ExportableEntitiesService {
private final Map<EntityType, EntityExportService<?, ?, ?>> exportServices = new HashMap<>();
@ -98,17 +98,6 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
saveReferencesCallback.run();
}
importResults.stream()
.map(EntityImportResult::getPushEventsCallback)
.filter(Objects::nonNull)
.forEach(pushEventsCallback -> {
try {
pushEventsCallback.run();
} catch (Exception e) {
log.error("Failed to send event for entity", e);
}
});
return importResults;
}
@ -188,16 +177,31 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
return daos.get(entityType);
}
@Autowired
private void setServices(Collection<EntityExportService<?, ?, ?>> exportServices,
Collection<EntityImportService<?, ?, ?>> importServices,
Collection<Dao<?>> daos) {
exportServices.forEach(entityExportService -> {
this.exportServices.put(entityExportService.getEntityType(), entityExportService);
private void setExportServices(DefaultEntityExportService<?, ?, ?> defaultExportService,
Collection<BaseEntityExportService<?, ?, ?>> exportServices) {
exportServices.stream()
.sorted(Comparator.comparing(exportService -> exportService.getSupportedEntityTypes().size(), Comparator.reverseOrder()))
.forEach(exportService -> {
exportService.getSupportedEntityTypes().forEach(entityType -> {
this.exportServices.put(entityType, exportService);
});
});
SUPPORTED_ENTITY_TYPES.forEach(entityType -> {
this.exportServices.putIfAbsent(entityType, defaultExportService);
});
}
@Autowired
private void setImportServices(Collection<EntityImportService<?, ?, ?>> importServices) {
importServices.forEach(entityImportService -> {
this.importServices.put(entityImportService.getEntityType(), entityImportService);
});
}
@Autowired
private void setDaos(Collection<Dao<?>> daos) {
daos.forEach(dao -> {
if (dao.getEntityType() != null) {
this.daos.put(dao.getEntityType(), dao);

3
application/src/main/java/org/thingsboard/server/service/sync/exporting/EntityExportService.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.service.sync.exporting;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
@ -27,6 +26,4 @@ public interface EntityExportService<I extends EntityId, E extends ExportableEnt
D getExportData(SecurityUser user, I entityId, EntityExportSettings exportSettings) throws ThingsboardException;
EntityType getEntityType();
}

32
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/AssetExportData.java

@ -1,32 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
@EqualsAndHashCode(callSuper = true)
@Data
public class AssetExportData extends EntityExportData<Asset> {
@Override
public EntityType getEntityType() {
return EntityType.ASSET;
}
}

32
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/CustomerExportData.java

@ -1,32 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntityType;
@EqualsAndHashCode(callSuper = true)
@Data
public class CustomerExportData extends EntityExportData<Customer> {
@Override
public EntityType getEntityType() {
return EntityType.CUSTOMER;
}
}

32
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DashboardExportData.java

@ -1,32 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EntityType;
@EqualsAndHashCode(callSuper = true)
@Data
public class DashboardExportData extends EntityExportData<Dashboard> {
@Override
public EntityType getEntityType() {
return EntityType.DASHBOARD;
}
}

6
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DeviceExportData.java

@ -18,7 +18,6 @@ package org.thingsboard.server.service.sync.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.security.DeviceCredentials;
@EqualsAndHashCode(callSuper = true)
@ -27,9 +26,4 @@ public class DeviceExportData extends EntityExportData<Device> {
private DeviceCredentials credentials;
@Override
public EntityType getEntityType() {
return EntityType.DEVICE;
}
}

32
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/DeviceProfileExportData.java

@ -1,32 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
@EqualsAndHashCode(callSuper = true)
@Data
public class DeviceProfileExportData extends EntityExportData<DeviceProfile> {
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;
}
}

31
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/EntityExportData.java

@ -15,39 +15,48 @@
*/
package org.thingsboard.server.service.sync.exporting.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
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.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.rule.RuleChain;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", defaultImpl = EntityExportData.class, visible = true)
@JsonSubTypes({
@Type(name = "DEVICE", value = DeviceExportData.class),
@Type(name = "DEVICE_PROFILE", value = DeviceProfileExportData.class),
@Type(name = "ASSET", value = AssetExportData.class),
@Type(name = "RULE_CHAIN", value = RuleChainExportData.class),
@Type(name = "DASHBOARD", value = DashboardExportData.class),
@Type(name = "CUSTOMER", value = CustomerExportData.class)
@Type(name = "RULE_CHAIN", value = RuleChainExportData.class)
})
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public abstract class EntityExportData<E extends ExportableEntity<? extends EntityId>> {
public class EntityExportData<E extends ExportableEntity<? extends EntityId>> {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
@JsonSubTypes({
@Type(name = "DEVICE", value = Device.class),
@Type(name = "RULE_CHAIN", value = RuleChain.class),
@Type(name = "DEVICE_PROFILE", value = DeviceProfile.class),
@Type(name = "ASSET", value = Asset.class),
@Type(name = "DASHBOARD", value = Dashboard.class),
@Type(name = "CUSTOMER", value = Customer.class)
})
private E entity;
private EntityType entityType;
private List<EntityRelation> inboundRelations;
private List<EntityRelation> outboundRelations;
@JsonIgnore
public abstract EntityType getEntityType();
}

6
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/RuleChainExportData.java

@ -17,7 +17,6 @@ package org.thingsboard.server.service.sync.exporting.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@ -27,9 +26,4 @@ public class RuleChainExportData extends EntityExportData<RuleChain> {
private RuleChainMetaData metaData;
@Override
public EntityType getEntityType() {
return EntityType.RULE_CHAIN;
}
}

6
application/src/main/java/org/thingsboard/server/service/sync/exporting/data/request/EntityExportSettings.java

@ -15,9 +15,15 @@
*/
package org.thingsboard.server.service.sync.exporting.data.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EntityExportSettings {
private boolean exportInboundRelations;
private boolean exportOutboundRelations;

39
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/AssetExportService.java

@ -1,39 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.impl;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.AssetExportData;
@Service
@TbCoreComponent
public class AssetExportService extends BaseEntityExportService<AssetId, Asset, AssetExportData> {
@Override
protected AssetExportData newExportData() {
return new AssetExportData();
}
@Override
public EntityType getEntityType() {
return EntityType.ASSET;
}
}

60
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/BaseEntityExportService.java

@ -15,71 +15,29 @@
*/
package org.thingsboard.server.service.sync.exporting.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.sync.exporting.EntityExportService;
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
import org.thingsboard.server.service.sync.exporting.ExportableEntitiesService;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
import java.util.List;
public abstract class BaseEntityExportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> implements EntityExportService<I, E, D> {
import java.util.Set;
@Autowired @Lazy
private ExportableEntitiesService exportableEntitiesService;
@Autowired
private RelationService relationService;
public abstract class BaseEntityExportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> extends DefaultEntityExportService<I, E, D> {
@Override
public final D getExportData(SecurityUser user, I entityId, EntityExportSettings exportSettings) throws ThingsboardException {
D exportData = newExportData();
E entity = exportableEntitiesService.findEntityByTenantIdAndId(user.getTenantId(), entityId);
if (entity == null) {
throw new IllegalArgumentException("Entity not found");
}
exportableEntitiesService.checkPermission(user, entity, getEntityType(), Operation.READ);
exportData.setEntity(entity);
setRelatedEntities(user.getTenantId(), entity, exportData);
setAdditionalExportData(user, entity, exportData, exportSettings);
return exportData;
protected void setAdditionalExportData(SecurityUser user, E entity, D exportData, EntityExportSettings exportSettings) throws ThingsboardException {
setRelatedEntities(user.getTenantId(), entity, (D) exportData);
super.setAdditionalExportData(user, entity, exportData, exportSettings);
}
protected void setRelatedEntities(TenantId tenantId, E mainEntity, D exportData) {}
protected void setAdditionalExportData(SecurityUser user, E entity, D exportData, EntityExportSettings exportSettings) throws ThingsboardException {
if (exportSettings.isExportInboundRelations()) {
List<EntityRelation> inboundRelations = relationService.findByTo(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
if (inboundRelations != null) {
for (EntityRelation relation : inboundRelations) {
exportableEntitiesService.checkPermission(user, relation.getFrom(), Operation.READ);
}
}
exportData.setInboundRelations(inboundRelations);
}
if (exportSettings.isExportOutboundRelations()) {
List<EntityRelation> outboundRelations = relationService.findByFrom(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
if (outboundRelations != null) {
for (EntityRelation relation : outboundRelations) {
exportableEntitiesService.checkPermission(user, relation.getTo(), Operation.READ);
}
}
exportData.setOutboundRelations(outboundRelations);
}
}
protected abstract D newExportData();
public abstract Set<EntityType> getSupportedEntityTypes();
}

39
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/CustomerExportService.java

@ -1,39 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.impl;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.CustomerExportData;
@Service
@TbCoreComponent
public class CustomerExportService extends BaseEntityExportService<CustomerId, Customer, CustomerExportData> {
@Override
protected CustomerExportData newExportData() {
return new CustomerExportData();
}
@Override
public EntityType getEntityType() {
return EntityType.CUSTOMER;
}
}

39
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DashboardExportService.java

@ -1,39 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.impl;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.DashboardExportData;
@Service
@TbCoreComponent
public class DashboardExportService extends BaseEntityExportService<DashboardId, Dashboard, DashboardExportData> {
@Override
protected DashboardExportData newExportData() {
return new DashboardExportData();
}
@Override
public EntityType getEntityType() {
return EntityType.DASHBOARD;
}
}

90
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DefaultEntityExportService.java

@ -0,0 +1,90 @@
/**
* Copyright © 2016-2022 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.exporting.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.sync.exporting.EntityExportService;
import org.thingsboard.server.service.sync.exporting.ExportableEntitiesService;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
import java.util.List;
@Service
@TbCoreComponent
@Primary
public class DefaultEntityExportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> implements EntityExportService<I, E, D> {
@Autowired @Lazy
private ExportableEntitiesService exportableEntitiesService;
@Autowired
private RelationService relationService;
@Override
public final D getExportData(SecurityUser user, I entityId, EntityExportSettings exportSettings) throws ThingsboardException {
D exportData = newExportData();
E entity = exportableEntitiesService.findEntityByTenantIdAndId(user.getTenantId(), entityId);
if (entity == null) {
throw new IllegalArgumentException(entityId.getEntityType() + " [" + entityId.getId() + "] not found");
}
exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ);
exportData.setEntity(entity);
exportData.setEntityType(entityId.getEntityType());
setAdditionalExportData(user, entity, exportData, exportSettings);
return exportData;
}
protected void setAdditionalExportData(SecurityUser user, E entity, D exportData, EntityExportSettings exportSettings) throws ThingsboardException {
if (exportSettings.isExportInboundRelations()) {
List<EntityRelation> inboundRelations = relationService.findByTo(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
if (inboundRelations != null) {
for (EntityRelation relation : inboundRelations) {
exportableEntitiesService.checkPermission(user, relation.getFrom(), Operation.READ);
}
}
exportData.setInboundRelations(inboundRelations);
}
if (exportSettings.isExportOutboundRelations()) {
List<EntityRelation> outboundRelations = relationService.findByFrom(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
if (outboundRelations != null) {
for (EntityRelation relation : outboundRelations) {
exportableEntitiesService.checkPermission(user, relation.getTo(), Operation.READ);
}
}
exportData.setOutboundRelations(outboundRelations);
}
}
protected D newExportData() {
return (D) new EntityExportData<E>();
}
}

6
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DeviceExportService.java

@ -25,6 +25,8 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.DeviceExportData;
import java.util.Set;
@Service
@TbCoreComponent
@RequiredArgsConstructor
@ -43,8 +45,8 @@ public class DeviceExportService extends BaseEntityExportService<DeviceId, Devic
}
@Override
public EntityType getEntityType() {
return EntityType.DEVICE;
public Set<EntityType> getSupportedEntityTypes() {
return Set.of(EntityType.DEVICE);
}
}

39
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/DeviceProfileExportService.java

@ -1,39 +0,0 @@
/**
* Copyright © 2016-2022 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.exporting.impl;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.DeviceProfileExportData;
@Service
@TbCoreComponent
public class DeviceProfileExportService extends BaseEntityExportService<DeviceProfileId, DeviceProfile, DeviceProfileExportData> {
@Override
protected DeviceProfileExportData newExportData() {
return new DeviceProfileExportData();
}
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;
}
}

6
application/src/main/java/org/thingsboard/server/service/sync/exporting/impl/RuleChainExportService.java

@ -25,6 +25,8 @@ import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
import java.util.Set;
@Service
@TbCoreComponent
@RequiredArgsConstructor
@ -43,8 +45,8 @@ public class RuleChainExportService extends BaseEntityExportService<RuleChainId,
}
@Override
public EntityType getEntityType() {
return EntityType.RULE_CHAIN;
public Set<EntityType> getSupportedEntityTypes() {
return Set.of(EntityType.RULE_CHAIN);
}
}

3
application/src/main/java/org/thingsboard/server/service/sync/importing/data/EntityImportResult.java

@ -18,6 +18,7 @@ package org.thingsboard.server.service.sync.importing.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.utils.ThrowingRunnable;
@ -27,6 +28,8 @@ public class EntityImportResult<E extends ExportableEntity<? extends EntityId>>
private E savedEntity;
@Getter @Setter
private E oldEntity;
@Getter @Setter
private EntityType entityType;
@Getter @JsonIgnore
private ThrowingRunnable saveReferencesCallback = () -> {};

9
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/AssetImportService.java

@ -20,17 +20,18 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.sync.exporting.data.AssetExportData;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class AssetImportService extends BaseEntityImportService<AssetId, Asset, AssetExportData> {
public class AssetImportService extends BaseEntityImportService<AssetId, Asset, EntityExportData<Asset>> {
private final AssetService assetService;
@ -41,12 +42,12 @@ public class AssetImportService extends BaseEntityImportService<AssetId, Asset,
}
@Override
protected Asset prepareAndSave(TenantId tenantId, Asset asset, AssetExportData exportData, NewIdProvider idProvider) {
protected Asset prepareAndSave(TenantId tenantId, Asset asset, EntityExportData<Asset> exportData, NewIdProvider idProvider) {
return assetService.saveAsset(asset);
}
@Override
protected void onEntitySaved(SecurityUser user, Asset savedAsset, Asset oldAsset) {
protected void onEntitySaved(SecurityUser user, Asset savedAsset, Asset oldAsset) throws ThingsboardException {
super.onEntitySaved(user, savedAsset, oldAsset);
if (oldAsset != null) {
entityActionService.sendEntityNotificationMsgToEdgeService(user.getTenantId(), savedAsset.getId(), EdgeEventActionType.UPDATED);

3
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/BaseEntityImportService.java

@ -84,6 +84,7 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
EntityImportResult<E> importResult = new EntityImportResult<>();
importResult.setSavedEntity(savedEntity);
importResult.setOldEntity(existingEntity);
importResult.setEntityType(getEntityType());
processAfterSaved(user, importResult, exportData, idProvider, importSettings);
@ -150,7 +151,7 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
});
}
protected void onEntitySaved(SecurityUser user, E savedEntity, E oldEntity) {
protected void onEntitySaved(SecurityUser user, E savedEntity, E oldEntity) throws ThingsboardException {
entityActionService.logEntityAction(user, savedEntity.getId(), savedEntity,
savedEntity instanceof HasCustomerId ? ((HasCustomerId) savedEntity).getCustomerId() : user.getCustomerId(),
oldEntity == null ? ActionType.ADDED : ActionType.UPDATED, null);

9
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/CustomerImportService.java

@ -20,17 +20,18 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.sync.exporting.data.CustomerExportData;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class CustomerImportService extends BaseEntityImportService<CustomerId, Customer, CustomerExportData> {
public class CustomerImportService extends BaseEntityImportService<CustomerId, Customer, EntityExportData<Customer>> {
private final CustomerService customerService;
@ -40,12 +41,12 @@ public class CustomerImportService extends BaseEntityImportService<CustomerId, C
}
@Override
protected Customer prepareAndSave(TenantId tenantId, Customer customer, CustomerExportData exportData, NewIdProvider idProvider) {
protected Customer prepareAndSave(TenantId tenantId, Customer customer, EntityExportData<Customer> exportData, NewIdProvider idProvider) {
return customerService.saveCustomer(customer);
}
@Override
protected void onEntitySaved(SecurityUser user, Customer savedCustomer, Customer oldCustomer) {
protected void onEntitySaved(SecurityUser user, Customer savedCustomer, Customer oldCustomer) throws ThingsboardException {
super.onEntitySaved(user, savedCustomer, oldCustomer);
if (oldCustomer != null) {
entityActionService.sendEntityNotificationMsgToEdgeService(user.getTenantId(), savedCustomer.getId(), EdgeEventActionType.UPDATED);

9
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DashboardImportService.java

@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId;
@ -34,7 +35,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.sql.query.DefaultEntityQueryRepository;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.sync.exporting.data.DashboardExportData;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import java.util.Collections;
import java.util.HashSet;
@ -46,7 +47,7 @@ import java.util.stream.Collectors;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class DashboardImportService extends BaseEntityImportService<DashboardId, Dashboard, DashboardExportData> {
public class DashboardImportService extends BaseEntityImportService<DashboardId, Dashboard, EntityExportData<Dashboard>> {
private final DashboardService dashboardService;
@ -58,7 +59,7 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
}
@Override
protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, DashboardExportData exportData, NewIdProvider idProvider) {
protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, NewIdProvider idProvider) {
Optional.ofNullable(dashboard.getConfiguration())
.flatMap(configuration -> Optional.ofNullable(configuration.get("entityAliases")))
.filter(JsonNode::isObject)
@ -110,7 +111,7 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
}
@Override
protected void onEntitySaved(SecurityUser user, Dashboard savedDashboard, Dashboard oldDashboard) {
protected void onEntitySaved(SecurityUser user, Dashboard savedDashboard, Dashboard oldDashboard) throws ThingsboardException {
super.onEntitySaved(user, savedDashboard, oldDashboard);
if (oldDashboard != null) {
entityActionService.sendEntityNotificationMsgToEdgeService(user.getTenantId(), savedDashboard.getId(), EdgeEventActionType.UPDATED);

3
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DeviceImportService.java

@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.device.DeviceService;
@ -54,7 +55,7 @@ public class DeviceImportService extends BaseEntityImportService<DeviceId, Devic
}
@Override
protected void onEntitySaved(SecurityUser user, Device savedDevice, Device oldDevice) {
protected void onEntitySaved(SecurityUser user, Device savedDevice, Device oldDevice) throws ThingsboardException {
super.onEntitySaved(user, savedDevice, oldDevice);
clusterService.onDeviceUpdated(savedDevice, oldDevice);
}

9
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/DeviceProfileImportService.java

@ -20,6 +20,7 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
@ -27,14 +28,14 @@ import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.ota.OtaPackageStateService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.sync.exporting.data.DeviceProfileExportData;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import java.util.Objects;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class DeviceProfileImportService extends BaseEntityImportService<DeviceProfileId, DeviceProfile, DeviceProfileExportData> {
public class DeviceProfileImportService extends BaseEntityImportService<DeviceProfileId, DeviceProfile, EntityExportData<DeviceProfile>> {
private final DeviceProfileService deviceProfileService;
private final OtaPackageStateService otaPackageStateService;
@ -45,7 +46,7 @@ public class DeviceProfileImportService extends BaseEntityImportService<DevicePr
}
@Override
protected DeviceProfile prepareAndSave(TenantId tenantId, DeviceProfile deviceProfile, DeviceProfileExportData exportData, NewIdProvider idProvider) {
protected DeviceProfile prepareAndSave(TenantId tenantId, DeviceProfile deviceProfile, EntityExportData<DeviceProfile> exportData, NewIdProvider idProvider) {
deviceProfile.setDefaultRuleChainId(idProvider.get(DeviceProfile::getDefaultRuleChainId));
deviceProfile.setDefaultDashboardId(idProvider.get(DeviceProfile::getDefaultDashboardId));
deviceProfile.setFirmwareId(idProvider.get(DeviceProfile::getFirmwareId));
@ -54,7 +55,7 @@ public class DeviceProfileImportService extends BaseEntityImportService<DevicePr
}
@Override
protected void onEntitySaved(SecurityUser user, DeviceProfile savedDeviceProfile, DeviceProfile oldDeviceProfile) {
protected void onEntitySaved(SecurityUser user, DeviceProfile savedDeviceProfile, DeviceProfile oldDeviceProfile) throws ThingsboardException {
super.onEntitySaved(user, savedDeviceProfile, oldDeviceProfile);
clusterService.onDeviceProfileChange(savedDeviceProfile, null);
clusterService.broadcastEntityStateChangeEvent(user.getTenantId(), savedDeviceProfile.getId(),

3
application/src/main/java/org/thingsboard/server/service/sync/importing/impl/RuleChainImportService.java

@ -22,6 +22,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
@ -84,7 +85,7 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
}
@Override
protected void onEntitySaved(SecurityUser user, RuleChain savedRuleChain, RuleChain oldRuleChain) {
protected void onEntitySaved(SecurityUser user, RuleChain savedRuleChain, RuleChain oldRuleChain) throws ThingsboardException {
super.onEntitySaved(user, savedRuleChain, oldRuleChain);
if (savedRuleChain.getType() == RuleChainType.CORE) {
clusterService.broadcastEntityStateChangeEvent(user.getTenantId(), savedRuleChain.getId(),

62
application/src/test/java/org/thingsboard/server/controller/BaseEntitiesExportImportControllerTest.java

@ -15,8 +15,10 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.TextNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.ResultActions;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration;
import org.thingsboard.server.common.data.Customer;
@ -25,6 +27,7 @@ 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.DeviceTransportType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.DeviceData;
@ -33,6 +36,7 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTra
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@ -44,9 +48,20 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
import org.thingsboard.server.service.sync.exporting.data.request.ExportRequest;
import org.thingsboard.server.service.sync.exporting.data.request.SingleEntityExportRequest;
import org.thingsboard.server.service.sync.importing.data.EntityImportResult;
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
import org.thingsboard.server.service.sync.importing.data.request.ImportRequest;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public abstract class BaseEntitiesExportImportControllerTest extends AbstractControllerTest {
@ -163,4 +178,49 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
return ruleChainService.findRuleChainById(tenantId, ruleChain.getId());
}
protected <E extends ExportableEntity<I>, I extends EntityId> EntityExportData<E> exportSingleEntity(I entityId) throws Exception {
SingleEntityExportRequest exportRequest = new SingleEntityExportRequest();
exportRequest.setEntityId(entityId);
exportRequest.setExportSettings(new EntityExportSettings());
return (EntityExportData<E>) exportEntities(exportRequest).get(0);
}
protected List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(ExportRequest exportRequest) throws Exception {
return getResponse(doPost("/api/entities/export", exportRequest), new TypeReference<List<EntityExportData<ExportableEntity<EntityId>>>>() {});
}
protected List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(List<ExportRequest> exportRequests) throws Exception {
return getResponse(doPost("/api/entities/export?multiple", exportRequests), new TypeReference<List<EntityExportData<ExportableEntity<EntityId>>>>() {});
}
protected <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(EntityExportData<E> exportData) throws Exception {
return (EntityImportResult<E>) importEntities(List.of((EntityExportData<ExportableEntity<EntityId>>)exportData)).get(0);
}
protected List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(List<EntityExportData<ExportableEntity<EntityId>>> exportDataList) throws Exception {
ImportRequest importRequest = new ImportRequest();
importRequest.setImportSettings(EntityImportSettings.builder()
.updateReferencesToOtherEntities(true)
.build());
importRequest.setExportDataList(exportDataList);
return getResponse(doPost("/api/entities/import", importRequest), new TypeReference<List<EntityImportResult<ExportableEntity<EntityId>>>>() {
@Override
public Type getType() {
return mapper.getTypeFactory().constructCollectionType(List.class,
mapper.getTypeFactory().constructParametricType(EntityImportResult.class,
exportDataList.get(0).getEntity().getClass()));
}
});
}
protected <T> T getResponse(ResultActions resultActions, TypeReference<T> typeReference) throws Exception {
try {
return readResponse(resultActions.andExpect(status().isOk()), typeReference);
} catch (AssertionError e) {
throw new AssertionError(readResponse(resultActions, String.class), e);
}
}
}

60
application/src/test/java/org/thingsboard/server/controller/sql/EntitiesExportImportControllerSqlTest.java

@ -15,15 +15,10 @@
*/
package org.thingsboard.server.controller.sql;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import lombok.SneakyThrows;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.ResultActions;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.Device;
@ -33,7 +28,7 @@ import org.thingsboard.server.common.data.HasTenantId;
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.id.EntityId;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@ -50,12 +45,8 @@ import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
import org.thingsboard.server.service.sync.importing.data.EntityImportResult;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Ignore
@DaoSqlTest
public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImportControllerTest {
@ -110,7 +101,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
assertThat(exportData.getEntity()).isEqualTo(asset);
logInAsTenantAdmin2();
EntityImportResult<Asset> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Asset> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, asset, tenantId2, importResult);
checkImportedAssetData(asset, importResult.getSavedEntity());
@ -122,7 +113,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
Asset asset = createAsset(tenantId1, null, "AB", "Asset v1.0");
EntityExportData<Asset> exportData = exportSingleEntity(asset.getId());
EntityImportResult<Asset> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Asset> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, asset, tenantId1, importResult);
checkImportedAssetData(asset, importResult.getSavedEntity());
@ -138,8 +129,8 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
EntityExportData<Asset> assetExportData = exportSingleEntity(asset.getId());
logInAsTenantAdmin2();
Customer importedCustomer = importEntities(List.of(customerExportData)).get(0).getSavedEntity();
Asset importedAsset = importEntities(List.of(assetExportData)).get(0).getSavedEntity();
Customer importedCustomer = importEntity(customerExportData).getSavedEntity();
Asset importedAsset = importEntity(assetExportData).getSavedEntity();
assertThat(importedAsset.getCustomerId()).isEqualTo(importedCustomer.getId());
}
@ -150,7 +141,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
Customer customer = createCustomer(tenantId1, "My customer");
Asset asset = createAsset(tenantId1, customer.getId(), "AB", "My asset");
Asset importedAsset = this.<Asset>importEntities(List.of(exportSingleEntity(asset.getId()))).get(0).getSavedEntity();
Asset importedAsset = importEntity(this.<Asset, AssetId>exportSingleEntity(asset.getId())).getSavedEntity();
assertThat(importedAsset.getCustomerId()).isEqualTo(asset.getCustomerId());
}
@ -171,7 +162,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
assertThat(exportData.getEntity()).isEqualTo(customer);
logInAsTenantAdmin2();
EntityImportResult<Customer> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Customer> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, customer, tenantId2, importResult);
checkImportedCustomerData(customer, importResult.getSavedEntity());
@ -183,7 +174,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
Customer customer = createCustomer(tenantAdmin1.getTenantId(), "Customer v1.0");
EntityExportData<Customer> exportData = exportSingleEntity(customer.getId());
EntityImportResult<Customer> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Customer> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, customer, tenantId1, importResult);
checkImportedCustomerData(customer, importResult.getSavedEntity());
@ -214,12 +205,12 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
exportedCredentials.setCredentialsId(credentials.getCredentialsId() + "a");
logInAsTenantAdmin2();
EntityImportResult<DeviceProfile> profileImportResult = importEntities(List.of(profileExportData)).get(0);
EntityImportResult<DeviceProfile> profileImportResult = importEntity(profileExportData);
checkImportedEntity(tenantId1, deviceProfile, tenantId2, profileImportResult);
checkImportedDeviceProfileData(deviceProfile, profileImportResult.getSavedEntity());
EntityImportResult<Device> deviceImportResult = importEntities(List.of(deviceExportData)).get(0);
EntityImportResult<Device> deviceImportResult = importEntity(deviceExportData);
Device importedDevice = deviceImportResult.getSavedEntity();
checkImportedEntity(tenantId1, device, tenantId2, deviceImportResult);
checkImportedDeviceData(device, importedDevice);
@ -242,7 +233,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
EntityExportData<Device> deviceExportData = exportSingleEntity(device.getId());
EntityImportResult<Device> importResult = importEntities(List.of(deviceExportData)).get(0);
EntityImportResult<Device> importResult = importEntity(deviceExportData);
Device importedDevice = importResult.getSavedEntity();
checkImportedEntity(tenantId1, device, tenantId1, importResult);
@ -277,7 +268,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
assertThat(((RuleChainExportData) exportData).getMetaData()).isEqualTo(metaData);
logInAsTenantAdmin2();
EntityImportResult<RuleChain> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<RuleChain> importResult = importEntity(exportData);
RuleChain importedRuleChain = importResult.getSavedEntity();
RuleChainMetaData importedMetaData = ruleChainService.loadRuleChainMetaData(tenantId2, importedRuleChain.getId());
@ -293,7 +284,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
EntityExportData<RuleChain> exportData = exportSingleEntity(ruleChain.getId());
EntityImportResult<RuleChain> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<RuleChain> importResult = importEntity(exportData);
RuleChain importedRuleChain = importResult.getSavedEntity();
RuleChainMetaData importedMetaData = ruleChainService.loadRuleChainMetaData(tenantId1, importedRuleChain.getId());
@ -330,7 +321,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
assertThat(exportData.getEntity()).isEqualTo(dashboard);
logInAsTenantAdmin2();
EntityImportResult<Dashboard> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Dashboard> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, dashboard, tenantId2, importResult);
checkImportedDashboardData(dashboard, importResult.getSavedEntity());
}
@ -342,7 +333,7 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
EntityImportResult<Dashboard> importResult = importEntities(List.of(exportData)).get(0);
EntityImportResult<Dashboard> importResult = importEntity(exportData);
checkImportedEntity(tenantId1, dashboard, tenantId1, importResult);
checkImportedDashboardData(dashboard, importResult.getSavedEntity());
}
@ -376,27 +367,6 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
}
@SneakyThrows
private <E extends ExportableEntity<? extends EntityId>> List<EntityImportResult<E>> importEntities(List<EntityExportData<E>> exportDataList) {
String requestJson = mapper.writerFor(new TypeReference<List<EntityExportData<E>>>() {}).writeValueAsString(exportDataList);
ResultActions resultActions = doPost("/api/entities/import", (Object) requestJson);
try {
String responseJson = resultActions.andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class,
mapper.getTypeFactory().constructParametricType(EntityImportResult.class, exportDataList.get(0).getEntity().getClass()));
return mapper.readValue(responseJson, type);
} catch (AssertionError e) {
throw new AssertionError(readResponse(resultActions, String.class), e);
}
}
private <E extends ExportableEntity<I>, I extends EntityId> EntityExportData<E> exportSingleEntity(I entityId) throws Exception {
return readResponse(doPost("/api/entities/export/" + entityId.getEntityType() + "/" + entityId.getId().toString())
.andExpect(status().isOk()), new TypeReference<EntityExportData<E>>() {});
}
private void logInAsTenantAdmin1() throws Exception {
login(tenantAdmin1.getEmail(), "12345678");
}

Loading…
Cancel
Save