diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java index ed73a50cb..eb33a8bcf 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java @@ -9,11 +9,7 @@ */ package org.eclipse.hawkbit.repository; -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.Collections; import java.util.List; -import java.util.Map.Entry; -import java.util.Optional; import lombok.Getter; @@ -28,32 +24,18 @@ public enum SoftwareModuleFields implements RsqlQueryField { NAME("name"), DESCRIPTION("description"), VERSION("version"), - METADATA("metadata", new SimpleImmutableEntry<>("key", "value")); + METADATA("metadata"); private final String jpaEntityFieldName; private final List subEntityAttributes; - private final Entry subEntityMapTuple; - - SoftwareModuleFields(final String jpaEntityFieldName) { - this(jpaEntityFieldName, Collections.emptyList(), null); - } SoftwareModuleFields(final String jpaEntityFieldName, final String... subEntityAttributes) { - this(jpaEntityFieldName, List.of(subEntityAttributes), null); - } - - SoftwareModuleFields(final String jpaEntityFieldName, final Entry subEntityMapTuple) { - this(jpaEntityFieldName, Collections.emptyList(), subEntityMapTuple); - } - - SoftwareModuleFields(final String jpaEntityFieldName, List subEntityAttributes, final Entry subEntityMapTuple) { this.jpaEntityFieldName = jpaEntityFieldName; - this.subEntityMapTuple = subEntityMapTuple; - this.subEntityAttributes = subEntityAttributes; + this.subEntityAttributes = List.of(subEntityAttributes); } @Override - public Optional> getSubEntityMapTuple() { - return Optional.ofNullable(subEntityMapTuple); + public boolean isMap() { + return this == METADATA; } } \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java deleted file mode 100644 index 3feca26b0..000000000 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository; - -import lombok.Getter; - -/** - * Sort fields for SoftwareModuleMetadata. - */ -@Getter -public enum SoftwareModuleMetadataFields implements RsqlQueryField { - - KEY("key"), - VALUE("value"), - TARGETVISIBLE("targetVisible"); - - private final String jpaEntityFieldName; - - SoftwareModuleMetadataFields(final String jpaEntityFieldName) { - this.jpaEntityFieldName = jpaEntityFieldName; - } - - @Override - public String identifierFieldName() { - return KEY.getJpaEntityFieldName(); - } -} \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index bc0ff8eb7..58a6182e6 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -243,9 +243,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final Artifact artifactSignature = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE); - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) .key(visibleMetadataOsKey).value(visibleMetadataOsValue).targetVisible(true)); - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) .key("metaDataNotVisible").value("withValue").targetVisible(false)); final Target savedTarget = createTargetAndAssertNoActiveActions(); @@ -360,9 +360,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final Artifact artifactSignature = testdataFactory.createArtifact( nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE); - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) .key("metaDataVisible").value("withValue").targetVisible(true)); - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) .key("metaDataNotVisible").value("withValue").targetVisible(false)); final Target savedTarget = createTargetAndAssertNoActiveActions(); diff --git a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java index 41a767e6e..21903fe48 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java +++ b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java @@ -26,6 +26,7 @@ import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequ import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.springframework.hateoas.MediaTypes; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -37,6 +38,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.multipart.MultipartFile; /** @@ -55,7 +57,7 @@ public interface MgmtSoftwareModuleRestApi { * @param optionalFileName to override {@link MultipartFile#getOriginalFilename()} * @param md5Sum checksum for uploaded content check * @param sha1Sum checksum for uploaded content check - * @param sha256sum checksum for uploaded content check + * @param sha256Sum checksum for uploaded content check * @return In case all sets could successful be created the ResponseEntity with status code 201 - Created but without ResponseBody. In any * failure the JsonResponseExceptionHandler is handling the response. */ @@ -387,16 +389,49 @@ public interface MgmtSoftwareModuleRestApi { @DeleteMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}") ResponseEntity deleteSoftwareModule(@PathVariable("softwareModuleId") Long softwareModuleId); + /** + * Creates a list of metadata for a specific software module. + * + * @param softwareModuleId the ID of the distribution set to create metadata for + * @param metadataRest the list of metadata entries to create + * @return status created if post request is successful with the value of the created metadata + */ + @Operation(summary = "Creates a list of metadata for a specific Software Module", description = "Create a list of metadata entries Required Permission: UPDATE_REPOSITORY") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Successfully created"), + @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), + @ApiResponse(responseCode = "401", description = "The request requires user authentication.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + + "data volume restriction applies.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", description = "Software Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "409", description = "E.g. in case an entity is created or modified by another " + + "user in another request at the same time. You may retry your modification request.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "415", description = "The request was attempt with a media-type which is not " + + "supported by the server for this resource.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts " + + "and the client has to wait another second.", + content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) + }) + @PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", + consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }) + @ResponseStatus(HttpStatus.CREATED) + void createMetadata(@PathVariable("softwareModuleId") Long softwareModuleId, @RequestBody List metadataRest); + /** * Gets a paged list of metadata for a software module. * * @param softwareModuleId the ID of the software module for the metadata - * @param pagingOffsetParam the offset of list of metadata for pagination, might not be present in the rest request then default value will - * be applied - * @param pagingLimitParam the limit of the paged request, might not be present in the rest request then default value will be applied - * @param sortParam the sorting parameter in the request URL, syntax {@code field:direction, field:direction} - * @param rsqlParam the search parameter in the request URL, syntax {@code q=key==abc} - * @return status OK if get request is successful with the paged list of metadata + * @return status OK with the paged list of metadata, if the request is successful */ @Operation(summary = "Return metadata for a Software Module", description = "Get a paged list of metadata for a software module. Required Permission: READ_REPOSITORY") @ApiResponses(value = { @@ -421,30 +456,7 @@ public interface MgmtSoftwareModuleRestApi { }) @GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> getMetadata( - @PathVariable("softwareModuleId") Long softwareModuleId, - @RequestParam( - value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, - defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) - @Schema(description = "The paging offset (default is 0)") - int pagingOffsetParam, - @RequestParam( - value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, - defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) - @Schema(description = "The maximum number of entries in a page (default is 50)") - int pagingLimitParam, - @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) - @Schema(description = """ - The query parameter sort allows to define the sort order for the result of a query. A sort criteria - consists of the name of a field and the sort direction (ASC for ascending and DESC descending). - The sequence of the sort criteria (multiple can be used) defines the sort order of the entities - in the result.""") - String sortParam, - @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) - @Schema(description = """ - Query fields based on the Feed Item Query Language (FIQL). See Entity Definitions for - available fields.""") - String rsqlParam); + ResponseEntity> getMetadata(@PathVariable("softwareModuleId") Long softwareModuleId); /** * Gets a single metadata value for a specific key of a software module. @@ -486,7 +498,6 @@ public interface MgmtSoftwareModuleRestApi { * @param softwareModuleId the ID of the software module to update the metadata entry * @param metadataKey the key of the metadata to update the value * @param metadata body to update - * @return status OK if the update request is successful and the updated metadata result */ @Operation(summary = "Update a single metadata value of a Software Module", description = "Update a single metadata value for speficic key. Required Permission: UPDATE_REPOSITORY") @ApiResponses(value = { @@ -508,9 +519,9 @@ public interface MgmtSoftwareModuleRestApi { "and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) }) - @PutMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}", - produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity updateMetadata( + @PutMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}") + @ResponseStatus(HttpStatus.OK) + void updateMetadata( @PathVariable("softwareModuleId") Long softwareModuleId, @PathVariable("metadataKey") String metadataKey, @RequestBody MgmtSoftwareModuleMetadataBodyPut metadata); @@ -520,7 +531,6 @@ public interface MgmtSoftwareModuleRestApi { * * @param softwareModuleId the ID of the software module to delete the metadata entry * @param metadataKey the key of the metadata to delete - * @return status OK if the delete request is successful */ @Operation(summary = "Delete single metadata entry from the software module", description = "Delete a single metadata. Required Permission: UPDATE_REPOSITORY") @ApiResponses(value = { @@ -543,47 +553,6 @@ public interface MgmtSoftwareModuleRestApi { content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) }) @DeleteMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}") - ResponseEntity deleteMetadata( - @PathVariable("softwareModuleId") Long softwareModuleId, - @PathVariable("metadataKey") String metadataKey); - - /** - * Creates a list of metadata for a specific software module. - * - * @param softwareModuleId the ID of the distribution set to create metadata for - * @param metadataRest the list of metadata entries to create - * @return status created if post request is successful with the value of the created metadata - */ - @Operation(summary = "Creates a list of metadata for a specific Software Module", description = "Create a list of metadata entries Required Permission: UPDATE_REPOSITORY") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "Successfully created"), - @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), - @ApiResponse(responseCode = "401", description = "The request requires user authentication.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "403", - description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + - "data volume restriction applies.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "404", description = "Software Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "409", description = "E.g. in case an entity is created or modified by another " + - "user in another request at the same time. You may retry your modification request.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "415", description = "The request was attempt with a media-type which is not " + - "supported by the server for this resource.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts " + - "and the client has to wait another second.", - content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) - }) - @PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", - consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }, - produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> createMetadata( - @PathVariable("softwareModuleId") Long softwareModuleId, - @RequestBody List metadataRest); + @ResponseStatus(HttpStatus.OK) + void deleteMetadata(@PathVariable("softwareModuleId") Long softwareModuleId, @PathVariable("metadataKey") String metadataKey); } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java index 56516f653..20fd53f4f 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java @@ -33,7 +33,6 @@ import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.rest.json.model.ResponseList; /** diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java index 837b45097..9828a03ca 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java @@ -117,15 +117,10 @@ public final class MgmtSoftwareModuleMapper { static void addLinks(final SoftwareModule softwareModule, final MgmtSoftwareModule response) { response.add(linkTo(methodOn(MgmtSoftwareModuleRestApi.class).getArtifacts(response.getId(), null, null)) .withRel(MgmtRestConstants.SOFTWAREMODULE_V1_ARTIFACT).expand()); - - response.add(linkTo( - methodOn(MgmtSoftwareModuleTypeRestApi.class).getSoftwareModuleType(softwareModule.getType().getId())) + response.add(linkTo(methodOn(MgmtSoftwareModuleTypeRestApi.class).getSoftwareModuleType(softwareModule.getType().getId())) .withRel(MgmtRestConstants.SOFTWAREMODULE_V1_TYPE).expand()); - - response.add(linkTo(methodOn(MgmtSoftwareModuleResource.class).getMetadata(response.getId(), - MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET_VALUE, - MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, null, null)).withRel("metadata") - .expand().expand()); + response.add(linkTo(methodOn(MgmtSoftwareModuleResource.class).getMetadata(response.getId())) + .withRel("metadata").expand()); } static MgmtArtifact toResponse(final Artifact artifact) { diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index 6ab318f94..a18152046 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -14,6 +14,7 @@ import java.io.InputStream; import java.text.MessageFormat; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import jakarta.validation.ValidationException; @@ -234,62 +235,42 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } @Override - public ResponseEntity> getMetadata( - final Long softwareModuleId, - final int pagingOffsetParam, final int pagingLimitParam, final String sortParam, final String rsqlParam) { + public void createMetadata(final Long softwareModuleId, final List metadataRest) { + softwareModuleManagement.createMetadata(MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, softwareModuleId, metadataRest)); + } + + @Override + public ResponseEntity> getMetadata(final Long softwareModuleId) { // check if software module exists otherwise throw exception immediately findSoftwareModuleWithExceptionIfNotFound(softwareModuleId, null); - final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam); - final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam); - final Sort sorting = PagingUtility.sanitizeSoftwareModuleMetadataSortParam(sortParam); - - final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting); - final Page metaDataPage; - - if (rsqlParam != null) { - metaDataPage = softwareModuleManagement.findMetaDataByRsql(softwareModuleId, rsqlParam, pageable); - } else { - metaDataPage = softwareModuleManagement.findMetaDataBySoftwareModuleId(pageable, softwareModuleId); - } - - return ResponseEntity - .ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponseSwMetadata(metaDataPage.getContent()), metaDataPage.getTotalElements())); + final List metadata = softwareModuleManagement.getMetadata(softwareModuleId); + return ResponseEntity.ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponseSwMetadata(metadata), metadata.size())); } @Override public ResponseEntity getMetadataValue(final Long softwareModuleId, final String metadataKey) { - final SoftwareModuleMetadata findOne = softwareModuleManagement - .findMetaDataBySoftwareModuleId(softwareModuleId, metadataKey).orElseThrow( - () -> new EntityNotFoundException(SoftwareModuleMetadata.class, softwareModuleId, metadataKey)); + final SoftwareModuleMetadata findOne = softwareModuleManagement.getMetadata(softwareModuleId).stream() + .filter(entry -> entry.getKey().equals(metadataKey)) + .findFirst() + .orElseThrow(() -> new EntityNotFoundException("SoftwareModule metadata", softwareModuleId + ":" + metadataKey)); return ResponseEntity.ok(MgmtSoftwareModuleMapper.toResponseSwMetadata(findOne)); } @Override - public ResponseEntity updateMetadata( - final Long softwareModuleId, final String metadataKey, final MgmtSoftwareModuleMetadataBodyPut metadata) { - final SoftwareModuleMetadata updated = softwareModuleManagement - .updateMetaData(entityFactory.softwareModuleMetadata().update(softwareModuleId, metadataKey) - .value(metadata.getValue()).targetVisible(metadata.getTargetVisible())); - - return ResponseEntity.ok(MgmtSoftwareModuleMapper.toResponseSwMetadata(updated)); + public void updateMetadata(final Long softwareModuleId, final String metadataKey, final MgmtSoftwareModuleMetadataBodyPut metadata) { + softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata() + .update(softwareModuleId, metadataKey) + .value(metadata.getValue()) + .targetVisible(metadata.getTargetVisible())); } @Override @AuditLog(entity = "SoftwareModule", type = AuditLog.Type.DELETE, description = "Delete Software Module Metadata") - public ResponseEntity deleteMetadata(final Long softwareModuleId, final String metadataKey) { - softwareModuleManagement.deleteMetaData(softwareModuleId, metadataKey); - return ResponseEntity.ok().build(); - } - - @Override - public ResponseEntity> createMetadata( - final Long softwareModuleId, final List metadataRest) { - final List created = softwareModuleManagement.putMetaData( - MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, softwareModuleId, metadataRest)); - - return ResponseEntity.status(HttpStatus.CREATED).body(MgmtSoftwareModuleMapper.toResponseSwMetadata(created)); + public void deleteMetadata(final Long softwareModuleId, final String metadataKey) { + softwareModuleManagement.deleteMetadata(softwareModuleId, metadataKey); } private static MgmtRepresentationMode parseRepresentationMode(final String representationModeParam) { diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/PagingUtility.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/PagingUtility.java index cab10e7cb..f9ef4fa94 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/PagingUtility.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/PagingUtility.java @@ -19,7 +19,6 @@ import org.eclipse.hawkbit.repository.DistributionSetTypeFields; import org.eclipse.hawkbit.repository.RolloutFields; import org.eclipse.hawkbit.repository.RolloutGroupFields; import org.eclipse.hawkbit.repository.SoftwareModuleFields; -import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields; import org.eclipse.hawkbit.repository.TagFields; import org.eclipse.hawkbit.repository.TargetFields; @@ -132,22 +131,6 @@ public final class PagingUtility { return Sort.by(SortUtility.parse(ActionStatusFields.class, sortParam)); } - public static Sort sanitizeMetadataSortParam(final String sortParam) { - if (sortParam == null) { - // default - return Sort.by(Direction.ASC, SoftwareModuleMetadataFields.KEY.getJpaEntityFieldName()); - } - return Sort.by(SortUtility.parse(SoftwareModuleMetadataFields.class, sortParam)); - } - - public static Sort sanitizeSoftwareModuleMetadataSortParam(final String sortParam) { - if (sortParam == null) { - // default - return Sort.by(Direction.ASC, SoftwareModuleMetadataFields.KEY.getJpaEntityFieldName()); - } - return Sort.by(SortUtility.parse(SoftwareModuleMetadataFields.class, sortParam)); - } - public static Sort sanitizeRolloutSortParam(final String sortParam) { if (sortParam == null) { // default diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index a7242b503..a21ae7832 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.contains; @@ -74,7 +75,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.data.domain.PageRequest; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; @@ -162,7 +162,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); for (int index = 0; index < totalMetadata; index++) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) .key(knownKeyPrefix + index).value(knownValuePrefix + index)); } @@ -182,7 +182,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); for (int index = 0; index < totalMetadata; index++) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) .key(knownKeyPrefix + index).value(knownValuePrefix + index)); } @@ -202,7 +202,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String knownKey = "knownKey"; final String knownValue = "knownValue"; final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue)); mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}", @@ -1202,8 +1202,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(jsonPath("$.createdBy", equalTo("uploadTester"))) .andExpect(jsonPath("$.createdAt", equalTo(os.getCreatedAt()))) .andExpect(jsonPath("$._links.metadata.href", - equalTo("http://localhost/rest/v1/softwaremodules/" + os.getId() - + "/metadata?offset=0&limit=50"))) + equalTo("http://localhost/rest/v1/softwaremodules/" + os.getId() + "/metadata"))) .andExpect(jsonPath("$._links.type.href", equalTo("http://localhost/rest/v1/softwaremoduletypes/" + osType.getId()))) .andExpect(jsonPath("$._links.artifacts.href", @@ -1346,7 +1345,6 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes @Test @Description("Verifies the successful creation of metadata and the enforcement of the meta data quota.") void createMetadata() throws Exception { - final String knownKey1 = "knownKey1"; final String knownValue1 = "knownValue1"; final String knownKey2 = "knownKey2"; @@ -1361,19 +1359,12 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON).content(metaData1.toString())) .andDo(MockMvcResultPrinter.print()) - .andExpect(status().isCreated()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("[0].key", equalTo(knownKey1))) - .andExpect(jsonPath("[0].value", equalTo(knownValue1))) - .andExpect(jsonPath("[0].targetVisible", equalTo(false))) - .andExpect(jsonPath("[1].key", equalTo(knownKey2))) - .andExpect(jsonPath("[1].value", equalTo(knownValue2))) - .andExpect(jsonPath("[1].targetVisible", equalTo(true))); + .andExpect(status().isCreated()); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(sm.getId(), knownKey1)) - .as("Metadata key is wrong").get().extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue1); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(sm.getId(), knownKey2)) - .as("Metadata key is wrong").get().extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue2); + assertThat(softwareModuleManagement.getMetadata(sm.getId(), knownKey1)) + .as("Metadata key is wrong").extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue1); + assertThat(softwareModuleManagement.getMetadata(sm.getId(), knownKey2)) + .as("Metadata key is wrong").extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue2); // verify quota enforcement final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule(); @@ -1388,11 +1379,8 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andDo(MockMvcResultPrinter.print()) .andExpect(status().isForbidden()); - // verify that the number of meta data entries has not changed - // (we cannot use the PAGE constant here as it tries to sort by ID) - assertThat(softwareModuleManagement - .findMetaDataBySoftwareModuleId(PageRequest.of(0, Integer.MAX_VALUE), sm.getId()).getTotalElements()) - .isEqualTo(metaData1.length()); + // verify that the number of meta data entries has not changed (we cannot use the PAGE constant here as it tries to sort by ID) + assertThat(softwareModuleManagement.getMetadata(sm.getId()).size()).isEqualTo(metaData1.length()); } @@ -1405,7 +1393,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String updateValue = "valueForUpdate"; final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); final JSONObject jsonObject = new JSONObject().put("key", knownKey) @@ -1415,13 +1403,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey).accept( MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString())) .andDo(MockMvcResultPrinter.print()) - .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("key", equalTo(knownKey))) - .andExpect(jsonPath("value", equalTo(updateValue))); + .andExpect(status().isOk()); - final SoftwareModuleMetadata assertDS = softwareModuleManagement.findMetaDataBySoftwareModuleId(sm.getId(), - knownKey).get(); + final SoftwareModuleMetadata assertDS = softwareModuleManagement.getMetadata(sm.getId(), knownKey); assertThat(assertDS.getValue()).as("Metadata is wrong").isEqualTo(updateValue); assertThat(assertDS.isTargetVisible()).as("target visible is wrong").isTrue(); } @@ -1433,15 +1417,16 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String knownKey = "knownKey"; final String knownValue = "knownValue"; - final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.updateMetaData( - entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); + final long smId = testdataFactory.createSoftwareModuleOs().getId(); + softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata().create(smId).key(knownKey).value(knownValue)); - mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)) + mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/{key}", smId, knownKey)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(sm.getId(), knownKey)).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> softwareModuleManagement.getMetadata(smId, knownKey)); } @Test @@ -1451,11 +1436,11 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String knownKey = "knownKey"; final String knownValue = "knownValue"; - final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.updateMetaData( - entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); + final long smId = testdataFactory.createSoftwareModuleOs().getId(); + softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata().create(smId).key(knownKey).value(knownValue)); - mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/XXX", sm.getId(), knownKey)) + mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/XXX", smId, knownKey)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isNotFound()); @@ -1463,7 +1448,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andDo(MockMvcResultPrinter.print()) .andExpect(status().isNotFound()); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(sm.getId(), knownKey)).isPresent(); + assertThat(softwareModuleManagement.getMetadata(smId, knownKey)).isNotNull(); } @Test @@ -1474,32 +1459,6 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(status().isNotFound()); } - @Test - @Description("Verifies the successful search of a metadata entry based on value.") - void searchSoftwareModuleMetadataRsql() throws Exception { - final int totalMetadata = 10; - final String knownKeyPrefix = "knownKey"; - final String knownValuePrefix = "knownValue"; - final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - - for (int index = 0; index < totalMetadata; index++) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata() - .create(sm.getId()) - .key(knownKeyPrefix + index) - .value(knownValuePrefix + index)); - } - - final String rsqlSearchValue1 = "value==knownValue1"; - - mvc.perform(get("/rest/v1/softwaremodules/{swId}/metadata?q=" + rsqlSearchValue1, sm.getId())) - .andDo(MockMvcResultPrinter.print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("size", equalTo(1))) - .andExpect(jsonPath("total", equalTo(1))) - .andExpect(jsonPath("content[0].key", equalTo("knownKey1"))) - .andExpect(jsonPath("content[0].value", equalTo("knownValue1"))); - } - private void assertArtifact(final SoftwareModule sm, final byte[] random) throws IOException { // check result in db... // repo diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index 6873c0808..2b6c6c808 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -32,7 +32,6 @@ import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThis import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Statistic; import org.springframework.data.domain.Page; @@ -126,12 +125,11 @@ public interface DistributionSetManagement extends RepositoryManagement metadata); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java index 847b4b204..44ccd0234 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java @@ -22,7 +22,6 @@ import org.eclipse.hawkbit.repository.builder.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder; import org.eclipse.hawkbit.repository.builder.TargetTypeBuilder; import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.MetaData; /** * central {@link BaseEntity} generation service. Objects are created but not diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java index baefbb458..f1e339a81 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java @@ -26,8 +26,6 @@ import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; @@ -53,7 +51,39 @@ public interface SoftwareModuleManagement extends RepositoryManagement putMetaData(@NotNull @Valid Collection metadata); + void createMetadata(@NotNull @Valid Collection metadata); + + /** + * Finds all meta-data by the given software module id. + * + * @param id the software module id to retrieve the meta-data from + * @return a paged result of all meta-data entries for a given software module id + * @throws EntityNotFoundException if software module with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + List getMetadata(long id); + + /** + * Finds all meta-data by the given software module id and key. + * + * @param id the software module id to retrieve the meta-data from + * @param key the meta-data key to retrieve + * @return a paged result of all meta-data entries for a given software module id + * @throws EntityNotFoundException if software module with given ID does not exist ot the + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModuleMetadata getMetadata(long id, String key); + + /** + * Finds all meta-data by the given software module id where {@link SoftwareModuleMetadata#isTargetVisible()}. + * + * @param pageable the page request to page the result + * @param id the software module id to retrieve the meta-data from + * @return a paged result of all meta-data entries for a given software module id + * @throws EntityNotFoundException if software module with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findMetaDataBySoftwareModuleIdAndTargetVisible(@NotNull Pageable pageable, long id); /** * Creates or updates a single software module meta-data entry. @@ -66,7 +96,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement findByNameAndVersionAndType(@NotEmpty String name, @NotEmpty String version, long typeId); - /** - * Finds a single software module meta-data by its id. - * - * @param id where meta-data has to be found - * @param key of the meta-data element - * @return the found SoftwareModuleMetadata or {@code null} if not exits - * @throws EntityNotFoundException is module with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Optional findMetaDataBySoftwareModuleId(long id, @NotEmpty String key); - - /** - * Finds all meta-data by the given software module id. - * - * @param pageable the page request to page the result - * @param id the software module id to retrieve the meta-data from - * @return a paged result of all meta-data entries for a given software module id - * @throws EntityNotFoundException if software module with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findMetaDataBySoftwareModuleId(@NotNull Pageable pageable, long id); - - /** - * Finds all meta-data by the given software module id where {@link SoftwareModuleMetadata#isTargetVisible()}. - * - * @param pageable the page request to page the result - * @param id the software module id to retrieve the meta-data from - * @return a paged result of all meta-data entries for a given software module id - * @throws EntityNotFoundException if software module with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findMetaDataBySoftwareModuleIdAndTargetVisible(@NotNull Pageable pageable, long id); - - /** - * Finds all meta-data by the given software module id. - * - * @param id the software module id to retrieve the meta-data from - * @param rsqlParam filter definition in RSQL syntax - * @param pageable the page request to page the result - * @return a paged result of all meta-data entries for a given software module id - * @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the given - * {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException if the RSQL syntax is wrong - * @throws EntityNotFoundException if software module with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findMetaDataByRsql(long id, @NotNull String rsqlParam, @NotNull Pageable pageable); - /** * Retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType} * @@ -215,14 +198,4 @@ public interface SoftwareModuleManagement extends RepositoryManagement controllerIds); @@ -701,11 +697,11 @@ public interface TargetManagement { /** * Creates a list of target meta-data entries. * - * @param controllerId {@link Target} controller id the metadata has to be created for + * @param controllerId {@link Target} controller id the meta-data has to be created for * @param metadata the meta-data entries to create or update * @throws EntityNotFoundException if given target does not exist - * @throws EntityAlreadyExistsException in case one of the metadata entry already exists for the specific key - * @throws AssignmentQuotaExceededException if the maximum number of {@link MetaData} entries is exceeded for the addressed {@link Target} + * @throws EntityAlreadyExistsException in case one of the metad-ata entry already exists for the specific key + * @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed {@link Target} */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) void createMetadata(@NotEmpty String controllerId, @NotEmpty Map metadata); @@ -714,7 +710,7 @@ public interface TargetManagement { * Finds a single target meta-data by its id. * * @param controllerId of the {@link Target} - * @return the found target metadata + * @return the found target meta-data * @throws EntityNotFoundException if target with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @@ -723,10 +719,10 @@ public interface TargetManagement { /** * Updates a target meta-data value if corresponding entry exists. * - * @param controllerId {@link Target} controller id of the metadata entry to be updated + * @param controllerId {@link Target} controller id of the meta-data entry to be updated * @param key meta data-entry key to be updated * @param value meta data-entry to be new value - * @throws EntityNotFoundException in case the metadata entry does not exist and cannot be updated + * @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) void updateMetadata(@NotEmpty String controllerId, @NotNull String key, @NotNull String value); @@ -734,7 +730,7 @@ public interface TargetManagement { /** * Deletes a target meta data entry. * - * @param controllerId where metadata has to be deleted + * @param controllerId where meta-data has to be deleted * @param key of the meta data element * @throws EntityNotFoundException if given target does not exist */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java index 978ae4baf..2c8e40d63 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java @@ -9,7 +9,6 @@ */ package org.eclipse.hawkbit.repository.builder; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; @@ -19,14 +18,14 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; public interface SoftwareModuleMetadataBuilder { /** - * @param softwareModuleId of the {@link SoftwareModule} the {@link MetaData} belongs to - * @param key of {@link MetaData#getKey()} + * @param softwareModuleId of the {@link SoftwareModule} the {@link SoftwareModuleMetadata} belongs to + * @param key of {@link SoftwareModuleMetadata#getKey()} * @return builder instance */ SoftwareModuleMetadataUpdate update(long softwareModuleId, String key); /** - * @param softwareModuleId of the {@link SoftwareModule} the {@link MetaData} belongs to + * @param softwareModuleId of the {@link SoftwareModule} the {@link SoftwareModuleMetadata} belongs to * @return builder instance */ SoftwareModuleMetadataCreate create(long softwareModuleId); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java index 817971f02..3e77be031 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java @@ -13,7 +13,7 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** @@ -24,16 +24,16 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; public interface SoftwareModuleMetadataCreate { /** - * @param key for {@link MetaData#getKey()} + * @param key for {@link SoftwareModuleMetadata#getKey()} * @return updated builder instance */ - SoftwareModuleMetadataCreate key(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key); + SoftwareModuleMetadataCreate key(@Size(min = 1, max =SoftwareModule.METADATA_KEY_MAX_SIZE) @NotNull String key); /** - * @param value for {@link MetaData#getValue()} + * @param value for {@link SoftwareModuleMetadata#getValue()} * @return updated builder instance */ - SoftwareModuleMetadataCreate value(@Size(max = MetaData.VALUE_MAX_SIZE) String value); + SoftwareModuleMetadataCreate value(@Size(max = SoftwareModule.METADATA_VALUE_MAX_SIZE) String value); /** * @param visible for {@link SoftwareModuleMetadata#isTargetVisible()} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java index dfd87cc14..05cb7212e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java @@ -12,7 +12,7 @@ package org.eclipse.hawkbit.repository.builder; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** @@ -22,10 +22,10 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; public interface SoftwareModuleMetadataUpdate { /** - * @param value for {@link MetaData#getValue()} + * @param value for {@link SoftwareModuleMetadata#getValue()} * @return updated builder instance */ - SoftwareModuleMetadataUpdate value(@Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value); + SoftwareModuleMetadataUpdate value(@Size(min = 1, max = SoftwareModule.METADATA_VALUE_MAX_SIZE) @NotNull String value); /** * @param visible for {@link SoftwareModuleMetadata#isTargetVisible()} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java index 1e738767c..3d036f821 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java @@ -18,7 +18,6 @@ import lombok.Getter; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.MetaData; /** * the {@link EntityNotFoundException} is thrown when a entity queried but not found. @@ -76,9 +75,7 @@ public class EntityNotFoundException extends AbstractServerRtException { * @param entityId of the {@link BaseEntity} */ public EntityNotFoundException(final String type, final Object entityId) { - super(type + " with given identifier {" + entityId + "} does not exist.", - THIS_ERROR, - Map.of(TYPE, type, ENTITY_ID, entityId)); + super(type + " with given identifier {" + entityId + "} does not exist.", THIS_ERROR, Map.of(TYPE, type, ENTITY_ID, entityId)); } /** @@ -91,30 +88,6 @@ public class EntityNotFoundException extends AbstractServerRtException { this(type.getSimpleName(), entityId); } - /** - * Parameterized constructor for {@link MetaData} not found. - * - * @param type of the entity that was not found - * @param entityId of the {@link BaseEntity} the {@link MetaData} was for - * @param key for the {@link MetaData} entry - */ - public EntityNotFoundException(final Class type, final Long entityId, final String key) { - this(type, String.valueOf(entityId), key); - } - - /** - * Parameterized constructor for {@link MetaData} not found. - * - * @param type of the entity that was not found - * @param entityId of the {@link BaseEntity} the {@link MetaData} was for - * @param key for the {@link MetaData} entry - */ - public EntityNotFoundException(final Class type, final String entityId, final String key) { - super(type.getSimpleName() + " for given entity {" + toEntityString(entityId) + "} and with key {" + key + "} does not exist.", - THIS_ERROR, - Map.of(TYPE, type.getSimpleName(), ENTITY_ID, entityId, KEY, key)); - } - /** * Parameterized constructor for a list of {@link BaseEntity}s not found. * @@ -122,10 +95,14 @@ public class EntityNotFoundException extends AbstractServerRtException { * @param expected collection of the {@link BaseEntity#getId()}s * @param found collection of the {@link BaseEntity#getId()}s */ - public EntityNotFoundException(final Class type, final Collection expected, - final Collection found) { - super(type.getSimpleName() + "s with given identifiers {" + toEntityString(expected.stream().filter(id -> !found.contains(id)) - .map(String::valueOf).collect(Collectors.joining(","))) + "} do not exist.", + public EntityNotFoundException(final Class type, final Collection expected, final Collection found) { + super( + String.format("%ss with given identifiers {%s} do not exist.", + type.getSimpleName(), + toEntityString(expected.stream() + .filter(id -> !found.contains(id)) + .map(String::valueOf) + .collect(Collectors.joining(",")))), THIS_ERROR, Map.of(TYPE, type.getSimpleName(), ENTITY_ID, expected.stream().filter(id -> !found.contains(id)).map(String::valueOf))); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java index 2852c0d1c..300707e29 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java @@ -26,12 +26,12 @@ public interface DistributionSet extends NamedVersionedEntity { /** * Maximum length of metadata key. */ - int METADATA_KEY_SIZE = 128; + int METADATA_MAX_KEY_SIZE = 128; /** * Maximum length of metadata value. */ - int METADATA_VALUE_SIZE = 4000; + int METADATA_MAX_VALUE_SIZE = 4000; /** * @return type of the {@link DistributionSet}. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java deleted file mode 100644 index 7a4d2199a..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.model; - -import java.io.Serializable; - -/** - * Meta data for entities, a (key/value) store. - */ -public interface MetaData extends Serializable { - - /** - * Maximum length of metadata key. - */ - int KEY_MAX_SIZE = 128; - - /** - * Maximum length of metadata value. - */ - int VALUE_MAX_SIZE = 4000; - - /** - * @return {@link BaseEntity#getId()} the metadata is related to - */ - Long getEntityId(); - - /** - * @return the key - */ - String getKey(); - - /** - * @return the value - */ - String getValue(); - -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModule.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModule.java index 96f743ab3..b247b417f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModule.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModule.java @@ -22,6 +22,16 @@ public interface SoftwareModule extends NamedVersionedEntity { */ int VENDOR_MAX_SIZE = 256; + /** + * Maximum length of metadata key. + */ + int METADATA_KEY_MAX_SIZE = 128; + + /** + * Maximum length of metadata value. + */ + int METADATA_VALUE_MAX_SIZE = 4000; + /** * @return the type of the software module */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java index 113f38166..91ee113af 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java @@ -9,24 +9,26 @@ */ package org.eclipse.hawkbit.repository.model; +import java.io.Serializable; + /** - * {@link MetaData} element of a {@link SoftwareModule}. + * Metadata element of a {@link SoftwareModule}. The software module metadata is not only (key, value) pair (like the metadata of + * targets and distribution sets), but also contains the information if the metadata is visible for targets as part of {@link Action}. */ -public interface SoftwareModuleMetadata extends MetaData { +public interface SoftwareModuleMetadata extends Serializable { /** - * @return {@link SoftwareModule} this entry belongs to. + * @return the key */ - SoftwareModule getSoftwareModule(); - - @Override - default Long getEntityId() { - return getSoftwareModule().getId(); - } + String getKey(); /** - * @return true if element is visible for targets as part of - * {@link Action}. + * @return the value + */ + String getValue(); + + /** + * @return true if element is visible for targets as part of {@link Action}. */ boolean isTargetVisible(); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java index 23638bd50..d08917021 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java @@ -40,22 +40,22 @@ public interface Target extends NamedEntity { /** * Maximum length of key of controller attribute */ - int CONTROLLER_ATTRIBUTE_KEY_SIZE = 128; + int CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE = 128; /** * Maximum length of value of controller attribute */ - int CONTROLLER_ATTRIBUTE_VALUE_SIZE = 128; + int CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE = 128; /** * Maximum length of metadata key. */ - int CONTROLLER_METADATA_KEY_SIZE = 128; + int METADATA_MAX_KEY_SIZE = 128; /** * Maximum length of metadata value. */ - int CONTROLLER_METADATA_VALUE_SIZE = 4000; + int METADATA_MAX_VALUE_SIZE = 4000; /** * @return business identifier of the {@link Target} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java index 207ff7248..3a3eb0902 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java @@ -26,7 +26,6 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder; -import org.eclipse.hawkbit.repository.model.MetaData; import org.springframework.validation.annotation.Validated; /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index c760fb9e7..d0d109f8d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED; import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; -import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE; -import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE; +import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE; +import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE; import java.net.URI; import java.time.Duration; @@ -618,11 +618,11 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } private static boolean isAttributeKeyValid(final String key) { - return key != null && key.length() <= CONTROLLER_ATTRIBUTE_KEY_SIZE && PATTERN.matcher(key).matches(); + return key != null && key.length() <= CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE && PATTERN.matcher(key).matches(); } private static boolean isAttributeValueValid(final String value) { - return value == null || (value.length() <= CONTROLLER_ATTRIBUTE_VALUE_SIZE && PATTERN.matcher(value).matches()); + return value == null || (value.length() <= CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE && PATTERN.matcher(value).matches()); } private static void copy(final Map src, final Map trg) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java index 76a77ad95..5be12498c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.jpa.management; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -19,7 +18,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import jakarta.persistence.EntityManager; @@ -29,7 +27,6 @@ import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleMetadataUpdate; import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleUpdate; import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; @@ -272,53 +269,61 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List putMetaData(final Collection create) { - if (!create.isEmpty()) { - // check if all metadata entries refer to the same software module - final Long id = ((JpaSoftwareModuleMetadataCreate) create.iterator().next()).getSoftwareModuleId(); - if (createJpaMetadataCreateStream(create).allMatch(c -> id.equals(c.getSoftwareModuleId()))) { - assertSoftwareModuleExists(id); - assertMetaDataQuota(id, create.size()); - - // touch to update revision and last modified timestamp - JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(id) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); - return createJpaMetadataCreateStream(create).map(this::saveMetadata).toList(); - } else { - // group by software module id to minimize database access - final Map> groups = createJpaMetadataCreateStream(create) - .collect(Collectors.groupingBy(JpaSoftwareModuleMetadataCreate::getSoftwareModuleId)); - return groups.entrySet().stream().flatMap(e -> { - final List group = e.getValue(); - + public void createMetadata(final Collection create) { + // group by software module id to minimize database access + create.stream() + .map(JpaSoftwareModuleMetadataCreate.class::cast) + .collect(Collectors.groupingBy(JpaSoftwareModuleMetadataCreate::getSoftwareModuleId)) + .forEach((id, createsForSoftwareModule) -> { assertSoftwareModuleExists(id); - assertMetaDataQuota(e.getKey(), group.size()); + assertMetadataQuota(id, createsForSoftwareModule.size()); // touch to update revision and last modified timestamp - JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(id) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); - return group.stream().map(this::saveMetadata); - }).toList(); - } - } + JpaManagementHelper.touch( + entityManager, softwareModuleRepository, + (JpaSoftwareModule) get(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); + createsForSoftwareModule.forEach(this::saveMetadata); + }); + } - return Collections.emptyList(); + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public List getMetadata(final long id) { + assertSoftwareModuleExists(id); + + return (List)softwareModuleMetadataRepository.findAll(metadataBySoftwareModuleIdSpec(id)); + } + + @Override + public SoftwareModuleMetadata getMetadata(final long id, final String key) { + assertSoftwareModuleExists(id); + + return findMetadata(id, key).orElseThrow(() -> new EntityNotFoundException("SoftwareModuleMetadata", id + ":" + key)); + } + + @Override + public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable, final long id) { + assertSoftwareModuleExists(id); + + return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( + id, true, PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT)), pageable); } @Override @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataCreate c) { + public SoftwareModuleMetadata updateMetadata(final SoftwareModuleMetadataCreate c) { final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c; final Long id = create.getSoftwareModuleId(); assertSoftwareModuleExists(id); - assertMetaDataQuota(id, 1); + assertMetadataQuota(id, 1); // touch to update revision and last modified timestamp - JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(id) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); + JpaManagementHelper.touch( + entityManager, softwareModuleRepository, + (JpaSoftwareModule) get(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); return saveMetadata(create); } @@ -326,13 +331,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataUpdate u) { + public SoftwareModuleMetadata updateMetadata(final SoftwareModuleMetadataUpdate u) { final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u; // check if exists otherwise throw entity not found exception - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findMetaDataBySoftwareModuleId( + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findMetadata( update.getSoftwareModuleId(), update.getKey()) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, update.getSoftwareModuleId(), update.getKey())); + .orElseThrow(() -> new EntityNotFoundException("SoftwareModuleMetadata", update.getSoftwareModuleId() + ":" + update.getKey())); update.getValue().ifPresent(metadata::setValue); update.isTargetVisible().ifPresent(metadata::setTargetVisible); @@ -345,9 +350,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void deleteMetaData(final long id, final String key) { - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findMetaDataBySoftwareModuleId0(id, key) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, id, key)); + public void deleteMetadata(final long id, final String key) { + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findMetadata(id, key) + .orElseThrow(() -> new EntityNotFoundException("SoftwareModuleMetadata", id + ":" + key)); JpaManagementHelper.touch(entityManager, softwareModuleRepository, metadata.getSoftwareModule()); softwareModuleMetadataRepository.deleteById(metadata.getId()); @@ -424,45 +429,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { .map(SoftwareModule.class::cast); } - @Override - public Optional findMetaDataBySoftwareModuleId(final long id, final String key) { - return findMetaDataBySoftwareModuleId0(id, key); - } - private Optional findMetaDataBySoftwareModuleId0(final long id, final String key) { - assertSoftwareModuleExists(id); - - return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(id, key)) - .map(SoftwareModuleMetadata.class::cast); - } - - @Override - public Page findMetaDataBySoftwareModuleId(final Pageable pageable, final long id) { - assertSoftwareModuleExists(id); - - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, - Collections.singletonList(metadataBySoftwareModuleIdSpec(id)), pageable - ); - } - - @Override - public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable, - final long id) { - assertSoftwareModuleExists(id); - - return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( - id, true, PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT)), pageable); - } - - @Override - public Page findMetaDataByRsql(final long id, final String rsqlParam, final Pageable pageable) { - assertSoftwareModuleExists(id); - - final List> specList = Arrays - .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class, - virtualPropertyReplacer, database), metadataBySoftwareModuleIdSpec(id)); - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, specList, pageable); - } - @Override public Slice findByType(final long typeId, final Pageable pageable) { assertSoftwareModuleTypeExists(typeId); @@ -490,18 +456,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { return softwareModuleRepository.count(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)); } - @Override - public long countMetaDataBySoftwareModuleId(final long id) { - assertSoftwareModuleExists(id); - - return softwareModuleMetadataRepository.countBySoftwareModuleId(id); - } - - private static Stream createJpaMetadataCreateStream( - final Collection create) { - return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast); - } - private static Specification metadataBySoftwareModuleIdSpec(final long id) { return (root, query, cb) -> cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(AbstractJpaBaseEntity_.id), id); } @@ -526,23 +480,30 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { return softwareModuleMetadataRepository.save(create.build()); } - private void assertSoftwareModuleMetadataDoesNotExist(final Long id, - final JpaSoftwareModuleMetadataCreate md) { + private Optional findMetadata(final long id, final String key) { + assertSoftwareModuleExists(id); + + return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(id, key)) + .map(SoftwareModuleMetadata.class::cast); + } + + private void assertSoftwareModuleMetadataDoesNotExist(final Long id, final JpaSoftwareModuleMetadataCreate md) { if (softwareModuleMetadataRepository.existsById(new SwMetadataCompositeKey(id, md.getKey()))) { throw new EntityAlreadyExistsException("Metadata entry with key '" + md.getKey() + "' already exists!"); } } /** - * Asserts the meta data quota for the software module with the given ID. + * Asserts the meta-data quota for the software module with the given ID. * * @param id The software module ID. - * @param requested Number of meta data entries to be created. + * @param requested Number of meta-data entries to be created. */ - private void assertMetaDataQuota(final Long id, final int requested) { + private void assertMetadataQuota(final Long id, final int requested) { final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule(); - QuotaHelper.assertAssignmentQuota(id, requested, maxMetaData, SoftwareModuleMetadata.class, - SoftwareModule.class, softwareModuleMetadataRepository::countBySoftwareModuleId); + QuotaHelper.assertAssignmentQuota( + id, requested, maxMetaData, SoftwareModuleMetadata.class, SoftwareModule.class, + softwareModuleMetadataRepository::countBySoftwareModuleId); } private void assertSoftwareModuleExists(final Long id) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java deleted file mode 100644 index c3948dbfc..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.model; - -import java.io.Serial; -import java.util.Objects; - -import jakarta.persistence.Basic; -import jakarta.persistence.Column; -import jakarta.persistence.Id; -import jakarta.persistence.MappedSuperclass; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.MetaData; - -/** - * Meta data for entities. - */ -@MappedSuperclass -public abstract class AbstractJpaMetaData implements MetaData { - - @Serial - private static final long serialVersionUID = 1L; - - @Id - @Column(name = "meta_key", nullable = false, length = MetaData.KEY_MAX_SIZE, updatable = false) - @Size(min = 1, max = MetaData.KEY_MAX_SIZE) - @NotNull - private String key; - - @Column(name = "meta_value", length = MetaData.VALUE_MAX_SIZE) - @Size(max = MetaData.VALUE_MAX_SIZE) - @Basic - private String value; - - protected AbstractJpaMetaData(final String key, final String value) { - this.key = key; - this.value = value; - } - - protected AbstractJpaMetaData() { - // Default constructor needed for JPA entities - } - - @Override - public String getKey() { - return key; - } - - public void setKey(final String key) { - this.key = key; - } - - @Override - public String getValue() { - return value; - } - - public void setValue(final String value) { - this.value = value; - } - - @Override - public int hashCode() { - return Objects.hash(key, value); - } - - @Override - public boolean equals(final Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - final AbstractJpaMetaData that = (AbstractJpaMetaData) o; - return Objects.equals(key, that.key) && Objects.equals(value, that.value); - } -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index c65f0c2ac..42c16abb5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -116,8 +116,8 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen name = "sp_ds_metadata", joinColumns = { @JoinColumn(name = "ds", nullable = false) }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_metadata_ds")) - @MapKeyColumn(name = "meta_key", length = DistributionSet.METADATA_KEY_SIZE) - @Column(name = "meta_value", length = DistributionSet.METADATA_VALUE_SIZE) + @MapKeyColumn(name = "meta_key", length = DistributionSet.METADATA_MAX_KEY_SIZE) + @Column(name = "meta_value", length = DistributionSet.METADATA_MAX_VALUE_SIZE) private Map metadata; @Column(name = "complete") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java index e247d64d2..3048a0040 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java @@ -13,10 +13,13 @@ import java.io.Serial; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.ConstraintMode; +import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.ForeignKey; @@ -24,6 +27,7 @@ import jakarta.persistence.Index; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapKeyColumn; import jakarta.persistence.NamedAttributeNode; import jakarta.persistence.NamedEntityGraph; import jakarta.persistence.OneToMany; @@ -69,8 +73,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement @Serial private static final long serialVersionUID = 1L; - private static final String DELETED_PROPERTY = "deleted"; - @Setter @ManyToOne @JoinColumn(name = "sm_type", nullable = false, updatable = false, @@ -92,11 +94,16 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement @Column(name = "encrypted") private boolean encrypted; - @ToString.Exclude - @OneToMany(mappedBy = "softwareModule", fetch = FetchType.LAZY, - cascade = { CascadeType.REMOVE }, - targetEntity = JpaSoftwareModuleMetadata.class) - private List metadata; + // no cascade option on an ElementCollection, the target objects are always persisted, merged, removed with their parent. + @Getter + @ElementCollection + @CollectionTable( + name = "sp_sm_metadata", + joinColumns = { @JoinColumn(name = "sm", nullable = false) }, + foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_sm_metadata_sm")) + @MapKeyColumn(name = "meta_key", length = SoftwareModule.METADATA_KEY_MAX_SIZE) + @Column(name = "meta_value", length = SoftwareModule.METADATA_VALUE_MAX_SIZE) + private Map metadata; @Column(name = "locked") private boolean locked; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java index 71d630014..b2cb566eb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.model; import java.io.Serial; +import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.ConstraintMode; import jakarta.persistence.Entity; @@ -21,11 +22,11 @@ import jakarta.persistence.IdClass; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import lombok.ToString; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; @@ -34,31 +35,42 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; */ @NoArgsConstructor // Default constructor for JPA @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) @IdClass(SwMetadataCompositeKey.class) @Entity @Table(name = "sp_sm_metadata") -public class JpaSoftwareModuleMetadata extends AbstractJpaMetaData implements SoftwareModuleMetadata { +public class JpaSoftwareModuleMetadata implements SoftwareModuleMetadata { @Serial private static final long serialVersionUID = 1L; @Id @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "sm", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_sm_metadata_sm")) + @JoinColumn( + name = "sm", nullable = false, updatable = false, + foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_sm_metadata_sm")) private JpaSoftwareModule softwareModule; + @Id + @Column(name = "meta_key", nullable = false, length = SoftwareModule.METADATA_KEY_MAX_SIZE, updatable = false) + @Size(min = 1, max = SoftwareModule.METADATA_KEY_MAX_SIZE) + @NotNull + private String key; + + @Column(name = "meta_value", length = SoftwareModule.METADATA_VALUE_MAX_SIZE) + @Size(max = SoftwareModule.METADATA_VALUE_MAX_SIZE) + @Basic + private String value; + @Column(name = "target_visible") private boolean targetVisible; public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value) { - super(key, value); - this.softwareModule = (JpaSoftwareModule) softwareModule; + this(key, softwareModule, value, false); } public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value, final boolean targetVisible) { - super(key, value); + this.key = key; + this.value = value; this.softwareModule = (JpaSoftwareModule) softwareModule; this.targetVisible = targetVisible; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index c72825abd..dcba2f317 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -37,7 +37,6 @@ import jakarta.persistence.MapKeyColumn; import jakarta.persistence.NamedAttributeNode; import jakarta.persistence.NamedEntityGraph; import jakarta.persistence.NamedEntityGraphs; -import jakarta.persistence.NamedSubgraph; import jakarta.persistence.OneToMany; import jakarta.persistence.PrimaryKeyJoinColumn; import jakarta.persistence.Table; @@ -187,8 +186,8 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw name = "sp_target_attributes", joinColumns = { @JoinColumn(name = "target", nullable = false) }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_attributes_target")) - @MapKeyColumn(name = "attribute_key", length = Target.CONTROLLER_ATTRIBUTE_KEY_SIZE) - @Column(name = "attribute_value", length = Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE) + @MapKeyColumn(name = "attribute_key", length = Target.CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE) + @Column(name = "attribute_value", length = Target.CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE) private Map controllerAttributes; // no cascade option on an ElementCollection, the target objects are always persisted, merged, removed with their parent @@ -198,8 +197,8 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw name = "sp_target_metadata", joinColumns = { @JoinColumn(name = "target", nullable = false) }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_metadata_target")) - @MapKeyColumn(name = "meta_key", length = Target.CONTROLLER_METADATA_KEY_SIZE) - @Column(name = "meta_value", length = Target.CONTROLLER_METADATA_VALUE_SIZE) + @MapKeyColumn(name = "meta_key", length = Target.METADATA_MAX_KEY_SIZE) + @Column(name = "meta_value", length = Target.METADATA_MAX_VALUE_SIZE) private Map metadata; @OneToMany(mappedBy = "target", fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE }, targetEntity = JpaAction.class) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java index 414ef7edb..882ab8f3c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java @@ -46,17 +46,20 @@ class SoftwareManagementSecurityTest @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void createMetaDataPermissionsCheck() { assertPermissions( - () -> softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(1L).key("key").value("value")), + () -> softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(1L).key("key").value("value")), List.of(SpPermission.UPDATE_REPOSITORY)); - assertPermissions(() -> softwareModuleManagement.putMetaData( - List.of(entityFactory.softwareModuleMetadata().create(1L).key("key").value("value"))), List.of(SpPermission.UPDATE_REPOSITORY)); + assertPermissions(() -> { + softwareModuleManagement.createMetadata( + List.of(entityFactory.softwareModuleMetadata().create(1L).key("key").value("value"))); + return null; + }, List.of(SpPermission.UPDATE_REPOSITORY)); } @Test @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void deleteMetaDataPermissionsCheck() { assertPermissions(() -> { - softwareModuleManagement.deleteMetaData(1L, "key"); + softwareModuleManagement.deleteMetadata(1L, "key"); return null; }, List.of(SpPermission.UPDATE_REPOSITORY)); } @@ -88,19 +91,13 @@ class SoftwareManagementSecurityTest @Test @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void getMetaDataBySoftwareModuleIdPermissionsCheck() { - assertPermissions(() -> softwareModuleManagement.findMetaDataBySoftwareModuleId(1L, "key"), List.of(SpPermission.READ_REPOSITORY)); + assertPermissions(() -> softwareModuleManagement.getMetadata(1L, "key"), List.of(SpPermission.READ_REPOSITORY)); } @Test @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void findMetaDataBySoftwareModuleIdPermissionsCheck() { - assertPermissions(() -> softwareModuleManagement.findMetaDataBySoftwareModuleId(PAGE, 1L), List.of(SpPermission.READ_REPOSITORY)); - } - - @Test - @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") - void countMetaDataBySoftwareModuleIdPermissionsCheck() { - assertPermissions(() -> softwareModuleManagement.countMetaDataBySoftwareModuleId(1L), List.of(SpPermission.READ_REPOSITORY)); + assertPermissions(() -> softwareModuleManagement.getMetadata(1L), List.of(SpPermission.READ_REPOSITORY)); } @Test @@ -110,12 +107,6 @@ class SoftwareManagementSecurityTest List.of(SpPermission.READ_REPOSITORY)); } - @Test - @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") - void findMetaDataByRsqlPermissionsCheck() { - assertPermissions(() -> softwareModuleManagement.findMetaDataByRsql(1L, "key==value", PAGE), List.of(SpPermission.READ_REPOSITORY)); - } - @Test @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void findByTypePermissionsCheck() { @@ -144,7 +135,7 @@ class SoftwareManagementSecurityTest @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void updateMetaDataPermissionsCheck() { assertPermissions( - () -> softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().update(1L, "key").value("value")), + () -> softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().update(1L, "key").value("value")), List.of(SpPermission.UPDATE_REPOSITORY)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java index 9a0c706bf..b50d207a2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java @@ -29,6 +29,7 @@ import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.LockedException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.RandomGeneratedInputStream; @@ -58,6 +59,8 @@ import org.springframework.data.domain.PageRequest; @Story("Software Module Management") class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { + private static final PageRequest PAGE_REQUEST_100 = PageRequest.of(0, 100); + @Test @Description("Verifies that management get access reacts as specified on calls for non existing entities by means " + "of Optional not present.") @@ -70,7 +73,8 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(softwareModuleManagement.findByNameAndVersionAndType(NOT_EXIST_ID, NOT_EXIST_ID, osType.getId())) .isNotPresent(); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(module.getId(), NOT_EXIST_ID)).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> softwareModuleManagement.getMetadata(module.getId(), NOT_EXIST_ID)); } @Test @@ -82,57 +86,40 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy( () -> softwareModuleManagement.create(Collections - .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))), - "SoftwareModuleType"); + .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))), "SoftwareModuleType"); verifyThrownExceptionBy( () -> softwareModuleManagement - .create(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID)), - "SoftwareModuleType"); + .create(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID)), "SoftwareModuleType"); verifyThrownExceptionBy( - () -> softwareModuleManagement.updateMetaData( - entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx")), - "SoftwareModule"); + () -> softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx")), "SoftwareModule"); verifyThrownExceptionBy( - () -> softwareModuleManagement.putMetaData(Collections.singletonList( - entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))), - "SoftwareModule"); + () -> softwareModuleManagement.createMetadata(Collections.singletonList( + entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))), "SoftwareModule"); verifyThrownExceptionBy(() -> softwareModuleManagement.delete(NOT_EXIST_IDL), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Collections.singletonList(NOT_EXIST_IDL)), - "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(module.getId(), NOT_EXIST_ID), - "SoftwareModuleMetadata"); + verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Collections.singletonList(NOT_EXIST_IDL)), "SoftwareModule"); + verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetadata(NOT_EXIST_IDL, "xxx"), "SoftwareModule"); verifyThrownExceptionBy( - () -> softwareModuleManagement.updateMetaData( - entityFactory.softwareModuleMetadata().update(NOT_EXIST_IDL, "xxx").value("xxx")), - "SoftwareModule"); + () -> softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata().update(NOT_EXIST_IDL, "xxx").value("xxx")), "SoftwareModule"); verifyThrownExceptionBy( - () -> softwareModuleManagement.updateMetaData( - entityFactory.softwareModuleMetadata().update(module.getId(), NOT_EXIST_ID).value("xxx")), - "SoftwareModuleMetadata"); + () -> softwareModuleManagement.updateMetadata( + entityFactory.softwareModuleMetadata().update(module.getId(), NOT_EXIST_ID).value("xxx")), "SoftwareModuleMetadata"); - verifyThrownExceptionBy(() -> softwareModuleManagement.findByAssignedTo(NOT_EXIST_IDL, PAGE), - "DistributionSet"); + verifyThrownExceptionBy(() -> softwareModuleManagement.findByAssignedTo(NOT_EXIST_IDL, PAGE), "DistributionSet"); verifyThrownExceptionBy(() -> softwareModuleManagement.findByNameAndVersionAndType("xxx", "xxx", NOT_EXIST_IDL), "SoftwareModuleType"); - verifyThrownExceptionBy( - () -> softwareModuleManagement.findMetaDataBySoftwareModuleId(NOT_EXIST_IDL, NOT_EXIST_ID), - "SoftwareModule"); + verifyThrownExceptionBy(() -> softwareModuleManagement.getMetadata(NOT_EXIST_IDL, NOT_EXIST_ID), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.findMetaDataBySoftwareModuleId(PAGE, NOT_EXIST_IDL), - "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.findMetaDataByRsql(NOT_EXIST_IDL, "name==*", PAGE), - "SoftwareModule"); + verifyThrownExceptionBy(() -> softwareModuleManagement.getMetadata(NOT_EXIST_IDL), "SoftwareModule"); verifyThrownExceptionBy(() -> softwareModuleManagement.findByType(NOT_EXIST_IDL, PAGE), "SoftwareModule"); - verifyThrownExceptionBy( - () -> softwareModuleManagement.update(entityFactory.softwareModule().update(NOT_EXIST_IDL)), - "SoftwareModule"); + verifyThrownExceptionBy(() -> softwareModuleManagement.update(entityFactory.softwareModule().update(NOT_EXIST_IDL)), "SoftwareModule"); } @Test @@ -496,27 +483,37 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final String knownKey2 = "myKnownKey2"; final String knownValue2 = "myKnownValue2"; - final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); + final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleApp(); - assertThat(ah.getOptLockRevision()).isEqualTo(1); + assertThat(softwareModule.getOptLockRevision()).isEqualTo(1); - final SoftwareModuleMetadataCreate swMetadata1 = entityFactory.softwareModuleMetadata().create(ah.getId()) - .key(knownKey1).value(knownValue1); + final SoftwareModuleMetadataCreate swMetadata1 = entityFactory.softwareModuleMetadata() + .create(softwareModule.getId()) + .key(knownKey1) + .value(knownValue1) + .targetVisible(true); - final SoftwareModuleMetadataCreate swMetadata2 = entityFactory.softwareModuleMetadata().create(ah.getId()) - .key(knownKey2).value(knownValue2); + final SoftwareModuleMetadataCreate swMetadata2 = entityFactory.softwareModuleMetadata() + .create(softwareModule.getId()) + .key(knownKey2) + .value(knownValue2); - final List softwareModuleMetadata = softwareModuleManagement - .putMetaData(Arrays.asList(swMetadata1, swMetadata2)); + softwareModuleManagement.createMetadata(Arrays.asList(swMetadata1, swMetadata2)); - final SoftwareModule changedLockRevisionModule = softwareModuleManagement.get(ah.getId()).get(); + final SoftwareModule changedLockRevisionModule = softwareModuleManagement.get(softwareModule.getId()).get(); assertThat(changedLockRevisionModule.getOptLockRevision()).isEqualTo(2); - assertThat(softwareModuleMetadata).hasSize(2); - assertThat(softwareModuleMetadata.get(0)).isNotNull(); - assertThat(softwareModuleMetadata.get(0).getValue()).isEqualTo(knownValue1); - assertThat(((JpaSoftwareModuleMetadata) softwareModuleMetadata.get(0)).getId().getKey()).isEqualTo(knownKey1); - assertThat(softwareModuleMetadata.get(0).getEntityId()).isEqualTo(ah.getId()); + assertThat(softwareModuleManagement.getMetadata(softwareModule.getId(), knownKey1)).satisfies(metadata -> { + assertThat(metadata.getKey()).isEqualTo(knownKey1); + assertThat(metadata.getValue()).isEqualTo(knownValue1); + assertThat(metadata.isTargetVisible()).isTrue(); + }); + + assertThat(softwareModuleManagement.getMetadata(softwareModule.getId(), knownKey2)).satisfies(metadata -> { + assertThat(metadata.getKey()).isEqualTo(knownKey2); + assertThat(metadata.getValue()).isEqualTo(knownValue2); + assertThat(metadata.isTargetVisible()).isFalse(); + }); } @Test @@ -527,7 +524,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule module = testdataFactory.createSoftwareModuleApp("m1"); final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule(); for (int i = 0; i < maxMetaData; ++i) { - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(module.getId()).key("k" + i).value("v" + i)); } @@ -535,7 +532,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModuleMetadataCreate metadata = entityFactory.softwareModuleMetadata().create(module.getId()) .key("k" + maxMetaData).value("v" + maxMetaData); assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> softwareModuleManagement.updateMetaData(metadata)); + .isThrownBy(() -> softwareModuleManagement.updateMetadata(metadata)); // add multiple meta data entries at once final SoftwareModule module2 = testdataFactory.createSoftwareModuleApp("m2"); @@ -545,13 +542,13 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { } // quota exceeded assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> softwareModuleManagement.putMetaData(create)); + .isThrownBy(() -> softwareModuleManagement.createMetadata(create)); // add some meta data entries final SoftwareModule module3 = testdataFactory.createSoftwareModuleApp("m3"); final int firstHalf = Math.round((maxMetaData) / 2.f); for (int i = 0; i < firstHalf; ++i) { - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(module3.getId()).key("k" + i).value("v" + i)); } // add too many data entries @@ -562,7 +559,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { } // quota exceeded assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> softwareModuleManagement.putMetaData(create2)); + .isThrownBy(() -> softwareModuleManagement.createMetadata(create2)); } @@ -576,21 +573,21 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModuleMetadataCreate metadata = entityFactory.softwareModuleMetadata() .create(ah.getId()).key(knownKey1).value(knownValue1).targetVisible(true); - softwareModuleManagement.updateMetaData(metadata); + softwareModuleManagement.updateMetadata(metadata); assertThatExceptionOfType(EntityAlreadyExistsException.class) - .isThrownBy(() -> softwareModuleManagement.updateMetaData(metadata)) + .isThrownBy(() -> softwareModuleManagement.updateMetadata(metadata)) .withMessageContaining("Metadata").withMessageContaining(knownKey1); final String knownKey2 = "myKnownKey2"; - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey2) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey2) .value(knownValue1).targetVisible(false)); final SoftwareModuleMetadataCreate metadata2 = entityFactory.softwareModuleMetadata().create(ah.getId()) .key(knownKey2).value(knownValue1).targetVisible(true); assertThatExceptionOfType(EntityAlreadyExistsException.class) - .isThrownBy(() -> softwareModuleManagement.updateMetaData(metadata2)) + .isThrownBy(() -> softwareModuleManagement.updateMetadata(metadata2)) .withMessageContaining("Metadata").withMessageContaining(knownKey2); } @@ -608,7 +605,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(ah.getOptLockRevision()).isEqualTo(1); // create an software module meta data entry - final SoftwareModuleMetadata softwareModuleMetadata = softwareModuleManagement.updateMetaData( + final SoftwareModuleMetadata softwareModuleMetadata = softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey).value(knownValue)); assertThat(softwareModuleMetadata.isTargetVisible()).isFalse(); assertThat(softwareModuleMetadata.getValue()).isEqualTo(knownValue); @@ -619,7 +616,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(changedLockRevisionModule.getOptLockRevision()).isEqualTo(2); // update the software module metadata - final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(entityFactory + final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetadata(entityFactory .softwareModuleMetadata().update(ah.getId(), knownKey).value(knownUpdateValue).targetVisible(true)); // we are updating the sw metadata so also modifying the base software @@ -632,7 +629,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(updated.getValue()).isEqualTo(knownUpdateValue); assertThat(updated.isTargetVisible()).isTrue(); assertThat(((JpaSoftwareModuleMetadata) updated).getId().getKey()).isEqualTo(knownKey); - assertThat(updated.getEntityId()).isEqualTo(ah.getId()); + assertThat(((JpaSoftwareModuleMetadata) updated).getSoftwareModule().getId()).isEqualTo(ah.getId()); } @Test @@ -643,19 +640,18 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule swModule = testdataFactory.createSoftwareModuleApp(); - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(swModule.getId()).key(knownKey1).value(knownValue1)); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(PageRequest.of(0, 10), swModule.getId()) - .getContent()).as("Contains the created metadata element").allSatisfy(metadata -> { - assertThat(metadata.getSoftwareModule().getId()).isEqualTo(swModule.getId()); - assertThat(metadata.getKey()).isEqualTo(knownKey1); - assertThat(metadata.getValue()).isEqualTo(knownValue1); - }); + assertThat(softwareModuleManagement.getMetadata(swModule.getId())) + .as("Contains the created metadata element").allSatisfy(metadata -> { + assertThat(((JpaSoftwareModuleMetadata) metadata).getSoftwareModule().getId()).isEqualTo(swModule.getId()); + assertThat(metadata.getKey()).isEqualTo(knownKey1); + assertThat(metadata.getValue()).isEqualTo(knownValue1); + }); - softwareModuleManagement.deleteMetaData(swModule.getId(), knownKey1); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(PageRequest.of(0, 10), swModule.getId()) - .getContent()).as("Metadata elements are").isEmpty(); + softwareModuleManagement.deleteMetadata(swModule.getId(), knownKey1); + assertThat(softwareModuleManagement.getMetadata(swModule.getId())).as("Metadata elements are").isEmpty(); } @Test @@ -666,16 +662,16 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); - softwareModuleManagement.updateMetaData( + softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey1).value(knownValue1)); - assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(ah.getId(), "doesnotexist")).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> softwareModuleManagement.getMetadata(ah.getId(), "doesnotexist")); } @Test @Description("Queries and loads the metadata related to a given software module.") void findAllSoftwareModuleMetadataBySwId() { - final SoftwareModule sw1 = testdataFactory.createSoftwareModuleApp(); final int metadataCountSw1 = 8; @@ -683,38 +679,28 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final int metadataCountSw2 = 10; for (int index = 0; index < metadataCountSw1; index++) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(sw1.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(sw1.getId()) .key("key" + index).value("value" + index).targetVisible(true)); } for (int index = 0; index < metadataCountSw2; index++) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(sw2.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(sw2.getId()) .key("key" + index).value("value" + index).targetVisible(false)); } - Page metadataSw1 = softwareModuleManagement - .findMetaDataBySoftwareModuleId(PageRequest.of(0, 100), sw1.getId()); + final List metadataSw1 = softwareModuleManagement.getMetadata(sw1.getId()); + final List metadataSw2 = softwareModuleManagement.getMetadata(sw2.getId()); + assertThat(metadataSw1).hasSize(metadataCountSw1); + assertThat(metadataSw2).hasSize(metadataCountSw2); - Page metadataSw2 = softwareModuleManagement - .findMetaDataBySoftwareModuleId(PageRequest.of(0, 100), sw2.getId()); - - assertThat(metadataSw1.getNumberOfElements()).isEqualTo(metadataCountSw1); - assertThat(metadataSw1.getTotalElements()).isEqualTo(metadataCountSw1); - - assertThat(metadataSw2.getNumberOfElements()).isEqualTo(metadataCountSw2); - assertThat(metadataSw2.getTotalElements()).isEqualTo(metadataCountSw2); - - metadataSw1 = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(PageRequest.of(0, 100), - sw1.getId()); - - metadataSw2 = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(PageRequest.of(0, 100), - sw2.getId()); - - assertThat(metadataSw1.getNumberOfElements()).isEqualTo(metadataCountSw1); - assertThat(metadataSw1.getTotalElements()).isEqualTo(metadataCountSw1); - - assertThat(metadataSw2.getNumberOfElements()).isZero(); - assertThat(metadataSw2.getTotalElements()).isZero(); + final Page metadataSw1V = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible( + PAGE_REQUEST_100, sw1.getId()); + final Page metadataSw2V = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible( + PAGE_REQUEST_100, sw2.getId()); + assertThat(metadataSw1V.getNumberOfElements()).isEqualTo(metadataCountSw1); + assertThat(metadataSw1V.getTotalElements()).isEqualTo(metadataCountSw1); + assertThat(metadataSw2V.getNumberOfElements()).isZero(); + assertThat(metadataSw2V.getTotalElements()).isZero(); } @Test @@ -757,7 +743,8 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { .isTrue(); // try add - final ArtifactUpload artifactUpload = new ArtifactUpload(new ByteArrayInputStream(new byte[] { 2 }), softwareModuleId, "artifact2", false, 1); + final ArtifactUpload artifactUpload = new ArtifactUpload(new ByteArrayInputStream(new byte[] { 2 }), softwareModuleId, "artifact2", + false, 1); assertThatExceptionOfType(LockedException.class) .as("Attempt to modify a locked SM artifacts should throw an exception") .isThrownBy(() -> artifactManagement.create(artifactUpload)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java index a9a6ab018..e01d0bc41 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java @@ -51,11 +51,11 @@ class RSQLSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { final SoftwareModuleMetadataCreate softwareModuleMetadata = entityFactory.softwareModuleMetadata() .create(ah.getId()).key("metaKey").value("metaValue"); - softwareModuleManagement.updateMetaData(softwareModuleMetadata); + softwareModuleManagement.updateMetadata(softwareModuleMetadata); final SoftwareModuleMetadataCreate softwareModuleMetadata2 = entityFactory.softwareModuleMetadata() .create(ah2.getId()).key("metaKey").value("value"); - softwareModuleManagement.updateMetaData(softwareModuleMetadata2); + softwareModuleManagement.updateMetadata(softwareModuleMetadata2); } @Test diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java deleted file mode 100644 index 6a0df1c08..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.rsql; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.List; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; -import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; -import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; -import org.eclipse.hawkbit.repository.test.util.TestdataFactory; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; - -@Feature("Component Tests - Repository") -@Story("RSQL filter software module metadata") -class RSQLSoftwareModuleMetadataFieldsTest extends AbstractJpaIntegrationTest { - - private Long softwareModuleId; - - @BeforeEach - void setupBeforeTest() { - final SoftwareModule softwareModule = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_APP); - - softwareModuleId = softwareModule.getId(); - - final List metadata = new ArrayList<>(5); - for (int i = 0; i < 5; i++) { - metadata.add( - entityFactory.softwareModuleMetadata().create(softwareModule.getId()).key("" + i).value("" + i)); - } - - metadata.add(entityFactory.softwareModuleMetadata().create(softwareModule.getId()).key("targetVisible") - .value("targetVisible").targetVisible(true)); - metadata.add(entityFactory.softwareModuleMetadata().create(softwareModule.getId()).key("emptyMd") - .targetVisible(true)); - - softwareModuleManagement.putMetaData(metadata); - - } - - @Test - @Description("Test filter software module metadata by key") - void testFilterByParameterKey() { - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "==1", 1); - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "!=1", 6); - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "=in=(1,2)", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "=out=(1,2)", 5); - } - - @Test - @Description("Test fitler software module metadata by value") - void testFilterByParameterValue() { - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "==''", 1); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "!=''", 6); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "==1", 1); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "!=1", 6); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "=in=(1,2)", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "=out=(1,2)", 5); - } - - @Test - @Description("Test fitler software module metadata by target visible") - void testFilterByParameterTargetVisible() { - assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "==true", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "==false", 5); - assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "!=false", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "!=true", 5); - } - - private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) { - - final Page findEnitity = softwareModuleManagement - .findMetaDataByRsql(softwareModuleId, rsqlParam, PageRequest.of(0, 100)); - final long countAllEntities = findEnitity.getTotalElements(); - assertThat(findEnitity).isNotNull(); - assertThat(countAllEntities).isEqualTo(expectedEntities); - } -} diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index bd579b2e0..77c3387fa 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -21,7 +21,6 @@ import java.time.ZonedDateTime; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.NoSuchElementException; import lombok.extern.slf4j.Slf4j; @@ -58,7 +57,6 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.RepositoryModelConstants; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Target; diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TargetTestData.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TargetTestData.java index 5fe8650cf..756fa5dcb 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TargetTestData.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TargetTestData.java @@ -23,10 +23,10 @@ public class TargetTestData { static { final Random rand = new SecureRandom(); - ATTRIBUTE_KEY_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE + 1, rand); - ATTRIBUTE_KEY_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE, rand); - ATTRIBUTE_VALUE_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE + 1, rand); - ATTRIBUTE_VALUE_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE, rand); + ATTRIBUTE_KEY_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE + 1, rand); + ATTRIBUTE_KEY_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE, rand); + ATTRIBUTE_VALUE_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE + 1, rand); + ATTRIBUTE_VALUE_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_MAX_VALUE_SIZE, rand); } private TargetTestData() { diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index 710917ae6..3d7f39c03 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -1210,9 +1210,9 @@ public class TestdataFactory { } private void addTestModuleMetadata(final SoftwareModule module) { - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) .key(VISIBLE_SM_MD_KEY).value(VISIBLE_SM_MD_VALUE).targetVisible(true)); - softwareModuleManagement.updateMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) .key(INVISIBLE_SM_MD_KEY).value(INVISIBLE_SM_MD_VALUE).targetVisible(false)); }