@ -43,6 +43,15 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset ;
import org.thingsboard.server.common.data.asset.Asset ;
import org.thingsboard.server.common.data.asset.AssetProfile ;
import org.thingsboard.server.common.data.asset.AssetProfile ;
import org.thingsboard.server.common.data.audit.ActionType ;
import org.thingsboard.server.common.data.audit.ActionType ;
import org.thingsboard.server.common.data.cf.CalculatedField ;
import org.thingsboard.server.common.data.cf.CalculatedFieldType ;
import org.thingsboard.server.common.data.cf.configuration.Argument ;
import org.thingsboard.server.common.data.cf.configuration.ArgumentType ;
import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration ;
import org.thingsboard.server.common.data.cf.configuration.Output ;
import org.thingsboard.server.common.data.cf.configuration.OutputType ;
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey ;
import org.thingsboard.server.common.data.cf.configuration.SimpleCalculatedFieldConfiguration ;
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration ;
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration ;
import org.thingsboard.server.common.data.device.data.DeviceData ;
import org.thingsboard.server.common.data.device.data.DeviceData ;
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration ;
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration ;
@ -70,6 +79,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType ;
import org.thingsboard.server.common.data.rule.RuleChainType ;
import org.thingsboard.server.common.data.rule.RuleNode ;
import org.thingsboard.server.common.data.rule.RuleNode ;
import org.thingsboard.server.common.data.security.Authority ;
import org.thingsboard.server.common.data.security.Authority ;
import org.thingsboard.server.common.data.sync.ie.DeviceExportData ;
import org.thingsboard.server.common.data.sync.ie.EntityExportData ;
import org.thingsboard.server.common.data.sync.ie.EntityExportData ;
import org.thingsboard.server.common.data.sync.ie.EntityExportSettings ;
import org.thingsboard.server.common.data.sync.ie.EntityExportSettings ;
import org.thingsboard.server.common.data.sync.ie.EntityImportResult ;
import org.thingsboard.server.common.data.sync.ie.EntityImportResult ;
@ -79,6 +89,7 @@ import org.thingsboard.server.common.data.util.ThrowingRunnable;
import org.thingsboard.server.controller.AbstractControllerTest ;
import org.thingsboard.server.controller.AbstractControllerTest ;
import org.thingsboard.server.dao.asset.AssetProfileService ;
import org.thingsboard.server.dao.asset.AssetProfileService ;
import org.thingsboard.server.dao.asset.AssetService ;
import org.thingsboard.server.dao.asset.AssetService ;
import org.thingsboard.server.dao.cf.CalculatedFieldService ;
import org.thingsboard.server.dao.customer.CustomerService ;
import org.thingsboard.server.dao.customer.CustomerService ;
import org.thingsboard.server.dao.dashboard.DashboardService ;
import org.thingsboard.server.dao.dashboard.DashboardService ;
import org.thingsboard.server.dao.device.DeviceProfileService ;
import org.thingsboard.server.dao.device.DeviceProfileService ;
@ -145,6 +156,8 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
protected TenantService tenantService ;
protected TenantService tenantService ;
@Autowired
@Autowired
protected EntityViewService entityViewService ;
protected EntityViewService entityViewService ;
@Autowired
protected CalculatedFieldService calculatedFieldService ;
protected TenantId tenantId1 ;
protected TenantId tenantId1 ;
protected User tenantAdmin1 ;
protected User tenantAdmin1 ;
@ -191,6 +204,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
Asset asset = createAsset ( tenantId1 , null , assetProfile . getId ( ) , "Asset 1" ) ;
Asset asset = createAsset ( tenantId1 , null , assetProfile . getId ( ) , "Asset 1" ) ;
DeviceProfile deviceProfile = createDeviceProfile ( tenantId1 , ruleChain . getId ( ) , dashboard . getId ( ) , "Device profile 1" ) ;
DeviceProfile deviceProfile = createDeviceProfile ( tenantId1 , ruleChain . getId ( ) , dashboard . getId ( ) , "Device profile 1" ) ;
Device device = createDevice ( tenantId1 , null , deviceProfile . getId ( ) , "Device 1" ) ;
Device device = createDevice ( tenantId1 , null , deviceProfile . getId ( ) , "Device 1" ) ;
CalculatedField calculatedField = createCalculatedField ( tenantId1 , device . getId ( ) , asset . getId ( ) ) ;
Map < EntityType , EntityExportData > entitiesExportData = Stream . of ( customer . getId ( ) , asset . getId ( ) , device . getId ( ) ,
Map < EntityType , EntityExportData > entitiesExportData = Stream . of ( customer . getId ( ) , asset . getId ( ) , device . getId ( ) ,
ruleChain . getId ( ) , dashboard . getId ( ) , assetProfile . getId ( ) , deviceProfile . getId ( ) )
ruleChain . getId ( ) , dashboard . getId ( ) , assetProfile . getId ( ) , deviceProfile . getId ( ) )
@ -198,6 +212,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
try {
try {
return exportEntity ( tenantAdmin1 , entityId , EntityExportSettings . builder ( )
return exportEntity ( tenantAdmin1 , entityId , EntityExportSettings . builder ( )
. exportCredentials ( false )
. exportCredentials ( false )
. exportCalculatedFields ( true )
. build ( ) ) ;
. build ( ) ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
throw new RuntimeException ( e ) ;
throw new RuntimeException ( e ) ;
@ -245,7 +260,6 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
verify ( entityActionService , Mockito . never ( ) ) . logEntityAction ( any ( ) , eq ( importedAsset . getId ( ) ) , eq ( importedAsset ) ,
verify ( entityActionService , Mockito . never ( ) ) . logEntityAction ( any ( ) , eq ( importedAsset . getId ( ) ) , eq ( importedAsset ) ,
any ( ) , eq ( ActionType . UPDATED ) , isNull ( ) ) ;
any ( ) , eq ( ActionType . UPDATED ) , isNull ( ) ) ;
EntityExportData < Asset > updatedAssetEntity = getAndClone ( entitiesExportData , EntityType . ASSET ) ;
EntityExportData < Asset > updatedAssetEntity = getAndClone ( entitiesExportData , EntityType . ASSET ) ;
updatedAssetEntity . getEntity ( ) . setLabel ( "t" + updatedAssetEntity . getEntity ( ) . getLabel ( ) ) ;
updatedAssetEntity . getEntity ( ) . setLabel ( "t" + updatedAssetEntity . getEntity ( ) . getLabel ( ) ) ;
Asset updatedAsset = importEntity ( tenantAdmin2 , updatedAssetEntity ) . getSavedEntity ( ) ;
Asset updatedAsset = importEntity ( tenantAdmin2 , updatedAssetEntity ) . getSavedEntity ( ) ;
@ -268,10 +282,27 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
importEntity ( tenantAdmin2 , getAndClone ( entitiesExportData , EntityType . DEVICE ) ) ;
importEntity ( tenantAdmin2 , getAndClone ( entitiesExportData , EntityType . DEVICE ) ) ;
verify ( tbClusterService , Mockito . never ( ) ) . onDeviceUpdated ( eq ( importedDevice ) , eq ( importedDevice ) ) ;
verify ( tbClusterService , Mockito . never ( ) ) . onDeviceUpdated ( eq ( importedDevice ) , eq ( importedDevice ) ) ;
// calculated field of imported device:
List < CalculatedField > calculatedFields = calculatedFieldService . findCalculatedFieldsByEntityId ( tenantId2 , importedDevice . getId ( ) ) ;
assertThat ( calculatedFields . size ( ) ) . isOne ( ) ;
var importedCalculatedField = calculatedFields . get ( 0 ) ;
assertThat ( importedCalculatedField . getName ( ) ) . isEqualTo ( calculatedField . getName ( ) ) ;
verify ( tbClusterService ) . onCalculatedFieldUpdated ( eq ( importedCalculatedField ) , isNull ( ) , any ( ) ) ;
EntityExportData < Device > updatedDeviceEntity = getAndClone ( entitiesExportData , EntityType . DEVICE ) ;
EntityExportData < Device > updatedDeviceEntity = getAndClone ( entitiesExportData , EntityType . DEVICE ) ;
updatedDeviceEntity . getEntity ( ) . setLabel ( "t" + updatedDeviceEntity . getEntity ( ) . getLabel ( ) ) ;
updatedDeviceEntity . getEntity ( ) . setLabel ( "t" + updatedDeviceEntity . getEntity ( ) . getLabel ( ) ) ;
Device updatedDevice = importEntity ( tenantAdmin2 , updatedDeviceEntity ) . getSavedEntity ( ) ;
Device updatedDevice = importEntity ( tenantAdmin2 , updatedDeviceEntity ) . getSavedEntity ( ) ;
verify ( tbClusterService ) . onDeviceUpdated ( eq ( updatedDevice ) , eq ( importedDevice ) ) ;
verify ( tbClusterService ) . onDeviceUpdated ( eq ( updatedDevice ) , eq ( importedDevice ) ) ;
// update calculated field:
DeviceExportData deviceExportData = ( DeviceExportData ) getAndClone ( entitiesExportData , EntityType . DEVICE ) ;
deviceExportData . setCalculatedFields ( deviceExportData . getCalculatedFields ( ) . stream ( ) . peek ( field - > field . setName ( "t_" + field . getName ( ) ) ) . toList ( ) ) ;
importEntity ( tenantAdmin2 , deviceExportData ) . getSavedEntity ( ) ;
calculatedFields = calculatedFieldService . findCalculatedFieldsByEntityId ( tenantId2 , importedDevice . getId ( ) ) ;
assertThat ( calculatedFields . size ( ) ) . isOne ( ) ;
importedCalculatedField = calculatedFields . get ( 0 ) ;
assertThat ( importedCalculatedField . getName ( ) ) . startsWith ( "t_" ) ;
}
}
@Test
@Test
@ -290,12 +321,15 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
Device device = createDevice ( tenantId1 , customer . getId ( ) , deviceProfile . getId ( ) , "Device 1" ) ;
Device device = createDevice ( tenantId1 , customer . getId ( ) , deviceProfile . getId ( ) , "Device 1" ) ;
EntityView entityView = createEntityView ( tenantId1 , customer . getId ( ) , device . getId ( ) , "Entity view 1" ) ;
EntityView entityView = createEntityView ( tenantId1 , customer . getId ( ) , device . getId ( ) , "Entity view 1" ) ;
CalculatedField calculatedField = createCalculatedField ( tenantId1 , device . getId ( ) , device . getId ( ) ) ;
Map < EntityId , EntityId > ids = new HashMap < > ( ) ;
Map < EntityId , EntityId > ids = new HashMap < > ( ) ;
for ( EntityId entityId : List . of ( customer . getId ( ) , ruleChain . getId ( ) , dashboard . getId ( ) , assetProfile . getId ( ) , asset . getId ( ) ,
for ( EntityId entityId : List . of ( customer . getId ( ) , ruleChain . getId ( ) , dashboard . getId ( ) , assetProfile . getId ( ) , asset . getId ( ) ,
deviceProfile . getId ( ) , device . getId ( ) , entityView . getId ( ) , ruleChain . getId ( ) , dashboard . getId ( ) ) ) {
deviceProfile . getId ( ) , device . getId ( ) , entityView . getId ( ) , ruleChain . getId ( ) , dashboard . getId ( ) ) ) {
EntityExportData exportData = exportEntity ( getSecurityUser ( tenantAdmin1 ) , entityId ) ;
EntityExportData exportData = exportEntity ( getSecurityUser ( tenantAdmin1 ) , entityId ) ;
EntityImportResult importResult = importEntity ( getSecurityUser ( tenantAdmin2 ) , exportData , EntityImportSettings . builder ( )
EntityImportResult importResult = importEntity ( getSecurityUser ( tenantAdmin2 ) , exportData , EntityImportSettings . builder ( )
. saveCredentials ( false )
. saveCredentials ( false )
. saveCalculatedFields ( true )
. build ( ) ) ;
. build ( ) ) ;
ids . put ( entityId , ( EntityId ) importResult . getSavedEntity ( ) . getId ( ) ) ;
ids . put ( entityId , ( EntityId ) importResult . getSavedEntity ( ) . getId ( ) ) ;
}
}
@ -325,10 +359,16 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
assertThat ( exportedDeviceProfile . getDefaultRuleChainId ( ) ) . isEqualTo ( ruleChain . getId ( ) ) ;
assertThat ( exportedDeviceProfile . getDefaultRuleChainId ( ) ) . isEqualTo ( ruleChain . getId ( ) ) ;
assertThat ( exportedDeviceProfile . getDefaultDashboardId ( ) ) . isEqualTo ( dashboard . getId ( ) ) ;
assertThat ( exportedDeviceProfile . getDefaultDashboardId ( ) ) . isEqualTo ( dashboard . getId ( ) ) ;
Device exportedDevice = ( Device ) exportEntity ( tenantAdmin2 , ( DeviceId ) ids . get ( device . getId ( ) ) ) . getEntity ( ) ;
EntityExportData < Device > entityExportData = exportEntity ( tenantAdmin2 , ( DeviceId ) ids . get ( device . getId ( ) ) ) ;
Device exportedDevice = entityExportData . getEntity ( ) ;
assertThat ( exportedDevice . getCustomerId ( ) ) . isEqualTo ( customer . getId ( ) ) ;
assertThat ( exportedDevice . getCustomerId ( ) ) . isEqualTo ( customer . getId ( ) ) ;
assertThat ( exportedDevice . getDeviceProfileId ( ) ) . isEqualTo ( deviceProfile . getId ( ) ) ;
assertThat ( exportedDevice . getDeviceProfileId ( ) ) . isEqualTo ( deviceProfile . getId ( ) ) ;
List < CalculatedField > calculatedFields = ( ( DeviceExportData ) entityExportData ) . getCalculatedFields ( ) ;
assertThat ( calculatedFields . size ( ) ) . isOne ( ) ;
CalculatedField field = calculatedFields . get ( 0 ) ;
assertThat ( field . getName ( ) ) . isEqualTo ( calculatedField . getName ( ) ) ;
EntityView exportedEntityView = ( EntityView ) exportEntity ( tenantAdmin2 , ( EntityViewId ) ids . get ( entityView . getId ( ) ) ) . getEntity ( ) ;
EntityView exportedEntityView = ( EntityView ) exportEntity ( tenantAdmin2 , ( EntityViewId ) ids . get ( entityView . getId ( ) ) ) . getEntity ( ) ;
assertThat ( exportedEntityView . getCustomerId ( ) ) . isEqualTo ( customer . getId ( ) ) ;
assertThat ( exportedEntityView . getCustomerId ( ) ) . isEqualTo ( customer . getId ( ) ) ;
assertThat ( exportedEntityView . getEntityId ( ) ) . isEqualTo ( device . getId ( ) ) ;
assertThat ( exportedEntityView . getEntityId ( ) ) . isEqualTo ( device . getId ( ) ) ;
@ -340,7 +380,6 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
deviceProfileService . saveDeviceProfile ( importedDeviceProfile ) ;
deviceProfileService . saveDeviceProfile ( importedDeviceProfile ) ;
}
}
protected Device createDevice ( TenantId tenantId , CustomerId customerId , DeviceProfileId deviceProfileId , String name ) {
protected Device createDevice ( TenantId tenantId , CustomerId customerId , DeviceProfileId deviceProfileId , String name ) {
Device device = new Device ( ) ;
Device device = new Device ( ) ;
device . setTenantId ( tenantId ) ;
device . setTenantId ( tenantId ) ;
@ -549,9 +588,43 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
return relation ;
return relation ;
}
}
private CalculatedField createCalculatedField ( TenantId tenantId , EntityId entityId , EntityId referencedEntityId ) {
CalculatedField calculatedField = new CalculatedField ( ) ;
calculatedField . setTenantId ( tenantId ) ;
calculatedField . setEntityId ( entityId ) ;
calculatedField . setType ( CalculatedFieldType . SIMPLE ) ;
calculatedField . setName ( "Test Calculated Field" ) ;
calculatedField . setConfigurationVersion ( 1 ) ;
calculatedField . setConfiguration ( getCalculatedFieldConfig ( referencedEntityId ) ) ;
calculatedField . setVersion ( 1L ) ;
return calculatedFieldService . save ( calculatedField ) ;
}
private CalculatedFieldConfiguration getCalculatedFieldConfig ( EntityId referencedEntityId ) {
SimpleCalculatedFieldConfiguration config = new SimpleCalculatedFieldConfiguration ( ) ;
Argument argument = new Argument ( ) ;
argument . setRefEntityId ( referencedEntityId ) ;
ReferencedEntityKey refEntityKey = new ReferencedEntityKey ( "temperature" , ArgumentType . TS_LATEST , null ) ;
argument . setRefEntityKey ( refEntityKey ) ;
config . setArguments ( Map . of ( "T" , argument ) ) ;
config . setExpression ( "T - (100 - H) / 5" ) ;
Output output = new Output ( ) ;
output . setName ( "output" ) ;
output . setType ( OutputType . TIME_SERIES ) ;
config . setOutput ( output ) ;
return config ;
}
protected < E extends ExportableEntity < I > , I extends EntityId > EntityExportData < E > exportEntity ( User user , I entityId ) throws Exception {
protected < E extends ExportableEntity < I > , I extends EntityId > EntityExportData < E > exportEntity ( User user , I entityId ) throws Exception {
return exportEntity ( user , entityId , EntityExportSettings . builder ( )
return exportEntity ( user , entityId , EntityExportSettings . builder ( )
. exportCredentials ( true )
. exportCredentials ( true )
. exportCalculatedFields ( true )
. build ( ) ) ;
. build ( ) ) ;
}
}
@ -562,6 +635,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
protected < E extends ExportableEntity < I > , I extends EntityId > EntityImportResult < E > importEntity ( User user , EntityExportData < E > exportData ) throws Exception {
protected < E extends ExportableEntity < I > , I extends EntityId > EntityImportResult < E > importEntity ( User user , EntityExportData < E > exportData ) throws Exception {
return importEntity ( user , exportData , EntityImportSettings . builder ( )
return importEntity ( user , exportData , EntityImportSettings . builder ( )
. saveCredentials ( true )
. saveCredentials ( true )
. saveCalculatedFields ( true )
. build ( ) ) ;
. build ( ) ) ;
}
}