Merge pull request #12905 from dashevchenko/resource_vc_fix
Version control: fixed resource restoring
This commit is contained in:
commit
51636229d1
@ -46,7 +46,7 @@ public class AssetImportService extends BaseEntityImportService<AssetId, Asset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Asset saveOrUpdate(EntitiesImportCtx ctx, Asset asset, EntityExportData<Asset> exportData, IdProvider idProvider) {
|
protected Asset saveOrUpdate(EntitiesImportCtx ctx, Asset asset, EntityExportData<Asset> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
Asset savedAsset = assetService.saveAsset(asset);
|
Asset savedAsset = assetService.saveAsset(asset);
|
||||||
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
||||||
importCalculatedFields(ctx, savedAsset, exportData, idProvider);
|
importCalculatedFields(ctx, savedAsset, exportData, idProvider);
|
||||||
|
|||||||
@ -49,7 +49,7 @@ public class AssetProfileImportService extends BaseEntityImportService<AssetProf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AssetProfile saveOrUpdate(EntitiesImportCtx ctx, AssetProfile assetProfile, EntityExportData<AssetProfile> exportData, IdProvider idProvider) {
|
protected AssetProfile saveOrUpdate(EntitiesImportCtx ctx, AssetProfile assetProfile, EntityExportData<AssetProfile> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
AssetProfile saved = assetProfileService.saveAssetProfile(assetProfile);
|
AssetProfile saved = assetProfileService.saveAssetProfile(assetProfile);
|
||||||
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
||||||
importCalculatedFields(ctx, saved, exportData, idProvider);
|
importCalculatedFields(ctx, saved, exportData, idProvider);
|
||||||
|
|||||||
@ -18,6 +18,8 @@ package org.thingsboard.server.service.sync.ie.importing.impl;
|
|||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.api.client.util.Objects;
|
import com.google.api.client.util.Objects;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -117,10 +119,10 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
|
|
||||||
E prepared = prepare(ctx, entity, existingEntity, exportData, idProvider);
|
E prepared = prepare(ctx, entity, existingEntity, exportData, idProvider);
|
||||||
|
|
||||||
boolean saveOrUpdate = existingEntity == null || compare(ctx, exportData, prepared, existingEntity);
|
CompareResult compareResult = compare(ctx, exportData, prepared, existingEntity);
|
||||||
|
|
||||||
if (saveOrUpdate) {
|
if (compareResult.isUpdateNeeded()) {
|
||||||
E savedEntity = saveOrUpdate(ctx, prepared, exportData, idProvider);
|
E savedEntity = saveOrUpdate(ctx, prepared, exportData, idProvider, compareResult);
|
||||||
boolean created = existingEntity == null;
|
boolean created = existingEntity == null;
|
||||||
importResult.setCreated(created);
|
importResult.setCreated(created);
|
||||||
importResult.setUpdated(!created);
|
importResult.setUpdated(!created);
|
||||||
@ -137,6 +139,17 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
return importResult;
|
return importResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
static class CompareResult {
|
||||||
|
private boolean updateNeeded;
|
||||||
|
private boolean externalIdChangedOnly;
|
||||||
|
|
||||||
|
public CompareResult(boolean updateNeeded) {
|
||||||
|
this.updateNeeded = updateNeeded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean updateRelatedEntitiesIfUnmodified(EntitiesImportCtx ctx, E prepared, D exportData, IdProvider idProvider) {
|
protected boolean updateRelatedEntitiesIfUnmodified(EntitiesImportCtx ctx, E prepared, D exportData, IdProvider idProvider) {
|
||||||
return importCalculatedFields(ctx, prepared, exportData, idProvider);
|
return importCalculatedFields(ctx, prepared, exportData, idProvider);
|
||||||
}
|
}
|
||||||
@ -148,18 +161,30 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
|
|
||||||
protected abstract E prepare(EntitiesImportCtx ctx, E entity, E oldEntity, D exportData, IdProvider idProvider);
|
protected abstract E prepare(EntitiesImportCtx ctx, E entity, E oldEntity, D exportData, IdProvider idProvider);
|
||||||
|
|
||||||
protected boolean compare(EntitiesImportCtx ctx, D exportData, E prepared, E existing) {
|
protected CompareResult compare(EntitiesImportCtx ctx, D exportData, E prepared, E existing) {
|
||||||
|
if (existing == null) {
|
||||||
|
log.debug("[{}] Found new entity.", prepared.getId());
|
||||||
|
return new CompareResult(true);
|
||||||
|
}
|
||||||
var newCopy = deepCopy(prepared);
|
var newCopy = deepCopy(prepared);
|
||||||
var existingCopy = deepCopy(existing);
|
var existingCopy = deepCopy(existing);
|
||||||
cleanupForComparison(newCopy);
|
cleanupForComparison(newCopy);
|
||||||
cleanupForComparison(existingCopy);
|
cleanupForComparison(existingCopy);
|
||||||
var result = !newCopy.equals(existingCopy);
|
var updateNeeded = isUpdateNeeded(ctx, exportData, newCopy, existingCopy);
|
||||||
if (result) {
|
boolean externalIdChangedOnly = false;
|
||||||
|
if (updateNeeded) {
|
||||||
log.debug("[{}] Found update.", prepared.getId());
|
log.debug("[{}] Found update.", prepared.getId());
|
||||||
log.debug("[{}] From: {}", prepared.getId(), newCopy);
|
log.debug("[{}] From: {}", prepared.getId(), newCopy);
|
||||||
log.debug("[{}] To: {}", prepared.getId(), existingCopy);
|
log.debug("[{}] To: {}", prepared.getId(), existingCopy);
|
||||||
|
cleanupExternalId(newCopy);
|
||||||
|
cleanupExternalId(existingCopy);
|
||||||
|
externalIdChangedOnly = newCopy.equals(existingCopy);
|
||||||
}
|
}
|
||||||
return result;
|
return new CompareResult(updateNeeded, externalIdChangedOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUpdateNeeded(EntitiesImportCtx ctx, D exportData, E prepared, E existing) {
|
||||||
|
return !prepared.equals(existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract E deepCopy(E e);
|
protected abstract E deepCopy(E e);
|
||||||
@ -172,7 +197,11 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract E saveOrUpdate(EntitiesImportCtx ctx, E entity, D exportData, IdProvider idProvider);
|
protected void cleanupExternalId(E e) {
|
||||||
|
e.setExternalId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract E saveOrUpdate(EntitiesImportCtx ctx, E entity, D exportData, IdProvider idProvider, CompareResult compareResult);
|
||||||
|
|
||||||
|
|
||||||
protected void processAfterSaved(EntitiesImportCtx ctx, EntityImportResult<E> importResult, D exportData, IdProvider idProvider) throws ThingsboardException {
|
protected void processAfterSaved(EntitiesImportCtx ctx, EntityImportResult<E> importResult, D exportData, IdProvider idProvider) throws ThingsboardException {
|
||||||
|
|||||||
@ -52,7 +52,7 @@ public class CustomerImportService extends BaseEntityImportService<CustomerId, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Customer saveOrUpdate(EntitiesImportCtx ctx, Customer customer, EntityExportData<Customer> exportData, IdProvider idProvider) {
|
protected Customer saveOrUpdate(EntitiesImportCtx ctx, Customer customer, EntityExportData<Customer> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
if (!customer.isPublic()) {
|
if (!customer.isPublic()) {
|
||||||
return customerService.saveCustomer(customer);
|
return customerService.saveCustomer(customer);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -75,7 +75,7 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dashboard saveOrUpdate(EntitiesImportCtx ctx, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
|
protected Dashboard saveOrUpdate(EntitiesImportCtx ctx, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
var tenantId = ctx.getTenantId();
|
var tenantId = ctx.getTenantId();
|
||||||
|
|
||||||
Set<ShortCustomerInfo> assignedCustomers = Optional.ofNullable(dashboard.getAssignedCustomers()).orElse(Collections.emptySet()).stream()
|
Set<ShortCustomerInfo> assignedCustomers = Optional.ofNullable(dashboard.getAssignedCustomers()).orElse(Collections.emptySet()).stream()
|
||||||
@ -116,8 +116,8 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean compare(EntitiesImportCtx ctx, EntityExportData<Dashboard> exportData, Dashboard prepared, Dashboard existing) {
|
protected boolean isUpdateNeeded(EntitiesImportCtx ctx, EntityExportData<Dashboard> exportData, Dashboard prepared, Dashboard existing) {
|
||||||
return super.compare(ctx, exportData, prepared, existing) || !prepared.getConfiguration().equals(existing.getConfiguration());
|
return super.isUpdateNeeded(ctx, exportData, prepared, existing) || !prepared.getConfiguration().equals(existing.getConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class DeviceImportService extends BaseEntityImportService<DeviceId, Devic
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Device saveOrUpdate(EntitiesImportCtx ctx, Device device, DeviceExportData exportData, IdProvider idProvider) {
|
protected Device saveOrUpdate(EntitiesImportCtx ctx, Device device, DeviceExportData exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
Device savedDevice;
|
Device savedDevice;
|
||||||
if (exportData.getCredentials() != null && ctx.isSaveCredentials()) {
|
if (exportData.getCredentials() != null && ctx.isSaveCredentials()) {
|
||||||
exportData.getCredentials().setId(null);
|
exportData.getCredentials().setId(null);
|
||||||
|
|||||||
@ -51,7 +51,7 @@ public class DeviceProfileImportService extends BaseEntityImportService<DevicePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DeviceProfile saveOrUpdate(EntitiesImportCtx ctx, DeviceProfile deviceProfile, EntityExportData<DeviceProfile> exportData, IdProvider idProvider) {
|
protected DeviceProfile saveOrUpdate(EntitiesImportCtx ctx, DeviceProfile deviceProfile, EntityExportData<DeviceProfile> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
DeviceProfile saved = deviceProfileService.saveDeviceProfile(deviceProfile);
|
DeviceProfile saved = deviceProfileService.saveDeviceProfile(deviceProfile);
|
||||||
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
||||||
importCalculatedFields(ctx, saved, exportData, idProvider);
|
importCalculatedFields(ctx, saved, exportData, idProvider);
|
||||||
|
|||||||
@ -55,7 +55,7 @@ public class EntityViewImportService extends BaseEntityImportService<EntityViewI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EntityView saveOrUpdate(EntitiesImportCtx ctx, EntityView entityView, EntityExportData<EntityView> exportData, IdProvider idProvider) {
|
protected EntityView saveOrUpdate(EntitiesImportCtx ctx, EntityView entityView, EntityExportData<EntityView> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
return entityViewService.saveEntityView(entityView);
|
return entityViewService.saveEntityView(entityView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -135,7 +135,7 @@ public class NotificationRuleImportService extends BaseEntityImportService<Notif
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NotificationRule saveOrUpdate(EntitiesImportCtx ctx, NotificationRule notificationRule, EntityExportData<NotificationRule> exportData, IdProvider idProvider) {
|
protected NotificationRule saveOrUpdate(EntitiesImportCtx ctx, NotificationRule notificationRule, EntityExportData<NotificationRule> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
ConstraintValidator.validateFields(notificationRule);
|
ConstraintValidator.validateFields(notificationRule);
|
||||||
return notificationRuleService.saveNotificationRule(ctx.getTenantId(), notificationRule);
|
return notificationRuleService.saveNotificationRule(ctx.getTenantId(), notificationRule);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ public class NotificationTargetImportService extends BaseEntityImportService<Not
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NotificationTarget saveOrUpdate(EntitiesImportCtx ctx, NotificationTarget notificationTarget, EntityExportData<NotificationTarget> exportData, IdProvider idProvider) {
|
protected NotificationTarget saveOrUpdate(EntitiesImportCtx ctx, NotificationTarget notificationTarget, EntityExportData<NotificationTarget> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
ConstraintValidator.validateFields(notificationTarget);
|
ConstraintValidator.validateFields(notificationTarget);
|
||||||
return notificationTargetService.saveNotificationTarget(ctx.getTenantId(), notificationTarget);
|
return notificationTargetService.saveNotificationTarget(ctx.getTenantId(), notificationTarget);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ public class NotificationTemplateImportService extends BaseEntityImportService<N
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NotificationTemplate saveOrUpdate(EntitiesImportCtx ctx, NotificationTemplate notificationTemplate, EntityExportData<NotificationTemplate> exportData, IdProvider idProvider) {
|
protected NotificationTemplate saveOrUpdate(EntitiesImportCtx ctx, NotificationTemplate notificationTemplate, EntityExportData<NotificationTemplate> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
ConstraintValidator.validateFields(notificationTemplate);
|
ConstraintValidator.validateFields(notificationTemplate);
|
||||||
return notificationTemplateService.saveNotificationTemplate(ctx.getTenantId(), notificationTemplate);
|
return notificationTemplateService.saveNotificationTemplate(ctx.getTenantId(), notificationTemplate);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,22 +57,30 @@ public class ResourceImportService extends BaseEntityImportService<TbResourceId,
|
|||||||
return existingResource;
|
return existingResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean compare(EntitiesImportCtx ctx, EntityExportData<TbResource> exportData, TbResource prepared, TbResource existing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TbResource deepCopy(TbResource resource) {
|
protected TbResource deepCopy(TbResource resource) {
|
||||||
return new TbResource(resource);
|
return new TbResource(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TbResource saveOrUpdate(EntitiesImportCtx ctx, TbResource resource, EntityExportData<TbResource> exportData, IdProvider idProvider) {
|
protected void cleanupForComparison(TbResource resource) {
|
||||||
|
super.cleanupForComparison(resource);
|
||||||
|
resource.setSearchText(null);
|
||||||
|
if (resource.getDescriptor().isNull()) {
|
||||||
|
resource.setDescriptor(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TbResource saveOrUpdate(EntitiesImportCtx ctx, TbResource resource, EntityExportData<TbResource> exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
if (resource.getResourceType() == ResourceType.IMAGE) {
|
if (resource.getResourceType() == ResourceType.IMAGE) {
|
||||||
return new TbResource(imageService.saveImage(resource));
|
return new TbResource(imageService.saveImage(resource));
|
||||||
} else {
|
} else {
|
||||||
resource = resourceService.saveResource(resource);
|
if (compareResult.isExternalIdChangedOnly()) {
|
||||||
|
resource = resourceService.saveResource(resource, false);
|
||||||
|
} else {
|
||||||
|
resource = resourceService.saveResource(resource);
|
||||||
|
}
|
||||||
resource.setData(null);
|
resource.setData(null);
|
||||||
resource.setPreview(null);
|
resource.setPreview(null);
|
||||||
return resource;
|
return resource;
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package org.thingsboard.server.service.sync.ie.importing.impl;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
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.EntityType;
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.audit.ActionType;
|
import org.thingsboard.server.common.data.audit.ActionType;
|
||||||
@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId;
|
|||||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||||
|
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||||
import org.thingsboard.server.common.data.sync.ie.RuleChainExportData;
|
import org.thingsboard.server.common.data.sync.ie.RuleChainExportData;
|
||||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||||
import org.thingsboard.server.dao.rule.RuleNodeDao;
|
import org.thingsboard.server.dao.rule.RuleNodeDao;
|
||||||
@ -103,7 +105,7 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RuleChain saveOrUpdate(EntitiesImportCtx ctx, RuleChain ruleChain, RuleChainExportData exportData, IdProvider idProvider) {
|
protected RuleChain saveOrUpdate(EntitiesImportCtx ctx, RuleChain ruleChain, RuleChainExportData exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
ruleChain = ruleChainService.saveRuleChain(ruleChain);
|
ruleChain = ruleChainService.saveRuleChain(ruleChain);
|
||||||
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
if (ctx.isFinalImportAttempt() || ctx.getCurrentImportResult().isUpdatedAllExternalIds()) {
|
||||||
exportData.getMetaData().setRuleChainId(ruleChain.getId());
|
exportData.getMetaData().setRuleChainId(ruleChain.getId());
|
||||||
@ -115,15 +117,15 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean compare(EntitiesImportCtx ctx, RuleChainExportData exportData, RuleChain prepared, RuleChain existing) {
|
protected boolean isUpdateNeeded(EntitiesImportCtx ctx, RuleChainExportData exportData, RuleChain prepared, RuleChain existing) {
|
||||||
boolean different = super.compare(ctx, exportData, prepared, existing);
|
boolean updateNeeded = super.isUpdateNeeded(ctx, exportData, prepared, existing);
|
||||||
if (!different) {
|
if (!updateNeeded) {
|
||||||
RuleChainMetaData newMD = exportData.getMetaData();
|
RuleChainMetaData newMD = exportData.getMetaData();
|
||||||
RuleChainMetaData existingMD = ruleChainService.loadRuleChainMetaData(ctx.getTenantId(), prepared.getId());
|
RuleChainMetaData existingMD = ruleChainService.loadRuleChainMetaData(ctx.getTenantId(), prepared.getId());
|
||||||
existingMD.setRuleChainId(null);
|
existingMD.setRuleChainId(null);
|
||||||
different = !newMD.equals(existingMD);
|
updateNeeded = !newMD.equals(existingMD);
|
||||||
}
|
}
|
||||||
return different;
|
return updateNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -44,13 +44,13 @@ public class WidgetTypeImportService extends BaseEntityImportService<WidgetTypeI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WidgetTypeDetails saveOrUpdate(EntitiesImportCtx ctx, WidgetTypeDetails widgetsBundle, WidgetTypeExportData exportData, IdProvider idProvider) {
|
protected WidgetTypeDetails saveOrUpdate(EntitiesImportCtx ctx, WidgetTypeDetails widgetsBundle, WidgetTypeExportData exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
return widgetTypeService.saveWidgetType(widgetsBundle);
|
return widgetTypeService.saveWidgetType(widgetsBundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean compare(EntitiesImportCtx ctx, WidgetTypeExportData exportData, WidgetTypeDetails prepared, WidgetTypeDetails existing) {
|
protected CompareResult compare(EntitiesImportCtx ctx, WidgetTypeExportData exportData, WidgetTypeDetails prepared, WidgetTypeDetails existing) {
|
||||||
return true;
|
return new CompareResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -49,7 +49,7 @@ public class WidgetsBundleImportService extends BaseEntityImportService<WidgetsB
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WidgetsBundle saveOrUpdate(EntitiesImportCtx ctx, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, IdProvider idProvider) {
|
protected WidgetsBundle saveOrUpdate(EntitiesImportCtx ctx, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, IdProvider idProvider, CompareResult compareResult) {
|
||||||
if (CollectionsUtil.isNotEmpty(exportData.getWidgets())) {
|
if (CollectionsUtil.isNotEmpty(exportData.getWidgets())) {
|
||||||
exportData.getWidgets().forEach(widgetTypeNode -> {
|
exportData.getWidgets().forEach(widgetTypeNode -> {
|
||||||
String bundleAlias = widgetTypeNode.remove("bundleAlias").asText();
|
String bundleAlias = widgetTypeNode.remove("bundleAlias").asText();
|
||||||
@ -75,8 +75,8 @@ public class WidgetsBundleImportService extends BaseEntityImportService<WidgetsB
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean compare(EntitiesImportCtx ctx, WidgetsBundleExportData exportData, WidgetsBundle prepared, WidgetsBundle existing) {
|
protected CompareResult compare(EntitiesImportCtx ctx, WidgetsBundleExportData exportData, WidgetsBundle prepared, WidgetsBundle existing) {
|
||||||
return true;
|
return new CompareResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -454,7 +454,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
private VersionLoadResult onError(EntityId externalId, Throwable e) {
|
private VersionLoadResult onError(EntityId externalId, Throwable e) {
|
||||||
return analyze(e, externalId).orElse(VersionLoadResult.error(EntityLoadError.runtimeError(e)));
|
return analyze(e, externalId).orElse(VersionLoadResult.error(EntityLoadError.runtimeError(e, externalId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<VersionLoadResult> analyze(Throwable e, EntityId externalId) {
|
private Optional<VersionLoadResult> analyze(Throwable e, EntityId externalId) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -40,6 +40,9 @@ import org.thingsboard.server.common.data.EntityView;
|
|||||||
import org.thingsboard.server.common.data.ExportableEntity;
|
import org.thingsboard.server.common.data.ExportableEntity;
|
||||||
import org.thingsboard.server.common.data.HasTenantId;
|
import org.thingsboard.server.common.data.HasTenantId;
|
||||||
import org.thingsboard.server.common.data.OtaPackage;
|
import org.thingsboard.server.common.data.OtaPackage;
|
||||||
|
import org.thingsboard.server.common.data.ResourceType;
|
||||||
|
import org.thingsboard.server.common.data.TbResource;
|
||||||
|
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
@ -113,6 +116,8 @@ import java.util.stream.Collectors;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
import static org.thingsboard.server.controller.TbResourceControllerTest.TEST_DATA;
|
||||||
|
import static org.thingsboard.server.controller.TbResourceControllerTest.JS_TEST_FILE_NAME;
|
||||||
|
|
||||||
@DaoSqlTest
|
@DaoSqlTest
|
||||||
public class VersionControlTest extends AbstractControllerTest {
|
public class VersionControlTest extends AbstractControllerTest {
|
||||||
@ -648,6 +653,26 @@ public class VersionControlTest extends AbstractControllerTest {
|
|||||||
assertThat(importedCalculatedField.getType()).isEqualTo(calculatedField.getType());
|
assertThat(importedCalculatedField.getType()).isEqualTo(calculatedField.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceVc_sameTenant() throws Exception {
|
||||||
|
TbResourceInfo resourceInfo = createResource("Test resource");
|
||||||
|
String versionId = createVersion("resources", EntityType.TB_RESOURCE);
|
||||||
|
|
||||||
|
TbResource resource = findResource(resourceInfo.getName());
|
||||||
|
|
||||||
|
loadVersion(versionId, EntityType.TB_RESOURCE);
|
||||||
|
TbResource importedResource = findResource(resource.getName());
|
||||||
|
checkImportedEntity(tenantId1, resource, tenantId1, importedResource);
|
||||||
|
checkImportedResourceData(resource, importedResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkImportedResourceData(TbResource resource, TbResource importedResource) {
|
||||||
|
assertThat(importedResource.getName()).isEqualTo(resource.getName());
|
||||||
|
assertThat(importedResource.getData()).isEqualTo(resource.getData());
|
||||||
|
assertThat(importedResource.getResourceKey()).isEqualTo(resource.getResourceKey());
|
||||||
|
assertThat(importedResource.getResourceType()).isEqualTo(resource.getResourceType());
|
||||||
|
}
|
||||||
|
|
||||||
private <E extends ExportableEntity<?> & HasTenantId> void checkImportedEntity(TenantId tenantId1, E initialEntity, TenantId tenantId2, E importedEntity) {
|
private <E extends ExportableEntity<?> & HasTenantId> void checkImportedEntity(TenantId tenantId1, E initialEntity, TenantId tenantId2, E importedEntity) {
|
||||||
assertThat(initialEntity.getTenantId()).isEqualTo(tenantId1);
|
assertThat(initialEntity.getTenantId()).isEqualTo(tenantId1);
|
||||||
assertThat(importedEntity.getTenantId()).isEqualTo(tenantId2);
|
assertThat(importedEntity.getTenantId()).isEqualTo(tenantId2);
|
||||||
@ -1128,4 +1153,22 @@ public class VersionControlTest extends AbstractControllerTest {
|
|||||||
return doGetTypedWithPageLink("/api/" + entityId.getEntityType() + "/" + entityId.getId() + "/calculatedFields?", new TypeReference<PageData<CalculatedField>>() {}, new PageLink(100, 0)).getData();
|
return doGetTypedWithPageLink("/api/" + entityId.getEntityType() + "/" + entityId.getId() + "/calculatedFields?", new TypeReference<PageData<CalculatedField>>() {}, new PageLink(100, 0)).getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TbResourceInfo createResource(String name) {
|
||||||
|
TbResource resource = new TbResource();
|
||||||
|
resource.setResourceType(ResourceType.JKS);
|
||||||
|
resource.setTitle(name);
|
||||||
|
resource.setFileName(JS_TEST_FILE_NAME);
|
||||||
|
resource.setEncodedData(TEST_DATA);
|
||||||
|
|
||||||
|
return saveTbResource(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TbResourceInfo saveTbResource(TbResource tbResource) {
|
||||||
|
return doPost("/api/resource", tbResource, TbResourceInfo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TbResource findResource(String name) throws Exception {
|
||||||
|
return doGetTypedWithPageLink("/api/resource?", new TypeReference<PageData<TbResource>>() {}, new PageLink(100, 0, name)).getData().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,11 +45,15 @@ public class EntityLoadError implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static EntityLoadError runtimeError(Throwable e) {
|
public static EntityLoadError runtimeError(Throwable e) {
|
||||||
|
return runtimeError(e, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityLoadError runtimeError(Throwable e, EntityId externalId) {
|
||||||
String message = e.getMessage();
|
String message = e.getMessage();
|
||||||
if (StringUtils.isEmpty(message)) {
|
if (StringUtils.isEmpty(message)) {
|
||||||
message = "unexpected error (" + ClassUtils.getShortClassName(e.getClass()) + ")";
|
message = "unexpected error (" + ClassUtils.getShortClassName(e.getClass()) + ")";
|
||||||
}
|
}
|
||||||
return EntityLoadError.builder().type("RUNTIME").message(message).build();
|
return EntityLoadError.builder().type("RUNTIME").message(message).source(externalId).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user