added uniquifyStrategy
This commit is contained in:
parent
7b8120fa1b
commit
f1da967a7d
@ -47,5 +47,3 @@ WHERE NOT (
|
|||||||
|
|
||||||
-- UPDATE TENANT PROFILE CONFIGURATION END
|
-- UPDATE TENANT PROFILE CONFIGURATION END
|
||||||
|
|
||||||
ALTER TABLE entity_view ADD CONSTRAINT entity_view_name_unq_key UNIQUE (tenant_id, name);
|
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.Customer;
|
|||||||
import org.thingsboard.server.common.data.EntitySubtype;
|
import org.thingsboard.server.common.data.EntitySubtype;
|
||||||
import org.thingsboard.server.common.data.NameConflictPolicy;
|
import org.thingsboard.server.common.data.NameConflictPolicy;
|
||||||
import org.thingsboard.server.common.data.NameConflictStrategy;
|
import org.thingsboard.server.common.data.NameConflictStrategy;
|
||||||
|
import org.thingsboard.server.common.data.UniquifyStrategy;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.asset.AssetInfo;
|
import org.thingsboard.server.common.data.asset.AssetInfo;
|
||||||
import org.thingsboard.server.common.data.asset.AssetSearchQuery;
|
import org.thingsboard.server.common.data.asset.AssetSearchQuery;
|
||||||
@ -79,7 +80,7 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARA
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_SEPARATOR_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_SEPARATOR_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
||||||
@ -87,6 +88,7 @@ import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_D
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
||||||
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_STRATEGY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
||||||
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
||||||
|
|
||||||
@ -143,12 +145,14 @@ public class AssetController extends BaseController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Asset saveAsset(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the asset.") @RequestBody Asset asset,
|
public Asset saveAsset(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the asset.") @RequestBody Asset asset,
|
||||||
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
||||||
@RequestParam(name = "policy", defaultValue = "FAIL") NameConflictPolicy policy,
|
@RequestParam(name = "nameConflictPolicy", defaultValue = "FAIL") NameConflictPolicy nameConflictPolicy,
|
||||||
@Parameter(description = NAME_CONFLICT_SEPARATOR_DESC)
|
@Parameter(description = UNIQUIFY_SEPARATOR_DESC)
|
||||||
@RequestParam(name = "separator", defaultValue = "_") String separator) throws Exception {
|
@RequestParam(name = "uniquifySeparator", defaultValue = "_") String uniquifySeparator,
|
||||||
|
@Parameter(description = UNIQUIFY_STRATEGY_DESC)
|
||||||
|
@RequestParam(name = "uniquifyStrategy", defaultValue = "RANDOM") UniquifyStrategy uniquifyStrategy) throws Exception {
|
||||||
asset.setTenantId(getTenantId());
|
asset.setTenantId(getTenantId());
|
||||||
checkEntity(asset.getId(), asset, Resource.ASSET);
|
checkEntity(asset.getId(), asset, Resource.ASSET);
|
||||||
return tbAssetService.save(asset, new NameConflictStrategy(policy, separator), getCurrentUser());
|
return tbAssetService.save(asset, new NameConflictStrategy(nameConflictPolicy, uniquifySeparator, uniquifyStrategy), getCurrentUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Delete asset (deleteAsset)",
|
@ApiOperation(value = "Delete asset (deleteAsset)",
|
||||||
|
|||||||
@ -1749,7 +1749,12 @@ public class ControllerConstants {
|
|||||||
" If omitted, FAIL policy is applied. FAIL policy implies exception will be thrown if an entity with the same name already exists. " +
|
" If omitted, FAIL policy is applied. FAIL policy implies exception will be thrown if an entity with the same name already exists. " +
|
||||||
" UNIQUIFY policy appends a suffix to the entity name, if a name conflict occurs.";
|
" UNIQUIFY policy appends a suffix to the entity name, if a name conflict occurs.";
|
||||||
|
|
||||||
public static final String NAME_CONFLICT_SEPARATOR_DESC = "Optional value of name suffix separator used by UNIQUIFY policy. By default, underscore separator is used. " +
|
public static final String UNIQUIFY_SEPARATOR_DESC = "Optional value of name suffix separator used by UNIQUIFY policy. By default, underscore separator is used. " +
|
||||||
"For example, strategy is UNIQUIFY, separator is '-'; if a name conflict occurs for entity name 'test-name', " +
|
"For example, strategy is UNIQUIFY, separator is '-'; if a name conflict occurs for entity name 'test-name', " +
|
||||||
"created entity will have name like 'test-name-7fsh4f'.";
|
"created entity will have name like 'test-name-7fsh4f'.";
|
||||||
|
|
||||||
|
public static final String UNIQUIFY_STRATEGY_DESC = "Optional value of uniquify strategy used by UNIQUIFY policy. Possible values: RANDOM or INCREMENTAL. " +
|
||||||
|
"By default, RANDOM strategy is used, which means random alphanumeric string will be added as a suffix to entity name. " +
|
||||||
|
"For example, strategy is UNIQUIFY, uniquify strategy is INCREMENTAL; if a name conflict occurs for entity name 'test-name', " +
|
||||||
|
"created entity will have name like 'test-name-1.";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import org.thingsboard.common.util.JacksonUtil;
|
|||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.NameConflictStrategy;
|
import org.thingsboard.server.common.data.NameConflictStrategy;
|
||||||
import org.thingsboard.server.common.data.NameConflictPolicy;
|
import org.thingsboard.server.common.data.NameConflictPolicy;
|
||||||
|
import org.thingsboard.server.common.data.UniquifyStrategy;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
@ -50,7 +51,7 @@ import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_TEXT_SEARCH_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_TEXT_SEARCH_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD;
|
import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_SEPARATOR_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_SEPARATOR_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
||||||
@ -58,6 +59,7 @@ import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_D
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
||||||
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_STRATEGY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -134,12 +136,14 @@ public class CustomerController extends BaseController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Customer saveCustomer(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the customer.") @RequestBody Customer customer,
|
public Customer saveCustomer(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the customer.") @RequestBody Customer customer,
|
||||||
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
||||||
@RequestParam(name = "policy", defaultValue = "FAIL") NameConflictPolicy policy,
|
@RequestParam(name = "nameConflictPolicy", defaultValue = "FAIL") NameConflictPolicy nameConflictPolicy,
|
||||||
@Parameter(description = NAME_CONFLICT_SEPARATOR_DESC)
|
@Parameter(description = UNIQUIFY_SEPARATOR_DESC)
|
||||||
@RequestParam(name = "separator", defaultValue = "_") String separator) throws Exception {
|
@RequestParam(name = "uniquifySeparator", defaultValue = "_") String uniquifySeparator,
|
||||||
|
@Parameter(description = UNIQUIFY_STRATEGY_DESC)
|
||||||
|
@RequestParam(name = "uniquifyStrategy", defaultValue = "RANDOM") UniquifyStrategy uniquifyStrategy) throws Exception {
|
||||||
customer.setTenantId(getTenantId());
|
customer.setTenantId(getTenantId());
|
||||||
checkEntity(customer.getId(), customer, Resource.CUSTOMER);
|
checkEntity(customer.getId(), customer, Resource.CUSTOMER);
|
||||||
return tbCustomerService.save(customer, new NameConflictStrategy(policy, separator), getCurrentUser());
|
return tbCustomerService.save(customer, new NameConflictStrategy(nameConflictPolicy, uniquifySeparator, uniquifyStrategy), getCurrentUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Delete Customer (deleteCustomer)",
|
@ApiOperation(value = "Delete Customer (deleteCustomer)",
|
||||||
|
|||||||
@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.NameConflictPolicy;
|
|||||||
import org.thingsboard.server.common.data.NameConflictStrategy;
|
import org.thingsboard.server.common.data.NameConflictStrategy;
|
||||||
import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
|
import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
|
import org.thingsboard.server.common.data.UniquifyStrategy;
|
||||||
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
|
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
|
||||||
import org.thingsboard.server.common.data.edge.Edge;
|
import org.thingsboard.server.common.data.edge.Edge;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
||||||
@ -111,7 +112,7 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARA
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_SEPARATOR_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_SEPARATOR_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
||||||
@ -121,6 +122,7 @@ import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHO
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
||||||
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_STRATEGY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
||||||
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
||||||
|
|
||||||
@ -184,16 +186,18 @@ public class DeviceController extends BaseController {
|
|||||||
"If omitted, access token will be auto-generated.")
|
"If omitted, access token will be auto-generated.")
|
||||||
@RequestParam(name = "accessToken", required = false) String accessToken,
|
@RequestParam(name = "accessToken", required = false) String accessToken,
|
||||||
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
||||||
@RequestParam(name = "policy", defaultValue = "FAIL") NameConflictPolicy policy,
|
@RequestParam(name = "nameConflictPolicy", defaultValue = "FAIL") NameConflictPolicy nameConflictPolicy,
|
||||||
@Parameter(description = NAME_CONFLICT_SEPARATOR_DESC)
|
@Parameter(description = UNIQUIFY_SEPARATOR_DESC)
|
||||||
@RequestParam(name = "separator", defaultValue = "_") String separator) throws Exception {
|
@RequestParam(name = "uniquifySeparator", defaultValue = "_") String uniquifySeparator,
|
||||||
|
@Parameter(description = UNIQUIFY_STRATEGY_DESC)
|
||||||
|
@RequestParam(name = "uniquifyStrategy", defaultValue = "RANDOM") UniquifyStrategy uniquifyStrategy) throws Exception {
|
||||||
device.setTenantId(getCurrentUser().getTenantId());
|
device.setTenantId(getCurrentUser().getTenantId());
|
||||||
if (device.getId() != null) {
|
if (device.getId() != null) {
|
||||||
checkDeviceId(device.getId(), Operation.WRITE);
|
checkDeviceId(device.getId(), Operation.WRITE);
|
||||||
} else {
|
} else {
|
||||||
checkEntity(null, device, Resource.DEVICE);
|
checkEntity(null, device, Resource.DEVICE);
|
||||||
}
|
}
|
||||||
return tbDeviceService.save(device, accessToken, new NameConflictStrategy(policy, separator), getCurrentUser());
|
return tbDeviceService.save(device, accessToken, new NameConflictStrategy(nameConflictPolicy, uniquifySeparator, uniquifyStrategy), getCurrentUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Create Device (saveDevice) with credentials ",
|
@ApiOperation(value = "Create Device (saveDevice) with credentials ",
|
||||||
@ -220,14 +224,16 @@ public class DeviceController extends BaseController {
|
|||||||
public Device saveDeviceWithCredentials(@Parameter(description = "The JSON object with device and credentials. See method description above for example.")
|
public Device saveDeviceWithCredentials(@Parameter(description = "The JSON object with device and credentials. See method description above for example.")
|
||||||
@Valid @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials,
|
@Valid @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials,
|
||||||
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
||||||
@RequestParam(name = "policy", defaultValue = "FAIL") NameConflictPolicy policy,
|
@RequestParam(name = "nameConflictPolicy", defaultValue = "FAIL") NameConflictPolicy nameConflictPolicy,
|
||||||
@Parameter(description = NAME_CONFLICT_SEPARATOR_DESC)
|
@Parameter(description = UNIQUIFY_SEPARATOR_DESC)
|
||||||
@RequestParam(name = "separator", defaultValue = "_") String separator) throws ThingsboardException {
|
@RequestParam(name = "uniquifySeparator", defaultValue = "_") String uniquifySeparator,
|
||||||
|
@Parameter(description = UNIQUIFY_STRATEGY_DESC)
|
||||||
|
@RequestParam(name = "uniquifyStrategy", defaultValue = "RANDOM") UniquifyStrategy uniquifyStrategy) throws ThingsboardException {
|
||||||
Device device = deviceAndCredentials.getDevice();
|
Device device = deviceAndCredentials.getDevice();
|
||||||
DeviceCredentials credentials = deviceAndCredentials.getCredentials();
|
DeviceCredentials credentials = deviceAndCredentials.getCredentials();
|
||||||
device.setTenantId(getCurrentUser().getTenantId());
|
device.setTenantId(getCurrentUser().getTenantId());
|
||||||
checkEntity(device.getId(), device, Resource.DEVICE);
|
checkEntity(device.getId(), device, Resource.DEVICE);
|
||||||
return tbDeviceService.saveDeviceWithCredentials(device, credentials, new NameConflictStrategy(policy, separator), getCurrentUser());
|
return tbDeviceService.saveDeviceWithCredentials(device, credentials, new NameConflictStrategy(nameConflictPolicy, uniquifySeparator, uniquifyStrategy), getCurrentUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Delete device (deleteDevice)",
|
@ApiOperation(value = "Delete device (deleteDevice)",
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.EntityView;
|
|||||||
import org.thingsboard.server.common.data.EntityViewInfo;
|
import org.thingsboard.server.common.data.EntityViewInfo;
|
||||||
import org.thingsboard.server.common.data.NameConflictPolicy;
|
import org.thingsboard.server.common.data.NameConflictPolicy;
|
||||||
import org.thingsboard.server.common.data.NameConflictStrategy;
|
import org.thingsboard.server.common.data.NameConflictStrategy;
|
||||||
|
import org.thingsboard.server.common.data.UniquifyStrategy;
|
||||||
import org.thingsboard.server.common.data.edge.Edge;
|
import org.thingsboard.server.common.data.edge.Edge;
|
||||||
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
|
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
@ -72,7 +73,7 @@ import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_TYPE;
|
import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_TYPE;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.MODEL_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.MODEL_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_POLICY_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.NAME_CONFLICT_SEPARATOR_DESC;
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_SEPARATOR_DESC;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
||||||
@ -80,6 +81,7 @@ import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_D
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
||||||
|
import static org.thingsboard.server.controller.ControllerConstants.UNIQUIFY_STRATEGY_DESC;
|
||||||
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,9 +136,11 @@ public class EntityViewController extends BaseController {
|
|||||||
@Parameter(description = "A JSON object representing the entity view.")
|
@Parameter(description = "A JSON object representing the entity view.")
|
||||||
@RequestBody EntityView entityView,
|
@RequestBody EntityView entityView,
|
||||||
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
@Parameter(description = NAME_CONFLICT_POLICY_DESC)
|
||||||
@RequestParam(name = "policy", defaultValue = "FAIL") NameConflictPolicy policy,
|
@RequestParam(name = "nameConflictPolicy", defaultValue = "FAIL") NameConflictPolicy nameConflictPolicy,
|
||||||
@Parameter(description = NAME_CONFLICT_SEPARATOR_DESC)
|
@Parameter(description = UNIQUIFY_SEPARATOR_DESC)
|
||||||
@RequestParam(name = "separator", defaultValue = "_") String separator) throws Exception {
|
@RequestParam(name = "uniquifySeparator", defaultValue = "_") String uniquifySeparator,
|
||||||
|
@Parameter(description = UNIQUIFY_STRATEGY_DESC)
|
||||||
|
@RequestParam(name = "uniquifyStrategy", defaultValue = "RANDOM") UniquifyStrategy uniquifyStrategy) throws Exception {
|
||||||
entityView.setTenantId(getCurrentUser().getTenantId());
|
entityView.setTenantId(getCurrentUser().getTenantId());
|
||||||
EntityView existingEntityView = null;
|
EntityView existingEntityView = null;
|
||||||
if (entityView.getId() == null) {
|
if (entityView.getId() == null) {
|
||||||
@ -145,7 +149,7 @@ public class EntityViewController extends BaseController {
|
|||||||
} else {
|
} else {
|
||||||
existingEntityView = checkEntityViewId(entityView.getId(), Operation.WRITE);
|
existingEntityView = checkEntityViewId(entityView.getId(), Operation.WRITE);
|
||||||
}
|
}
|
||||||
return tbEntityViewService.save(entityView, existingEntityView, new NameConflictStrategy(policy, separator), getCurrentUser());
|
return tbEntityViewService.save(entityView, existingEntityView, new NameConflictStrategy(nameConflictPolicy, uniquifySeparator, uniquifyStrategy), getCurrentUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Delete entity view (deleteEntityView)",
|
@ApiOperation(value = "Delete entity view (deleteEntityView)",
|
||||||
|
|||||||
@ -76,6 +76,6 @@ public class Lwm2mController extends BaseController {
|
|||||||
public Device saveDeviceWithCredentials(@RequestBody Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException {
|
public Device saveDeviceWithCredentials(@RequestBody Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException {
|
||||||
Device device = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class));
|
Device device = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class));
|
||||||
DeviceCredentials credentials = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));
|
DeviceCredentials credentials = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));
|
||||||
return deviceController.saveDeviceWithCredentials(new SaveDeviceWithCredentialsRequest(device, credentials), DEFAULT.policy(), DEFAULT.separator());
|
return deviceController.saveDeviceWithCredentials(new SaveDeviceWithCredentialsRequest(device, credentials), DEFAULT.policy(), DEFAULT.separator(), DEFAULT.uniquifyStrategy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1083,19 +1083,25 @@ public class AssetControllerTest extends AbstractControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSaveAssetWithUniquifyStrategy() throws Exception {
|
public void testSaveAssetWithUniquifyStrategy() throws Exception {
|
||||||
Asset asset = new Asset();
|
Asset asset = new Asset();
|
||||||
asset.setName("My asset");
|
asset.setName("My unique asset");
|
||||||
asset.setType("default");
|
asset.setType("default");
|
||||||
doPost("/api/asset", asset, Asset.class);
|
doPost("/api/asset", asset, Asset.class);
|
||||||
|
|
||||||
doPost("/api/asset", asset).andExpect(status().isBadRequest());
|
doPost("/api/asset", asset).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
doPost("/api/asset?policy=FAIL", asset).andExpect(status().isBadRequest());
|
doPost("/api/asset?nameConflictPolicy=FAIL", asset).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
Asset secondAsset = doPost("/api/asset?policy=UNIQUIFY", asset, Asset.class);
|
Asset secondAsset = doPost("/api/asset?nameConflictPolicy=UNIQUIFY", asset, Asset.class);
|
||||||
assertThat(secondAsset.getName()).startsWith("My asset_");
|
assertThat(secondAsset.getName()).startsWith("My unique asset_");
|
||||||
|
|
||||||
Asset thirdAsset = doPost("/api/asset?policy=UNIQUIFY&separator=-", asset, Asset.class);
|
Asset thirdAsset = doPost("/api/asset?nameConflictPolicy=UNIQUIFY&uniquifySeparator=-", asset, Asset.class);
|
||||||
assertThat(thirdAsset.getName()).startsWith("My asset-");
|
assertThat(thirdAsset.getName()).startsWith("My unique asset-");
|
||||||
|
|
||||||
|
Asset fourthAsset = doPost("/api/asset?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", asset, Asset.class);
|
||||||
|
assertThat(fourthAsset.getName()).isEqualTo("My unique asset_1");
|
||||||
|
|
||||||
|
Asset fifthAsset = doPost("/api/asset?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", asset, Asset.class);
|
||||||
|
assertThat(fifthAsset.getName()).isEqualTo("My unique asset_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Asset createAsset(String name) {
|
private Asset createAsset(String name) {
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import org.springframework.context.annotation.Primary;
|
|||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.thingsboard.common.util.ThingsBoardExecutors;
|
import org.thingsboard.common.util.ThingsBoardExecutors;
|
||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
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;
|
||||||
@ -465,16 +466,22 @@ public class CustomerControllerTest extends AbstractControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSaveCustomerWithUniquifyStrategy() throws Exception {
|
public void testSaveCustomerWithUniquifyStrategy() throws Exception {
|
||||||
Customer customer = new Customer();
|
Customer customer = new Customer();
|
||||||
customer.setTitle("My customer");
|
customer.setTitle("My unique customer");
|
||||||
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
|
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
|
||||||
|
|
||||||
doPost("/api/customer?policy=FAIL", customer).andExpect(status().isBadRequest());
|
doPost("/api/customer?nameConflictPolicy=FAIL", customer).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
Customer secondCustomer = doPost("/api/customer?policy=UNIQUIFY", customer, Customer.class);
|
Customer secondCustomer = doPost("/api/customer?nameConflictPolicy=UNIQUIFY", customer, Customer.class);
|
||||||
assertThat(secondCustomer.getName()).startsWith("My customer_");
|
assertThat(secondCustomer.getName()).startsWith("My unique customer_");
|
||||||
|
|
||||||
Customer thirdCustomer = doPost("/api/customer?policy=UNIQUIFY&separator=-", customer, Customer.class);
|
Customer thirdCustomer = doPost("/api/customer?nameConflictPolicy=UNIQUIFY&uniquifySeparator=-", customer, Customer.class);
|
||||||
assertThat(thirdCustomer.getName()).startsWith("My customer-");
|
assertThat(thirdCustomer.getName()).startsWith("My unique customer-");
|
||||||
|
|
||||||
|
Customer fourthCustomer = doPost("/api/customer?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", customer, Customer.class);
|
||||||
|
assertThat(fourthCustomer.getName()).isEqualTo("My unique customer_1");
|
||||||
|
|
||||||
|
Customer fifthCustomer = doPost("/api/customer?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", customer, Customer.class);
|
||||||
|
assertThat(fifthCustomer.getName()).isEqualTo("My unique customer_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Customer createCustomer(String title) {
|
private Customer createCustomer(String title) {
|
||||||
|
|||||||
@ -1611,19 +1611,25 @@ public class DeviceControllerTest extends AbstractControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSaveDeviceWithUniquifyStrategy() throws Exception {
|
public void testSaveDeviceWithUniquifyStrategy() throws Exception {
|
||||||
Device device = new Device();
|
Device device = new Device();
|
||||||
device.setName("My device");
|
device.setName("My unique device");
|
||||||
device.setType("default");
|
device.setType("default");
|
||||||
Device savedDevice = doPost("/api/device", device, Device.class);
|
Device savedDevice = doPost("/api/device", device, Device.class);
|
||||||
|
|
||||||
doPost("/api/device", device).andExpect(status().isBadRequest());
|
doPost("/api/device", device).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
doPost("/api/device?policy=FAIL", device).andExpect(status().isBadRequest());
|
doPost("/api/device?nameConflictPolicy=FAIL", device).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
Device secondDevice = doPost("/api/device?policy=UNIQUIFY", device, Device.class);
|
Device secondDevice = doPost("/api/device?nameConflictPolicy=UNIQUIFY", device, Device.class);
|
||||||
assertThat(secondDevice.getName()).startsWith("My device_");
|
assertThat(secondDevice.getName()).startsWith("My unique device_");
|
||||||
|
|
||||||
Device thirdDevice = doPost("/api/device?policy=UNIQUIFY&separator=-", device, Device.class);
|
Device thirdDevice = doPost("/api/device?nameConflictPolicy=UNIQUIFY&uniquifySeparator=-", device, Device.class);
|
||||||
assertThat(thirdDevice.getName()).startsWith("My device-");
|
assertThat(thirdDevice.getName()).startsWith("My unique device-");
|
||||||
|
|
||||||
|
Device fourthDevice = doPost("/api/device?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", device, Device.class);
|
||||||
|
assertThat(fourthDevice.getName()).isEqualTo("My unique device_1");
|
||||||
|
|
||||||
|
Device fifthDevice = doPost("/api/device?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", device, Device.class);
|
||||||
|
assertThat(fifthDevice.getName()).isEqualTo("My unique device_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Device createDevice(String name) {
|
private Device createDevice(String name) {
|
||||||
|
|||||||
@ -860,16 +860,22 @@ public class EntityViewControllerTest extends AbstractControllerTest {
|
|||||||
view.setEntityId(testDevice.getId());
|
view.setEntityId(testDevice.getId());
|
||||||
view.setTenantId(tenantId);
|
view.setTenantId(tenantId);
|
||||||
view.setType("default");
|
view.setType("default");
|
||||||
view.setName("Test device view");
|
view.setName("My unique view");
|
||||||
|
|
||||||
EntityView savedView = doPost("/api/entityView", view, EntityView.class);
|
EntityView savedView = doPost("/api/entityView", view, EntityView.class);
|
||||||
|
|
||||||
doPost("/api/entityView?policy=FAIL", view).andExpect(status().isBadRequest());
|
doPost("/api/entityView?nameConflictPolicy=FAIL", view).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
EntityView secondView = doPost("/api/entityView?policy=UNIQUIFY", view, EntityView.class);
|
EntityView secondView = doPost("/api/entityView?nameConflictPolicy=UNIQUIFY", view, EntityView.class);
|
||||||
assertThat(secondView.getName()).startsWith("Test device view_");
|
assertThat(secondView.getName()).startsWith("My unique view_");
|
||||||
|
|
||||||
EntityView thirdView = doPost("/api/entityView?policy=UNIQUIFY&separator=-", view, EntityView.class);
|
EntityView thirdView = doPost("/api/entityView?nameConflictPolicy=UNIQUIFY&uniquifySeparator=-", view, EntityView.class);
|
||||||
assertThat(thirdView.getName()).startsWith("Test device view-");
|
assertThat(thirdView.getName()).startsWith("My unique view-");
|
||||||
|
|
||||||
|
EntityView fourthView = doPost("/api/entityView?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", view, EntityView.class);
|
||||||
|
assertThat(fourthView.getName()).isEqualTo("My unique view_1");
|
||||||
|
|
||||||
|
EntityView fifthEntityView = doPost("/api/entityView?nameConflictPolicy=UNIQUIFY&uniquifyStrategy=INCREMENTAL", view, EntityView.class);
|
||||||
|
assertThat(fifthEntityView.getName()).isEqualTo("My unique view_2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,8 @@ package org.thingsboard.server.common.data;
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
@Schema
|
@Schema
|
||||||
public record NameConflictStrategy(NameConflictPolicy policy, String separator) {
|
public record NameConflictStrategy(NameConflictPolicy policy, String separator, UniquifyStrategy uniquifyStrategy) {
|
||||||
|
|
||||||
public static final NameConflictStrategy DEFAULT = new NameConflictStrategy(NameConflictPolicy.FAIL, null);
|
public static final NameConflictStrategy DEFAULT = new NameConflictStrategy(NameConflictPolicy.FAIL, null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2025 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.common.data;
|
||||||
|
|
||||||
|
public enum UniquifyStrategy {
|
||||||
|
|
||||||
|
RANDOM,
|
||||||
|
INCREMENTAL;
|
||||||
|
|
||||||
|
}
|
||||||
@ -33,7 +33,7 @@ public interface Dao<T> {
|
|||||||
|
|
||||||
ListenableFuture<T> findByIdAsync(TenantId tenantId, UUID id);
|
ListenableFuture<T> findByIdAsync(TenantId tenantId, UUID id);
|
||||||
|
|
||||||
default EntityInfo findEntityInfoByName(TenantId tenantId, String name) {
|
default List<EntityInfo> findEntityInfosByNamePrefix(TenantId tenantId, String name) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,8 +51,12 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.thingsboard.server.common.data.UniquifyStrategy.RANDOM;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractEntityService {
|
public abstract class AbstractEntityService {
|
||||||
@ -167,18 +171,23 @@ public abstract class AbstractEntityService {
|
|||||||
return now + TimeUnit.MINUTES.toMillis(DebugModeUtil.getMaxDebugAllDuration(tbTenantProfileCache.get(tenantId).getDefaultProfileConfiguration().getMaxDebugModeDurationMinutes(), defaultDebugDurationMinutes));
|
return now + TimeUnit.MINUTES.toMillis(DebugModeUtil.getMaxDebugAllDuration(tbTenantProfileCache.get(tenantId).getDefaultProfileConfiguration().getMaxDebugModeDurationMinutes(), defaultDebugDurationMinutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <E extends HasId<?> & HasTenantId & HasName> void uniquifyEntityName(E entity, E oldEntity, Consumer<String> setName, EntityType entityType, NameConflictStrategy nameConflictStrategy) {
|
protected <E extends HasId<?> & HasTenantId & HasName> void uniquifyEntityName(E entity, E oldEntity, Consumer<String> setName, EntityType entityType, NameConflictStrategy strategy) {
|
||||||
Dao<?> dao = entityDaoRegistry.getDao(entityType);
|
Dao<?> dao = entityDaoRegistry.getDao(entityType);
|
||||||
EntityInfo existingEntity = dao.findEntityInfoByName(entity.getTenantId(), entity.getName());
|
List<EntityInfo> existingEntities = dao.findEntityInfosByNamePrefix(entity.getTenantId(), entity.getName());
|
||||||
if (existingEntity != null && (oldEntity == null || !existingEntity.getId().equals(oldEntity.getId()))) {
|
Set<String> existingNames = existingEntities.stream()
|
||||||
String suffix = StringUtils.randomAlphanumeric(6);
|
.filter(e -> (oldEntity == null || !e.getId().equals(oldEntity.getId())))
|
||||||
|
.map(EntityInfo::getName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (!existingNames.isEmpty()) {
|
||||||
|
int idx = 1;
|
||||||
|
String suffix = (strategy.uniquifyStrategy() == RANDOM) ? StringUtils.randomAlphanumeric(6) : String.valueOf(idx);
|
||||||
while (true) {
|
while (true) {
|
||||||
String newName = entity.getName() + nameConflictStrategy.separator() + suffix;
|
String newName = entity.getName() + strategy.separator() + suffix;
|
||||||
if (dao.findEntityInfoByName(entity.getTenantId(), newName) == null) {
|
if (!existingNames.contains(newName)) {
|
||||||
setName.accept(newName);
|
setName.accept(newName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
suffix = StringUtils.randomAlphanumeric(6);
|
suffix = (strategy.uniquifyStrategy() == RANDOM) ? StringUtils.randomAlphanumeric(6) : String.valueOf(idx++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -124,16 +124,14 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService<EntityVi
|
|||||||
|
|
||||||
private EntityView saveEntityView(EntityView entityView, boolean doValidate, NameConflictStrategy nameConflictStrategy) {
|
private EntityView saveEntityView(EntityView entityView, boolean doValidate, NameConflictStrategy nameConflictStrategy) {
|
||||||
log.trace("Executing save entity view [{}]", entityView);
|
log.trace("Executing save entity view [{}]", entityView);
|
||||||
EntityView old = null;
|
EntityView old = (entityView.getId() != null) ? findEntityViewById(entityView.getTenantId(), entityView.getId(), false) : null;
|
||||||
|
if (nameConflictStrategy.policy() == NameConflictPolicy.UNIQUIFY) {
|
||||||
|
uniquifyEntityName(entityView, old, entityView::setName, EntityType.ENTITY_VIEW, nameConflictStrategy);
|
||||||
|
}
|
||||||
if (doValidate) {
|
if (doValidate) {
|
||||||
old = entityViewValidator.validate(entityView, EntityView::getTenantId);
|
entityViewValidator.validate(entityView, EntityView::getTenantId);
|
||||||
} else if (entityView.getId() != null) {
|
|
||||||
old = findEntityViewById(entityView.getTenantId(), entityView.getId(), false);
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (nameConflictStrategy.policy() == NameConflictPolicy.UNIQUIFY) {
|
|
||||||
uniquifyEntityName(entityView, old, entityView::setName, EntityType.ENTITY_VIEW, nameConflictStrategy);
|
|
||||||
}
|
|
||||||
EntityView saved = entityViewDao.save(entityView.getTenantId(), entityView);
|
EntityView saved = entityViewDao.save(entityView.getTenantId(), entityView);
|
||||||
publishEvictEvent(new EntityViewEvictEvent(saved.getTenantId(), saved.getId(), saved.getEntityId(), old != null ? old.getEntityId() : null, saved.getName(), old != null ? old.getName() : null, saved));
|
publishEvictEvent(new EntityViewEvictEvent(saved.getTenantId(), saved.getId(), saved.getEntityId(), old != null ? old.getEntityId() : null, saved.getName(), old != null ? old.getName() : null, saved));
|
||||||
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(saved.getTenantId())
|
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(saved.getTenantId())
|
||||||
|
|||||||
@ -37,6 +37,14 @@ public class EntityViewDataValidator extends DataValidator<EntityView> {
|
|||||||
private final TenantService tenantService;
|
private final TenantService tenantService;
|
||||||
private final CustomerDao customerDao;
|
private final CustomerDao customerDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateCreate(TenantId tenantId, EntityView entityView) {
|
||||||
|
entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName())
|
||||||
|
.ifPresent(e -> {
|
||||||
|
throw new DataValidationException("Entity view with such name already exists!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EntityView validateUpdate(TenantId tenantId, EntityView entityView) {
|
protected EntityView validateUpdate(TenantId tenantId, EntityView entityView) {
|
||||||
var opt = entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName());
|
var opt = entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName());
|
||||||
|
|||||||
@ -105,8 +105,8 @@ public interface AssetRepository extends JpaRepository<AssetEntity, UUID>, Expor
|
|||||||
AssetEntity findByTenantIdAndName(UUID tenantId, String name);
|
AssetEntity findByTenantIdAndName(UUID tenantId, String name);
|
||||||
|
|
||||||
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'ASSET', a.name) " +
|
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'ASSET', a.name) " +
|
||||||
"FROM AssetEntity a WHERE a.tenantId = :tenantId AND a.name = :name")
|
"FROM AssetEntity a WHERE a.tenantId = :tenantId AND a.name LIKE CONCAT(:prefix, '%')")
|
||||||
EntityInfo findEntityInfoByName(UUID tenantId, String name);
|
List<EntityInfo> findEntityInfosByNamePrefix(UUID tenantId, String prefix);
|
||||||
|
|
||||||
@Query("SELECT a FROM AssetEntity a WHERE a.tenantId = :tenantId " +
|
@Query("SELECT a FROM AssetEntity a WHERE a.tenantId = :tenantId " +
|
||||||
"AND a.type = :type " +
|
"AND a.type = :type " +
|
||||||
|
|||||||
@ -269,9 +269,9 @@ public class JpaAssetDao extends JpaAbstractDao<AssetEntity, Asset> implements A
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityInfo findEntityInfoByName(TenantId tenantId, String name) {
|
public List<EntityInfo> findEntityInfosByNamePrefix(TenantId tenantId, String name) {
|
||||||
log.debug("Find asset entity info by name [{}]", name);
|
log.debug("Find asset entity infos by name [{}]", name);
|
||||||
return assetRepository.findEntityInfoByName(tenantId.getId(), name);
|
return assetRepository.findEntityInfosByNamePrefix(tenantId.getId(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -43,8 +43,8 @@ public interface CustomerRepository extends JpaRepository<CustomerEntity, UUID>,
|
|||||||
CustomerEntity findByTenantIdAndTitle(UUID tenantId, String title);
|
CustomerEntity findByTenantIdAndTitle(UUID tenantId, String title);
|
||||||
|
|
||||||
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'CUSTOMER', a.title) " +
|
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'CUSTOMER', a.title) " +
|
||||||
"FROM CustomerEntity a WHERE a.tenantId = :tenantId AND a.title = :name")
|
"FROM CustomerEntity a WHERE a.tenantId = :tenantId AND a.title LIKE CONCAT(:prefix, '%')")
|
||||||
EntityInfo findEntityInfoByName(UUID tenantId, String name);
|
List<EntityInfo> findEntityInfosByNamePrefix(UUID tenantId, String prefix);
|
||||||
|
|
||||||
@Query(value = "SELECT * FROM customer c WHERE c.tenant_id = :tenantId " +
|
@Query(value = "SELECT * FROM customer c WHERE c.tenant_id = :tenantId " +
|
||||||
"AND c.is_public IS TRUE ORDER BY c.id ASC LIMIT 1", nativeQuery = true)
|
"AND c.is_public IS TRUE ORDER BY c.id ASC LIMIT 1", nativeQuery = true)
|
||||||
|
|||||||
@ -119,8 +119,8 @@ public class JpaCustomerDao extends JpaAbstractDao<CustomerEntity, Customer> imp
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityInfo findEntityInfoByName(TenantId tenantId, String name) {
|
public List<EntityInfo> findEntityInfosByNamePrefix(TenantId tenantId, String name) {
|
||||||
return customerRepository.findEntityInfoByName(tenantId.getId(), name);
|
return customerRepository.findEntityInfosByNamePrefix(tenantId.getId(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -153,8 +153,8 @@ public interface DeviceRepository extends JpaRepository<DeviceEntity, UUID>, Exp
|
|||||||
DeviceEntity findByTenantIdAndName(UUID tenantId, String name);
|
DeviceEntity findByTenantIdAndName(UUID tenantId, String name);
|
||||||
|
|
||||||
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'DEVICE', a.name) " +
|
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'DEVICE', a.name) " +
|
||||||
"FROM DeviceEntity a WHERE a.tenantId = :tenantId AND a.name = :name")
|
"FROM DeviceEntity a WHERE a.tenantId = :tenantId AND a.name LIKE CONCAT(:prefix, '%')")
|
||||||
EntityInfo findEntityInfoByName(UUID tenantId, String name);
|
List<EntityInfo> findEntityInfosByNamePrefix(UUID tenantId, String prefix);
|
||||||
|
|
||||||
List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List<UUID> deviceIds);
|
List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List<UUID> deviceIds);
|
||||||
|
|
||||||
|
|||||||
@ -116,8 +116,8 @@ public class JpaDeviceDao extends JpaAbstractDao<DeviceEntity, Device> implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityInfo findEntityInfoByName(TenantId tenantId, String name) {
|
public List<EntityInfo> findEntityInfosByNamePrefix(TenantId tenantId, String name) {
|
||||||
return deviceRepository.findEntityInfoByName(tenantId.getId(), name);
|
return deviceRepository.findEntityInfosByNamePrefix(tenantId.getId(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -120,8 +120,8 @@ public interface EntityViewRepository extends JpaRepository<EntityViewEntity, UU
|
|||||||
EntityViewEntity findByTenantIdAndName(UUID tenantId, String name);
|
EntityViewEntity findByTenantIdAndName(UUID tenantId, String name);
|
||||||
|
|
||||||
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'ENTITY_VIEW', a.name) " +
|
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(a.id, 'ENTITY_VIEW', a.name) " +
|
||||||
"FROM EntityViewEntity a WHERE a.tenantId = :tenantId AND a.name = :name")
|
"FROM EntityViewEntity a WHERE a.tenantId = :tenantId AND a.name LIKE CONCAT(:prefix, '%')")
|
||||||
EntityInfo findEntityInfoByName(UUID tenantId, String name);
|
List<EntityInfo> findEntityInfosByNamePrefix(UUID tenantId, String prefix);
|
||||||
|
|
||||||
List<EntityViewEntity> findAllByTenantIdAndEntityId(UUID tenantId, UUID entityId);
|
List<EntityViewEntity> findAllByTenantIdAndEntityId(UUID tenantId, UUID entityId);
|
||||||
|
|
||||||
|
|||||||
@ -232,8 +232,8 @@ public class JpaEntityViewDao extends JpaAbstractDao<EntityViewEntity, EntityVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityInfo findEntityInfoByName(TenantId tenantId, String name) {
|
public List<EntityInfo> findEntityInfosByNamePrefix(TenantId tenantId, String name) {
|
||||||
return entityViewRepository.findEntityInfoByName(tenantId.getId(), name);
|
return entityViewRepository.findEntityInfosByNamePrefix(tenantId.getId(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -551,7 +551,6 @@ CREATE TABLE IF NOT EXISTS entity_view (
|
|||||||
additional_info varchar,
|
additional_info varchar,
|
||||||
external_id uuid,
|
external_id uuid,
|
||||||
version BIGINT DEFAULT 1,
|
version BIGINT DEFAULT 1,
|
||||||
CONSTRAINT entity_view_name_unq_key UNIQUE (tenant_id, name),
|
|
||||||
CONSTRAINT entity_view_external_id_unq_key UNIQUE (tenant_id, external_id)
|
CONSTRAINT entity_view_external_id_unq_key UNIQUE (tenant_id, external_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user