From d4d4fb80558a8f53014ff2e26d81c6481c96c9a7 Mon Sep 17 00:00:00 2001 From: valeriuc Date: Wed, 18 Mar 2026 16:07:29 +0100 Subject: [PATCH 1/7] Add api-project-component-v0 module. --- .../openapi/api-project-component-v0.yaml | 166 +++++++++ api-project-component-v0/pom.xml | 163 +++++++++ .../project/api/ProjectComponentsApi.java | 118 +++++++ .../controller/ComponentsResponseFactory.java | 29 ++ .../ProjectComponentsController.java | 49 +++ .../apiservice/project/model/Component.java | 324 ++++++++++++++++++ .../project/model/CreateComponentRequest.java | 143 ++++++++ .../model/CreateComponentResponse.java | 156 +++++++++ .../project/service/ComponentsService.java | 42 +++ .../ProjectComponentsControllerTest.java | 93 +++++ .../service/ComponentsServiceTest.java | 75 ++++ .../apiservice/project/util/TestHelper.java | 40 +++ pom.xml | 1 + 13 files changed, 1399 insertions(+) create mode 100644 api-project-component-v0/openapi/api-project-component-v0.yaml create mode 100644 api-project-component-v0/pom.xml create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java create mode 100644 api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java create mode 100644 api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java create mode 100644 api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java diff --git a/api-project-component-v0/openapi/api-project-component-v0.yaml b/api-project-component-v0/openapi/api-project-component-v0.yaml new file mode 100644 index 0000000..dcd3912 --- /dev/null +++ b/api-project-component-v0/openapi/api-project-component-v0.yaml @@ -0,0 +1,166 @@ +openapi: 3.0.3 +info: + title: ODS API Server + description: API documentation for ODS (Open DevStack) API Service + contact: + name: ODS Team + version: v0.0.1 +servers: + - url: http://{baseurl}/api/pub/v0 + variables: + baseurl: + default: localhost:8080 + description: Development environment +tags: + - name: ProjectComponents + description: API for managing project components + +paths: + /projects/{projectId}/components/: + post: + tags: + - projectComponents + summary: Create a component in a project + operationId: createProjectComponent + description: Retrieves information about a specific component + parameters: + - name: projectId + in: path + required: true + description: Project id + schema: + type: string + requestBody: + description: Component data + content: + application/json: + schema: + $ref: '#/components/schemas/CreateComponentRequest' + responses: + '201': + description: Created + headers: + Location: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/CreateComponentResponse' + '400': + description: Bad Request + '401': + $ref: '#/components/responses/UnauthorizedError' + '403': + description: Forbidden + '404': + description: Endpoint not found / Project not found / Product not found + '500': + description: Internal Server Error + + /projects/{projectId}/components/{componentId}: + get: + tags: + - projectComponents + summary: Get component information + operationId: getProjectComponent + description: Retrieves information about a specific component + parameters: + - name: projectId + in: path + required: true + description: Project id + schema: + type: string + - name: componentId + in: path + required: true + description: Component id + schema: + type: string + responses: + '200': + description: Component information + content: + application/json: + schema: + $ref: '#/components/schemas/Component' + +components: + securitySchemes: + basicAuth: + type: http + scheme: basic + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + responses: + UnauthorizedError: + description: Authentication information is missing or invalid + headers: + WWW_Authenticate: + schema: + type: string + schemas: + Component: + type: object + properties: + id: + type: string + description: Component ID + name: + type: string + description: Name of the component + productDescription: + type: string + description: Description of the product + productName: + type: string + description: Name of the product (e.g. Docker plain) + productId: + type: string + description: Product ID + environment: + type: string + description: Environment (e.g. DEV) + status: + type: string + description: Status of the component (e.g. READY, NOT_READY) + resultTraceback: + type: string + description: Traceback information in case of error + repositoryURL: + type: string + description: URL of the repository (for ODS products) + params: + type: object + description: Additional parameters (key-value pairs) + component-type: + type: string + description: Type of component (ods|awx) + CreateComponentResponse: + type: object + properties: + errorCode: + type: integer + field: + type: string + message: + type: string + location: + type: string + format: url + CreateComponentRequest: + type: object + properties: + name: + type: string + description: component name + productId: + type: string + description: product id + params: + type: object + additionalProperties: + type: string \ No newline at end of file diff --git a/api-project-component-v0/pom.xml b/api-project-component-v0/pom.xml new file mode 100644 index 0000000..a3f50df --- /dev/null +++ b/api-project-component-v0/pom.xml @@ -0,0 +1,163 @@ + + 4.0.0 + + + org.opendevstack.apiservice + devstack-api-service + 0.0.3 + + + api-project-component-v0 + API Project Components V0 + API module for managing EDP project components + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + + + + org.opendevstack.apiservice + service-projects + ${project.version} + + + + io.jsonwebtoken + jjwt-api + 0.12.3 + + + + io.jsonwebtoken + jjwt-impl + 0.12.3 + runtime + + + + io.jsonwebtoken + jjwt-jackson + 0.12.3 + runtime + + + + org.projectlombok + lombok + provided + + + + org.mapstruct + mapstruct + 1.6.3 + + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable.version} + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-core + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + 1.6.3 + + + + + + org.openapitools + openapi-generator-maven-plugin + + + generate-api-project-component-v0 + + generate + + + spring + ${project.basedir} + spring-boot + ${project.basedir}/openapi/api-project-component-v0.yaml + org.opendevstack.apiservice.project.api + org.opendevstack.apiservice.project.model + org.opendevstack.apiservice.project + false + false + false + false + false + false + + true + true + springdoc + true + true + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + \ No newline at end of file diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java new file mode 100644 index 0000000..61b6df0 --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java @@ -0,0 +1,118 @@ +/* + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.15.0). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.opendevstack.apiservice.project.api; + +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import io.swagger.v3.oas.annotations.ExternalDocumentation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.lang.Nullable; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import jakarta.annotation.Generated; + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") +@Validated +@Tag(name = "projectComponents", description = "the projectComponents API") +public interface ProjectComponentsApi { + + public static final String PATH_CREATE_PROJECT_COMPONENT = "/projects/{projectId}/components/"; + /** + * POST /projects/{projectId}/components/ : Create a component in a project + * Retrieves information about a specific component + * + * @param projectId Project id (required) + * @param createComponentRequest Component data (optional) + * @return Created (status code 201) + * or Bad Request (status code 400) + * or Authentication information is missing or invalid (status code 401) + * or Forbidden (status code 403) + * or Endpoint not found / Project not found / Product not found (status code 404) + * or Internal Server Error (status code 500) + */ + @Operation( + operationId = "createProjectComponent", + summary = "Create a component in a project", + description = "Retrieves information about a specific component", + tags = { "projectComponents" }, + responses = { + @ApiResponse(responseCode = "201", description = "Created", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = CreateComponentResponse.class)) + }), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "401", description = "Authentication information is missing or invalid"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Endpoint not found / Project not found / Product not found"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = ProjectComponentsApi.PATH_CREATE_PROJECT_COMPONENT, + produces = { "application/json" }, + consumes = { "application/json" } + ) + + ResponseEntity createProjectComponent( + @Parameter(name = "projectId", description = "Project id", required = true, in = ParameterIn.PATH) @PathVariable("projectId") String projectId, + @Parameter(name = "CreateComponentRequest", description = "Component data") @Valid @RequestBody(required = false) @Nullable CreateComponentRequest createComponentRequest + ); + + + public static final String PATH_GET_PROJECT_COMPONENT = "/projects/{projectId}/components/{componentId}"; + /** + * GET /projects/{projectId}/components/{componentId} : Get component information + * Retrieves information about a specific component + * + * @param projectId Project id (required) + * @param componentId Component id (required) + * @return Component information (status code 200) + */ + @Operation( + operationId = "getProjectComponent", + summary = "Get component information", + description = "Retrieves information about a specific component", + tags = { "projectComponents" }, + responses = { + @ApiResponse(responseCode = "200", description = "Component information", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = Component.class)) + }) + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = ProjectComponentsApi.PATH_GET_PROJECT_COMPONENT, + produces = { "application/json" } + ) + + ResponseEntity getProjectComponent( + @Parameter(name = "projectId", description = "Project id", required = true, in = ParameterIn.PATH) @PathVariable("projectId") String projectId, + @Parameter(name = "componentId", description = "Component id", required = true, in = ParameterIn.PATH) @PathVariable("componentId") String componentId + ); + +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java new file mode 100644 index 0000000..de9cd3b --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java @@ -0,0 +1,29 @@ +package org.opendevstack.apiservice.project.controller; + +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +public class ComponentsResponseFactory { + + private ComponentsResponseFactory() { + } + + public static CreateComponentResponse error(String projectId) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setMessage("Failed to create component for project '" + projectId); + return response; + } + + public static CreateComponentResponse entityCreated(String projectId, String componentName) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.CREATED.value()); + response.setMessage(componentName + " component created successfully in project " + projectId); + return response; + } + + public static ResponseEntity toResponseEntity(CreateComponentResponse response) { + return new ResponseEntity(response, HttpStatus.valueOf(response.getErrorCode())); + } +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java new file mode 100644 index 0000000..b2106bb --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java @@ -0,0 +1,49 @@ +package org.opendevstack.apiservice.project.controller; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.opendevstack.apiservice.project.api.ProjectComponentsApi; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.opendevstack.apiservice.project.service.ComponentsService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import static org.opendevstack.apiservice.project.controller.ComponentsResponseFactory.toResponseEntity; + +@RestController +@AllArgsConstructor +@Slf4j +public class ProjectComponentsController implements ProjectComponentsApi { + + private final ComponentsService componentsService; + + @Override + public ResponseEntity createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + try { + Component component = componentsService.createProjectComponent(projectId, createComponentRequest); + if (component == null) { + log.error("Failed to create component for project '{}'", projectId); + return toResponseEntity(ComponentsResponseFactory.error(projectId)); + } + return toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); + } catch (Exception e) { + log.error("Error while trying to create component for project '" + projectId + "': " + e.getMessage(), e); + return toResponseEntity(ComponentsResponseFactory.error(projectId)); + } + } + + @Override + public ResponseEntity getProjectComponent(String projectId, String componentId) { + try { + Component component = componentsService.getProjectComponent(projectId, componentId); + return component != null ? + ResponseEntity.ok(component) : ResponseEntity.notFound().build(); + } catch (Exception e) { + log.error("Error retrieving component '{}' for project '{}': {}", componentId, projectId, e.getMessage(), e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value()).build(); + } + } +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java new file mode 100644 index 0000000..a2d943f --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java @@ -0,0 +1,324 @@ +package org.opendevstack.apiservice.project.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * Component + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") +public class Component { + + private @Nullable String id; + + private @Nullable String name; + + private @Nullable String productDescription; + + private @Nullable String productName; + + private @Nullable String productId; + + private @Nullable String environment; + + private @Nullable String status; + + private @Nullable String resultTraceback; + + private @Nullable String repositoryURL; + + private @Nullable Object params; + + private @Nullable String componentType; + + public Component id(@Nullable String id) { + this.id = id; + return this; + } + + /** + * Component ID + * @return id + */ + + @Schema(name = "id", description = "Component ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("id") + public @Nullable String getId() { + return id; + } + + public void setId(@Nullable String id) { + this.id = id; + } + + public Component name(@Nullable String name) { + this.name = name; + return this; + } + + /** + * Name of the component + * @return name + */ + + @Schema(name = "name", description = "Name of the component", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("name") + public @Nullable String getName() { + return name; + } + + public void setName(@Nullable String name) { + this.name = name; + } + + public Component productDescription(@Nullable String productDescription) { + this.productDescription = productDescription; + return this; + } + + /** + * Description of the product + * @return productDescription + */ + + @Schema(name = "productDescription", description = "Description of the product", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("productDescription") + public @Nullable String getProductDescription() { + return productDescription; + } + + public void setProductDescription(@Nullable String productDescription) { + this.productDescription = productDescription; + } + + public Component productName(@Nullable String productName) { + this.productName = productName; + return this; + } + + /** + * Name of the product (e.g. Docker plain) + * @return productName + */ + + @Schema(name = "productName", description = "Name of the product (e.g. Docker plain)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("productName") + public @Nullable String getProductName() { + return productName; + } + + public void setProductName(@Nullable String productName) { + this.productName = productName; + } + + public Component productId(@Nullable String productId) { + this.productId = productId; + return this; + } + + /** + * Product ID + * @return productId + */ + + @Schema(name = "productId", description = "Product ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("productId") + public @Nullable String getProductId() { + return productId; + } + + public void setProductId(@Nullable String productId) { + this.productId = productId; + } + + public Component environment(@Nullable String environment) { + this.environment = environment; + return this; + } + + /** + * Environment (e.g. DEV) + * @return environment + */ + + @Schema(name = "environment", description = "Environment (e.g. DEV)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("environment") + public @Nullable String getEnvironment() { + return environment; + } + + public void setEnvironment(@Nullable String environment) { + this.environment = environment; + } + + public Component status(@Nullable String status) { + this.status = status; + return this; + } + + /** + * Status of the component (e.g. READY, NOT_READY) + * @return status + */ + + @Schema(name = "status", description = "Status of the component (e.g. READY, NOT_READY)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("status") + public @Nullable String getStatus() { + return status; + } + + public void setStatus(@Nullable String status) { + this.status = status; + } + + public Component resultTraceback(@Nullable String resultTraceback) { + this.resultTraceback = resultTraceback; + return this; + } + + /** + * Traceback information in case of error + * @return resultTraceback + */ + + @Schema(name = "resultTraceback", description = "Traceback information in case of error", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("resultTraceback") + public @Nullable String getResultTraceback() { + return resultTraceback; + } + + public void setResultTraceback(@Nullable String resultTraceback) { + this.resultTraceback = resultTraceback; + } + + public Component repositoryURL(@Nullable String repositoryURL) { + this.repositoryURL = repositoryURL; + return this; + } + + /** + * URL of the repository (for ODS products) + * @return repositoryURL + */ + + @Schema(name = "repositoryURL", description = "URL of the repository (for ODS products)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("repositoryURL") + public @Nullable String getRepositoryURL() { + return repositoryURL; + } + + public void setRepositoryURL(@Nullable String repositoryURL) { + this.repositoryURL = repositoryURL; + } + + public Component params(@Nullable Object params) { + this.params = params; + return this; + } + + /** + * Additional parameters (key-value pairs) + * @return params + */ + + @Schema(name = "params", description = "Additional parameters (key-value pairs)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("params") + public @Nullable Object getParams() { + return params; + } + + public void setParams(@Nullable Object params) { + this.params = params; + } + + public Component componentType(@Nullable String componentType) { + this.componentType = componentType; + return this; + } + + /** + * Type of component (ods|awx) + * @return componentType + */ + + @Schema(name = "component-type", description = "Type of component (ods|awx)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("component-type") + public @Nullable String getComponentType() { + return componentType; + } + + public void setComponentType(@Nullable String componentType) { + this.componentType = componentType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Component component = (Component) o; + return Objects.equals(this.id, component.id) && + Objects.equals(this.name, component.name) && + Objects.equals(this.productDescription, component.productDescription) && + Objects.equals(this.productName, component.productName) && + Objects.equals(this.productId, component.productId) && + Objects.equals(this.environment, component.environment) && + Objects.equals(this.status, component.status) && + Objects.equals(this.resultTraceback, component.resultTraceback) && + Objects.equals(this.repositoryURL, component.repositoryURL) && + Objects.equals(this.params, component.params) && + Objects.equals(this.componentType, component.componentType); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, productDescription, productName, productId, environment, status, resultTraceback, repositoryURL, params, componentType); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Component {\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" productDescription: ").append(toIndentedString(productDescription)).append("\n"); + sb.append(" productName: ").append(toIndentedString(productName)).append("\n"); + sb.append(" productId: ").append(toIndentedString(productId)).append("\n"); + sb.append(" environment: ").append(toIndentedString(environment)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" resultTraceback: ").append(toIndentedString(resultTraceback)).append("\n"); + sb.append(" repositoryURL: ").append(toIndentedString(repositoryURL)).append("\n"); + sb.append(" params: ").append(toIndentedString(params)).append("\n"); + sb.append(" componentType: ").append(toIndentedString(componentType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java new file mode 100644 index 0000000..c19af9f --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java @@ -0,0 +1,143 @@ +package org.opendevstack.apiservice.project.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * CreateComponentRequest + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") +public class CreateComponentRequest { + + private @Nullable String name; + + private @Nullable String productId; + + @Valid + private Map params = new HashMap<>(); + + public CreateComponentRequest name(@Nullable String name) { + this.name = name; + return this; + } + + /** + * component name + * @return name + */ + + @Schema(name = "name", description = "component name", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("name") + public @Nullable String getName() { + return name; + } + + public void setName(@Nullable String name) { + this.name = name; + } + + public CreateComponentRequest productId(@Nullable String productId) { + this.productId = productId; + return this; + } + + /** + * product id + * @return productId + */ + + @Schema(name = "productId", description = "product id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("productId") + public @Nullable String getProductId() { + return productId; + } + + public void setProductId(@Nullable String productId) { + this.productId = productId; + } + + public CreateComponentRequest params(Map params) { + this.params = params; + return this; + } + + public CreateComponentRequest putParamsItem(String key, String paramsItem) { + if (this.params == null) { + this.params = new HashMap<>(); + } + this.params.put(key, paramsItem); + return this; + } + + /** + * Get params + * @return params + */ + + @Schema(name = "params", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("params") + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CreateComponentRequest createComponentRequest = (CreateComponentRequest) o; + return Objects.equals(this.name, createComponentRequest.name) && + Objects.equals(this.productId, createComponentRequest.productId) && + Objects.equals(this.params, createComponentRequest.params); + } + + @Override + public int hashCode() { + return Objects.hash(name, productId, params); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CreateComponentRequest {\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" productId: ").append(toIndentedString(productId)).append("\n"); + sb.append(" params: ").append(toIndentedString(params)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java new file mode 100644 index 0000000..e9313aa --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java @@ -0,0 +1,156 @@ +package org.opendevstack.apiservice.project.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * CreateComponentResponse + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") +public class CreateComponentResponse { + + private @Nullable Integer errorCode; + + private @Nullable String field; + + private @Nullable String message; + + private @Nullable String location; + + public CreateComponentResponse errorCode(@Nullable Integer errorCode) { + this.errorCode = errorCode; + return this; + } + + /** + * Get errorCode + * @return errorCode + */ + + @Schema(name = "errorCode", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("errorCode") + public @Nullable Integer getErrorCode() { + return errorCode; + } + + public void setErrorCode(@Nullable Integer errorCode) { + this.errorCode = errorCode; + } + + public CreateComponentResponse field(@Nullable String field) { + this.field = field; + return this; + } + + /** + * Get field + * @return field + */ + + @Schema(name = "field", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("field") + public @Nullable String getField() { + return field; + } + + public void setField(@Nullable String field) { + this.field = field; + } + + public CreateComponentResponse message(@Nullable String message) { + this.message = message; + return this; + } + + /** + * Get message + * @return message + */ + + @Schema(name = "message", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("message") + public @Nullable String getMessage() { + return message; + } + + public void setMessage(@Nullable String message) { + this.message = message; + } + + public CreateComponentResponse location(@Nullable String location) { + this.location = location; + return this; + } + + /** + * Get location + * @return location + */ + + @Schema(name = "location", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("location") + public @Nullable String getLocation() { + return location; + } + + public void setLocation(@Nullable String location) { + this.location = location; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CreateComponentResponse createComponentResponse = (CreateComponentResponse) o; + return Objects.equals(this.errorCode, createComponentResponse.errorCode) && + Objects.equals(this.field, createComponentResponse.field) && + Objects.equals(this.message, createComponentResponse.message) && + Objects.equals(this.location, createComponentResponse.location); + } + + @Override + public int hashCode() { + return Objects.hash(errorCode, field, message, location); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CreateComponentResponse {\n"); + sb.append(" errorCode: ").append(toIndentedString(errorCode)).append("\n"); + sb.append(" field: ").append(toIndentedString(field)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" location: ").append(toIndentedString(location)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java new file mode 100644 index 0000000..0125d81 --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java @@ -0,0 +1,42 @@ +package org.opendevstack.apiservice.project.service; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.opendevstack.apiservice.externalservice.api.ExternalService; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +@Slf4j +public class ComponentsService { + + private final MarketplaceExternalServicePlaceholder marketplaceExternalService; + + public Component getProjectComponent(String projectId, String componentId) { + return marketplaceExternalService.getProjectComponent(projectId, componentId); + } + + public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + return marketplaceExternalService.createProjectComponent(projectId, createComponentRequest); + } + + //TODO replace this with actual external service implementations and remove the placeholder + @Service + class MarketplaceExternalServicePlaceholder implements ExternalService { + + @Override + public boolean isHealthy() { + return false; + } + + public Component getProjectComponent(String projectId, String componentId) { + return null; + } + + public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + return null; + } + } +} diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java new file mode 100644 index 0000000..b4a3ff9 --- /dev/null +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java @@ -0,0 +1,93 @@ +package org.opendevstack.apiservice.project.controller; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.opendevstack.apiservice.project.service.ComponentsService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.opendevstack.apiservice.project.util.TestHelper.*; + +@ExtendWith(MockitoExtension.class) +class ProjectComponentsControllerTest { + + @Mock + private ComponentsService componentsService; + + private ProjectComponentsController projectComponentsController; + + @BeforeEach + void setup() { + projectComponentsController = new ProjectComponentsController(componentsService); + } + + @Test + void testCreateProjectComponent_whenSuccess_thenReturnOk() throws Exception { + Component testComponent = buildTestComponent(); + CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); + CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(); + + when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) + .thenReturn(testComponent); + + ResponseEntity response = projectComponentsController.createProjectComponent("testId", + testCreateComponentRequest); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().equals(testServiceResponseSuccess)); + } + + @Test + void testCreateProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { + CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); + CreateComponentResponse testServiceResponseFailure = buildTestCreateComponentResponseFailure(); + + when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) + .thenReturn(null); + + ResponseEntity response = projectComponentsController.createProjectComponent("projectId", + testCreateComponentRequest); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().equals(testServiceResponseFailure)); + } + + @Test + void testGetProjectComponent_whenSuccess_thenReturnOk() throws Exception { + Component testComponent = buildTestComponent(); + + when(componentsService.getProjectComponent(anyString(), anyString())) + .thenReturn(testComponent); + + ResponseEntity response = projectComponentsController.getProjectComponent("projectId", + "testId"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().equals(testComponent)); + } + + @Test + void testGetProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { + when(componentsService.getProjectComponent(anyString(), anyString())) + .thenReturn(null); + + ResponseEntity response = projectComponentsController.getProjectComponent("projectId", + "testId"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(response.getBody()).isNull(); + } +} \ No newline at end of file diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java new file mode 100644 index 0000000..dac538f --- /dev/null +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java @@ -0,0 +1,75 @@ +package org.opendevstack.apiservice.project.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.opendevstack.apiservice.project.util.TestHelper.buildTestComponent; +import static org.opendevstack.apiservice.project.util.TestHelper.buildTestCreateComponentRequest; + +@ExtendWith(MockitoExtension.class) +class ComponentsServiceTest { + + //TODO update this with actual marketplace service mocks once implemented and remove the placeholder + @Mock + private ComponentsService.MarketplaceExternalServicePlaceholder marketPlaceExternalServicePlaceholder; + + private ComponentsService componentsService; + + @BeforeEach + void setup() { + componentsService = new ComponentsService(marketPlaceExternalServicePlaceholder); + } + + @Test + void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { + Component testComponent = buildTestComponent(); + + when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + .thenReturn(testComponent); + + Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); + assertThat(retrievedComponent).isEqualTo(testComponent); + } + + @Test + void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Exception { + when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + .thenReturn(null); + + Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); + assertThat(retrievedComponent).isEqualTo(null); + } + + @Test + void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { + Component testComponent = buildTestComponent(); + CreateComponentRequest testRequest = buildTestCreateComponentRequest(); + + when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + .thenReturn(testComponent); + + Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); + assertThat(retrievedComponent).isEqualTo(testComponent); + } + + + @Test + void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { + CreateComponentRequest testRequest = buildTestCreateComponentRequest(); + + when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + .thenReturn(null); + + Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); + assertThat(retrievedComponent).isEqualTo(null); + } +} \ No newline at end of file diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java new file mode 100644 index 0000000..e6a26a9 --- /dev/null +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java @@ -0,0 +1,40 @@ +package org.opendevstack.apiservice.project.util; + +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; + +public class TestHelper { + + public static Component buildTestComponent() { + Component component = new Component(); + component.setId("testId"); + component.setName("testComponentName"); + component.environment("testEnv"); + component.setComponentType("testComponentType"); + return component; + } + + public static CreateComponentRequest buildTestCreateComponentRequest() { + CreateComponentRequest request = new CreateComponentRequest(); + request.setName("testComponentName"); + request.setProductId("testProductId"); + return request; + } + + public static CreateComponentResponse buildTestCreateComponentResponseSuccess() { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.CREATED.value()); + response.setMessage("success"); + return response; + } + + public static CreateComponentResponse buildTestCreateComponentResponseFailure() { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setMessage("failure"); + return response; + } +} diff --git a/pom.xml b/pom.xml index c825aa0..6382c31 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,7 @@ api-project-users api-project-platform api-project + api-project-component-v0 From 62d163f48095355cb4b0467419db883d12f48759 Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Thu, 19 Mar 2026 16:14:36 +0100 Subject: [PATCH 2/7] Remove generated files. --- .../project/api/ProjectComponentsApi.java | 118 ------- .../apiservice/project/model/Component.java | 324 ------------------ .../project/model/CreateComponentRequest.java | 143 -------- .../model/CreateComponentResponse.java | 156 --------- 4 files changed, 741 deletions(-) delete mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java delete mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java delete mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java delete mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java deleted file mode 100644 index 61b6df0..0000000 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api/ProjectComponentsApi.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.15.0). - * https://openapi-generator.tech - * Do not edit the class manually. - */ -package org.opendevstack.apiservice.project.api; - -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; -import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import io.swagger.v3.oas.annotations.ExternalDocumentation; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.lang.Nullable; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.multipart.MultipartFile; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.*; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import jakarta.annotation.Generated; - -@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") -@Validated -@Tag(name = "projectComponents", description = "the projectComponents API") -public interface ProjectComponentsApi { - - public static final String PATH_CREATE_PROJECT_COMPONENT = "/projects/{projectId}/components/"; - /** - * POST /projects/{projectId}/components/ : Create a component in a project - * Retrieves information about a specific component - * - * @param projectId Project id (required) - * @param createComponentRequest Component data (optional) - * @return Created (status code 201) - * or Bad Request (status code 400) - * or Authentication information is missing or invalid (status code 401) - * or Forbidden (status code 403) - * or Endpoint not found / Project not found / Product not found (status code 404) - * or Internal Server Error (status code 500) - */ - @Operation( - operationId = "createProjectComponent", - summary = "Create a component in a project", - description = "Retrieves information about a specific component", - tags = { "projectComponents" }, - responses = { - @ApiResponse(responseCode = "201", description = "Created", content = { - @Content(mediaType = "application/json", schema = @Schema(implementation = CreateComponentResponse.class)) - }), - @ApiResponse(responseCode = "400", description = "Bad Request"), - @ApiResponse(responseCode = "401", description = "Authentication information is missing or invalid"), - @ApiResponse(responseCode = "403", description = "Forbidden"), - @ApiResponse(responseCode = "404", description = "Endpoint not found / Project not found / Product not found"), - @ApiResponse(responseCode = "500", description = "Internal Server Error") - } - ) - @RequestMapping( - method = RequestMethod.POST, - value = ProjectComponentsApi.PATH_CREATE_PROJECT_COMPONENT, - produces = { "application/json" }, - consumes = { "application/json" } - ) - - ResponseEntity createProjectComponent( - @Parameter(name = "projectId", description = "Project id", required = true, in = ParameterIn.PATH) @PathVariable("projectId") String projectId, - @Parameter(name = "CreateComponentRequest", description = "Component data") @Valid @RequestBody(required = false) @Nullable CreateComponentRequest createComponentRequest - ); - - - public static final String PATH_GET_PROJECT_COMPONENT = "/projects/{projectId}/components/{componentId}"; - /** - * GET /projects/{projectId}/components/{componentId} : Get component information - * Retrieves information about a specific component - * - * @param projectId Project id (required) - * @param componentId Component id (required) - * @return Component information (status code 200) - */ - @Operation( - operationId = "getProjectComponent", - summary = "Get component information", - description = "Retrieves information about a specific component", - tags = { "projectComponents" }, - responses = { - @ApiResponse(responseCode = "200", description = "Component information", content = { - @Content(mediaType = "application/json", schema = @Schema(implementation = Component.class)) - }) - } - ) - @RequestMapping( - method = RequestMethod.GET, - value = ProjectComponentsApi.PATH_GET_PROJECT_COMPONENT, - produces = { "application/json" } - ) - - ResponseEntity getProjectComponent( - @Parameter(name = "projectId", description = "Project id", required = true, in = ParameterIn.PATH) @PathVariable("projectId") String projectId, - @Parameter(name = "componentId", description = "Component id", required = true, in = ParameterIn.PATH) @PathVariable("componentId") String componentId - ); - -} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java deleted file mode 100644 index a2d943f..0000000 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/Component.java +++ /dev/null @@ -1,324 +0,0 @@ -package org.opendevstack.apiservice.project.model; - -import java.net.URI; -import java.util.Objects; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import org.springframework.lang.Nullable; -import org.openapitools.jackson.nullable.JsonNullable; -import java.time.OffsetDateTime; -import jakarta.validation.Valid; -import jakarta.validation.constraints.*; -import io.swagger.v3.oas.annotations.media.Schema; - - -import java.util.*; -import jakarta.annotation.Generated; - -/** - * Component - */ - -@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") -public class Component { - - private @Nullable String id; - - private @Nullable String name; - - private @Nullable String productDescription; - - private @Nullable String productName; - - private @Nullable String productId; - - private @Nullable String environment; - - private @Nullable String status; - - private @Nullable String resultTraceback; - - private @Nullable String repositoryURL; - - private @Nullable Object params; - - private @Nullable String componentType; - - public Component id(@Nullable String id) { - this.id = id; - return this; - } - - /** - * Component ID - * @return id - */ - - @Schema(name = "id", description = "Component ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("id") - public @Nullable String getId() { - return id; - } - - public void setId(@Nullable String id) { - this.id = id; - } - - public Component name(@Nullable String name) { - this.name = name; - return this; - } - - /** - * Name of the component - * @return name - */ - - @Schema(name = "name", description = "Name of the component", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("name") - public @Nullable String getName() { - return name; - } - - public void setName(@Nullable String name) { - this.name = name; - } - - public Component productDescription(@Nullable String productDescription) { - this.productDescription = productDescription; - return this; - } - - /** - * Description of the product - * @return productDescription - */ - - @Schema(name = "productDescription", description = "Description of the product", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("productDescription") - public @Nullable String getProductDescription() { - return productDescription; - } - - public void setProductDescription(@Nullable String productDescription) { - this.productDescription = productDescription; - } - - public Component productName(@Nullable String productName) { - this.productName = productName; - return this; - } - - /** - * Name of the product (e.g. Docker plain) - * @return productName - */ - - @Schema(name = "productName", description = "Name of the product (e.g. Docker plain)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("productName") - public @Nullable String getProductName() { - return productName; - } - - public void setProductName(@Nullable String productName) { - this.productName = productName; - } - - public Component productId(@Nullable String productId) { - this.productId = productId; - return this; - } - - /** - * Product ID - * @return productId - */ - - @Schema(name = "productId", description = "Product ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("productId") - public @Nullable String getProductId() { - return productId; - } - - public void setProductId(@Nullable String productId) { - this.productId = productId; - } - - public Component environment(@Nullable String environment) { - this.environment = environment; - return this; - } - - /** - * Environment (e.g. DEV) - * @return environment - */ - - @Schema(name = "environment", description = "Environment (e.g. DEV)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("environment") - public @Nullable String getEnvironment() { - return environment; - } - - public void setEnvironment(@Nullable String environment) { - this.environment = environment; - } - - public Component status(@Nullable String status) { - this.status = status; - return this; - } - - /** - * Status of the component (e.g. READY, NOT_READY) - * @return status - */ - - @Schema(name = "status", description = "Status of the component (e.g. READY, NOT_READY)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("status") - public @Nullable String getStatus() { - return status; - } - - public void setStatus(@Nullable String status) { - this.status = status; - } - - public Component resultTraceback(@Nullable String resultTraceback) { - this.resultTraceback = resultTraceback; - return this; - } - - /** - * Traceback information in case of error - * @return resultTraceback - */ - - @Schema(name = "resultTraceback", description = "Traceback information in case of error", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("resultTraceback") - public @Nullable String getResultTraceback() { - return resultTraceback; - } - - public void setResultTraceback(@Nullable String resultTraceback) { - this.resultTraceback = resultTraceback; - } - - public Component repositoryURL(@Nullable String repositoryURL) { - this.repositoryURL = repositoryURL; - return this; - } - - /** - * URL of the repository (for ODS products) - * @return repositoryURL - */ - - @Schema(name = "repositoryURL", description = "URL of the repository (for ODS products)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("repositoryURL") - public @Nullable String getRepositoryURL() { - return repositoryURL; - } - - public void setRepositoryURL(@Nullable String repositoryURL) { - this.repositoryURL = repositoryURL; - } - - public Component params(@Nullable Object params) { - this.params = params; - return this; - } - - /** - * Additional parameters (key-value pairs) - * @return params - */ - - @Schema(name = "params", description = "Additional parameters (key-value pairs)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("params") - public @Nullable Object getParams() { - return params; - } - - public void setParams(@Nullable Object params) { - this.params = params; - } - - public Component componentType(@Nullable String componentType) { - this.componentType = componentType; - return this; - } - - /** - * Type of component (ods|awx) - * @return componentType - */ - - @Schema(name = "component-type", description = "Type of component (ods|awx)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("component-type") - public @Nullable String getComponentType() { - return componentType; - } - - public void setComponentType(@Nullable String componentType) { - this.componentType = componentType; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Component component = (Component) o; - return Objects.equals(this.id, component.id) && - Objects.equals(this.name, component.name) && - Objects.equals(this.productDescription, component.productDescription) && - Objects.equals(this.productName, component.productName) && - Objects.equals(this.productId, component.productId) && - Objects.equals(this.environment, component.environment) && - Objects.equals(this.status, component.status) && - Objects.equals(this.resultTraceback, component.resultTraceback) && - Objects.equals(this.repositoryURL, component.repositoryURL) && - Objects.equals(this.params, component.params) && - Objects.equals(this.componentType, component.componentType); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, productDescription, productName, productId, environment, status, resultTraceback, repositoryURL, params, componentType); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class Component {\n"); - sb.append(" id: ").append(toIndentedString(id)).append("\n"); - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" productDescription: ").append(toIndentedString(productDescription)).append("\n"); - sb.append(" productName: ").append(toIndentedString(productName)).append("\n"); - sb.append(" productId: ").append(toIndentedString(productId)).append("\n"); - sb.append(" environment: ").append(toIndentedString(environment)).append("\n"); - sb.append(" status: ").append(toIndentedString(status)).append("\n"); - sb.append(" resultTraceback: ").append(toIndentedString(resultTraceback)).append("\n"); - sb.append(" repositoryURL: ").append(toIndentedString(repositoryURL)).append("\n"); - sb.append(" params: ").append(toIndentedString(params)).append("\n"); - sb.append(" componentType: ").append(toIndentedString(componentType)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} - diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java deleted file mode 100644 index c19af9f..0000000 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentRequest.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.opendevstack.apiservice.project.model; - -import java.net.URI; -import java.util.Objects; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import java.util.HashMap; -import java.util.Map; -import org.springframework.lang.Nullable; -import org.openapitools.jackson.nullable.JsonNullable; -import java.time.OffsetDateTime; -import jakarta.validation.Valid; -import jakarta.validation.constraints.*; -import io.swagger.v3.oas.annotations.media.Schema; - - -import java.util.*; -import jakarta.annotation.Generated; - -/** - * CreateComponentRequest - */ - -@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") -public class CreateComponentRequest { - - private @Nullable String name; - - private @Nullable String productId; - - @Valid - private Map params = new HashMap<>(); - - public CreateComponentRequest name(@Nullable String name) { - this.name = name; - return this; - } - - /** - * component name - * @return name - */ - - @Schema(name = "name", description = "component name", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("name") - public @Nullable String getName() { - return name; - } - - public void setName(@Nullable String name) { - this.name = name; - } - - public CreateComponentRequest productId(@Nullable String productId) { - this.productId = productId; - return this; - } - - /** - * product id - * @return productId - */ - - @Schema(name = "productId", description = "product id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("productId") - public @Nullable String getProductId() { - return productId; - } - - public void setProductId(@Nullable String productId) { - this.productId = productId; - } - - public CreateComponentRequest params(Map params) { - this.params = params; - return this; - } - - public CreateComponentRequest putParamsItem(String key, String paramsItem) { - if (this.params == null) { - this.params = new HashMap<>(); - } - this.params.put(key, paramsItem); - return this; - } - - /** - * Get params - * @return params - */ - - @Schema(name = "params", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("params") - public Map getParams() { - return params; - } - - public void setParams(Map params) { - this.params = params; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CreateComponentRequest createComponentRequest = (CreateComponentRequest) o; - return Objects.equals(this.name, createComponentRequest.name) && - Objects.equals(this.productId, createComponentRequest.productId) && - Objects.equals(this.params, createComponentRequest.params); - } - - @Override - public int hashCode() { - return Objects.hash(name, productId, params); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class CreateComponentRequest {\n"); - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" productId: ").append(toIndentedString(productId)).append("\n"); - sb.append(" params: ").append(toIndentedString(params)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} - diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java deleted file mode 100644 index e9313aa..0000000 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model/CreateComponentResponse.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.opendevstack.apiservice.project.model; - -import java.net.URI; -import java.util.Objects; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import org.springframework.lang.Nullable; -import org.openapitools.jackson.nullable.JsonNullable; -import java.time.OffsetDateTime; -import jakarta.validation.Valid; -import jakarta.validation.constraints.*; -import io.swagger.v3.oas.annotations.media.Schema; - - -import java.util.*; -import jakarta.annotation.Generated; - -/** - * CreateComponentResponse - */ - -@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.15.0") -public class CreateComponentResponse { - - private @Nullable Integer errorCode; - - private @Nullable String field; - - private @Nullable String message; - - private @Nullable String location; - - public CreateComponentResponse errorCode(@Nullable Integer errorCode) { - this.errorCode = errorCode; - return this; - } - - /** - * Get errorCode - * @return errorCode - */ - - @Schema(name = "errorCode", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("errorCode") - public @Nullable Integer getErrorCode() { - return errorCode; - } - - public void setErrorCode(@Nullable Integer errorCode) { - this.errorCode = errorCode; - } - - public CreateComponentResponse field(@Nullable String field) { - this.field = field; - return this; - } - - /** - * Get field - * @return field - */ - - @Schema(name = "field", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("field") - public @Nullable String getField() { - return field; - } - - public void setField(@Nullable String field) { - this.field = field; - } - - public CreateComponentResponse message(@Nullable String message) { - this.message = message; - return this; - } - - /** - * Get message - * @return message - */ - - @Schema(name = "message", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("message") - public @Nullable String getMessage() { - return message; - } - - public void setMessage(@Nullable String message) { - this.message = message; - } - - public CreateComponentResponse location(@Nullable String location) { - this.location = location; - return this; - } - - /** - * Get location - * @return location - */ - - @Schema(name = "location", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - @JsonProperty("location") - public @Nullable String getLocation() { - return location; - } - - public void setLocation(@Nullable String location) { - this.location = location; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CreateComponentResponse createComponentResponse = (CreateComponentResponse) o; - return Objects.equals(this.errorCode, createComponentResponse.errorCode) && - Objects.equals(this.field, createComponentResponse.field) && - Objects.equals(this.message, createComponentResponse.message) && - Objects.equals(this.location, createComponentResponse.location); - } - - @Override - public int hashCode() { - return Objects.hash(errorCode, field, message, location); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class CreateComponentResponse {\n"); - sb.append(" errorCode: ").append(toIndentedString(errorCode)).append("\n"); - sb.append(" field: ").append(toIndentedString(field)).append("\n"); - sb.append(" message: ").append(toIndentedString(message)).append("\n"); - sb.append(" location: ").append(toIndentedString(location)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} - From c8dff782344bea2d069fe1bb8894d3270e89ff31 Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Thu, 19 Mar 2026 16:16:20 +0100 Subject: [PATCH 3/7] Git ignore generated files. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5183737..c765529 100644 --- a/.gitignore +++ b/.gitignore @@ -95,5 +95,7 @@ api-project-platform/src/main/java/org/opendevstack/apiservice/projectplatform/a api-project-platform/src/main/java/org/opendevstack/apiservice/projectplatform/model api-project/src/main/java/org/opendevstack/apiservice/project/api api-project/src/main/java/org/opendevstack/apiservice/project/model +api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api +api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model **/.openapi-generator From 478027bbb1679aac86a5b7eed5d7973caa62fcbc Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Fri, 20 Mar 2026 09:22:13 +0100 Subject: [PATCH 4/7] Fix sonar complaints. --- .../controller/ComponentsResponseFactory.java | 6 +++--- .../project/service/ComponentsService.java | 2 ++ .../ProjectComponentsControllerTest.java | 17 ++++++++++------- .../project/service/ComponentsServiceTest.java | 4 ++-- .../apiservice/project/util/TestHelper.java | 8 ++++---- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java index de9cd3b..cafb6c8 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java @@ -12,7 +12,7 @@ private ComponentsResponseFactory() { public static CreateComponentResponse error(String projectId) { CreateComponentResponse response = new CreateComponentResponse(); response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); - response.setMessage("Failed to create component for project '" + projectId); + response.setMessage("Failed to create component for project '" + projectId + "'"); return response; } @@ -23,7 +23,7 @@ public static CreateComponentResponse entityCreated(String projectId, String com return response; } - public static ResponseEntity toResponseEntity(CreateComponentResponse response) { - return new ResponseEntity(response, HttpStatus.valueOf(response.getErrorCode())); + public static ResponseEntity toResponseEntity(CreateComponentResponse response) { + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getErrorCode())); } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java index 0125d81..c94be5c 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java @@ -32,10 +32,12 @@ public boolean isHealthy() { } public Component getProjectComponent(String projectId, String componentId) { + log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); return null; } public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); return null; } } diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java index b4a3ff9..a1f575a 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java @@ -34,34 +34,37 @@ void setup() { @Test void testCreateProjectComponent_whenSuccess_thenReturnOk() throws Exception { Component testComponent = buildTestComponent(); + String testProjectId = "testProjectId"; CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); - CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(); + CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(testComponent.getName(), + testProjectId); when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) .thenReturn(testComponent); - ResponseEntity response = projectComponentsController.createProjectComponent("testId", + ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, testCreateComponentRequest); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().equals(testServiceResponseSuccess)); + assertThat(response.getBody()).isEqualTo(testServiceResponseSuccess); } @Test void testCreateProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); - CreateComponentResponse testServiceResponseFailure = buildTestCreateComponentResponseFailure(); + String testProjectId = "testProjectId"; + CreateComponentResponse testServiceResponseFailure = buildTestCreateComponentResponseFailure(testProjectId); when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) .thenReturn(null); - ResponseEntity response = projectComponentsController.createProjectComponent("projectId", + ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, testCreateComponentRequest); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().equals(testServiceResponseFailure)); + assertThat(response.getBody()).isEqualTo(testServiceResponseFailure); } @Test @@ -76,7 +79,7 @@ void testGetProjectComponent_whenSuccess_thenReturnOk() throws Exception { assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().equals(testComponent)); + assertThat(response.getBody()).isEqualTo(testComponent); } @Test diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java index dac538f..8589fbb 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java @@ -46,7 +46,7 @@ void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Except .thenReturn(null); Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); - assertThat(retrievedComponent).isEqualTo(null); + assertThat(retrievedComponent).isNull(); } @Test @@ -70,6 +70,6 @@ void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { .thenReturn(null); Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); - assertThat(retrievedComponent).isEqualTo(null); + assertThat(retrievedComponent).isNull(); } } \ No newline at end of file diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java index e6a26a9..2034ee0 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java @@ -24,17 +24,17 @@ public static CreateComponentRequest buildTestCreateComponentRequest() { return request; } - public static CreateComponentResponse buildTestCreateComponentResponseSuccess() { + public static CreateComponentResponse buildTestCreateComponentResponseSuccess(String componentName, String projectId) { CreateComponentResponse response = new CreateComponentResponse(); response.setErrorCode(HttpStatus.CREATED.value()); - response.setMessage("success"); + response.setMessage(componentName + " component created successfully in project " + projectId); return response; } - public static CreateComponentResponse buildTestCreateComponentResponseFailure() { + public static CreateComponentResponse buildTestCreateComponentResponseFailure(String projectId) { CreateComponentResponse response = new CreateComponentResponse(); response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); - response.setMessage("failure"); + response.setMessage("Failed to create component for project '" + projectId + "'"); return response; } } From 589098ffd542d96802c0e1c274668f3631f929fa Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Fri, 20 Mar 2026 09:42:27 +0100 Subject: [PATCH 5/7] Fix sonar complaints. --- .../controller/ComponentsResponseFactory.java | 58 +++--- .../ProjectComponentsController.java | 100 ++++----- .../project/service/ComponentsService.java | 87 ++++---- .../ProjectComponentsControllerTest.java | 190 +++++++++--------- .../service/ComponentsServiceTest.java | 147 +++++++------- .../apiservice/project/util/TestHelper.java | 80 ++++---- 6 files changed, 331 insertions(+), 331 deletions(-) diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java index cafb6c8..90ba586 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java @@ -1,29 +1,29 @@ -package org.opendevstack.apiservice.project.controller; - -import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -public class ComponentsResponseFactory { - - private ComponentsResponseFactory() { - } - - public static CreateComponentResponse error(String projectId) { - CreateComponentResponse response = new CreateComponentResponse(); - response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); - response.setMessage("Failed to create component for project '" + projectId + "'"); - return response; - } - - public static CreateComponentResponse entityCreated(String projectId, String componentName) { - CreateComponentResponse response = new CreateComponentResponse(); - response.setErrorCode(HttpStatus.CREATED.value()); - response.setMessage(componentName + " component created successfully in project " + projectId); - return response; - } - - public static ResponseEntity toResponseEntity(CreateComponentResponse response) { - return new ResponseEntity<>(response, HttpStatus.valueOf(response.getErrorCode())); - } -} +package org.opendevstack.apiservice.project.controller; + +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +public class ComponentsResponseFactory { + + private ComponentsResponseFactory() { + } + + public static CreateComponentResponse error(String projectId) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setMessage("Failed to create component for project '" + projectId + "'"); + return response; + } + + public static CreateComponentResponse entityCreated(String projectId, String componentName) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.CREATED.value()); + response.setMessage(componentName + " component created successfully in project " + projectId); + return response; + } + + public static ResponseEntity toResponseEntity(CreateComponentResponse response) { + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getErrorCode())); + } +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java index b2106bb..ccfb7ea 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java @@ -1,49 +1,51 @@ -package org.opendevstack.apiservice.project.controller; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.opendevstack.apiservice.project.api.ProjectComponentsApi; -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; -import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import org.opendevstack.apiservice.project.service.ComponentsService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RestController; - -import static org.opendevstack.apiservice.project.controller.ComponentsResponseFactory.toResponseEntity; - -@RestController -@AllArgsConstructor -@Slf4j -public class ProjectComponentsController implements ProjectComponentsApi { - - private final ComponentsService componentsService; - - @Override - public ResponseEntity createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - try { - Component component = componentsService.createProjectComponent(projectId, createComponentRequest); - if (component == null) { - log.error("Failed to create component for project '{}'", projectId); - return toResponseEntity(ComponentsResponseFactory.error(projectId)); - } - return toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); - } catch (Exception e) { - log.error("Error while trying to create component for project '" + projectId + "': " + e.getMessage(), e); - return toResponseEntity(ComponentsResponseFactory.error(projectId)); - } - } - - @Override - public ResponseEntity getProjectComponent(String projectId, String componentId) { - try { - Component component = componentsService.getProjectComponent(projectId, componentId); - return component != null ? - ResponseEntity.ok(component) : ResponseEntity.notFound().build(); - } catch (Exception e) { - log.error("Error retrieving component '{}' for project '{}': {}", componentId, projectId, e.getMessage(), e); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value()).build(); - } - } -} +package org.opendevstack.apiservice.project.controller; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.opendevstack.apiservice.project.api.ProjectComponentsApi; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.opendevstack.apiservice.project.service.ComponentsService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import static org.opendevstack.apiservice.project.controller.ComponentsResponseFactory.toResponseEntity; + +@RestController +@AllArgsConstructor +@Slf4j +public class ProjectComponentsController implements ProjectComponentsApi { + + private final ComponentsService componentsService; + + @Override + public ResponseEntity createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + try { + Component component = componentsService.createProjectComponent(projectId, createComponentRequest); + if (component == null) { + log.error("Failed to create component for project '{}'", projectId); + return toResponseEntity(ComponentsResponseFactory.error(projectId)); + } + return toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); + } catch (Exception e) { + log.error("Error while trying to create component for project '" + projectId + "': " + e.getMessage(), e); + return toResponseEntity(ComponentsResponseFactory.error(projectId)); + } + } + + @Override + public ResponseEntity getProjectComponent(String projectId, String componentId) { + try { + Component component = componentsService.getProjectComponent(projectId, componentId); + if (component == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + return ResponseEntity.status(HttpStatus.OK).body(component); + } catch (Exception e) { + log.error("Error retrieving component '{}' for project '{}': {}", componentId, projectId, e.getMessage(), e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java index c94be5c..959127a 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/service/ComponentsService.java @@ -1,44 +1,43 @@ -package org.opendevstack.apiservice.project.service; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.opendevstack.apiservice.externalservice.api.ExternalService; -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -@Slf4j -public class ComponentsService { - - private final MarketplaceExternalServicePlaceholder marketplaceExternalService; - - public Component getProjectComponent(String projectId, String componentId) { - return marketplaceExternalService.getProjectComponent(projectId, componentId); - } - - public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - return marketplaceExternalService.createProjectComponent(projectId, createComponentRequest); - } - - //TODO replace this with actual external service implementations and remove the placeholder - @Service - class MarketplaceExternalServicePlaceholder implements ExternalService { - - @Override - public boolean isHealthy() { - return false; - } - - public Component getProjectComponent(String projectId, String componentId) { - log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); - return null; - } - - public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); - return null; - } - } -} +package org.opendevstack.apiservice.project.service; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.opendevstack.apiservice.externalservice.api.ExternalService; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +@Slf4j +public class ComponentsService { + + private final MarketplaceExternalServicePlaceholder marketplaceExternalService; + + public Component getProjectComponent(String projectId, String componentId) { + return marketplaceExternalService.getProjectComponent(projectId, componentId); + } + + public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + return marketplaceExternalService.createProjectComponent(projectId, createComponentRequest); + } + + @Service + class MarketplaceExternalServicePlaceholder implements ExternalService { + + @Override + public boolean isHealthy() { + return false; + } + + public Component getProjectComponent(String projectId, String componentId) { + log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); + return null; + } + + public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); + return null; + } + } +} diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java index a1f575a..89ac444 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java @@ -1,96 +1,96 @@ -package org.opendevstack.apiservice.project.controller; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; -import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import org.opendevstack.apiservice.project.service.ComponentsService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; -import static org.opendevstack.apiservice.project.util.TestHelper.*; - -@ExtendWith(MockitoExtension.class) -class ProjectComponentsControllerTest { - - @Mock - private ComponentsService componentsService; - - private ProjectComponentsController projectComponentsController; - - @BeforeEach - void setup() { - projectComponentsController = new ProjectComponentsController(componentsService); - } - - @Test - void testCreateProjectComponent_whenSuccess_thenReturnOk() throws Exception { - Component testComponent = buildTestComponent(); - String testProjectId = "testProjectId"; - CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); - CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(testComponent.getName(), - testProjectId); - - when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) - .thenReturn(testComponent); - - ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, - testCreateComponentRequest); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); - assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody()).isEqualTo(testServiceResponseSuccess); - } - - @Test - void testCreateProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { - CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); - String testProjectId = "testProjectId"; - CreateComponentResponse testServiceResponseFailure = buildTestCreateComponentResponseFailure(testProjectId); - - when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) - .thenReturn(null); - - ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, - testCreateComponentRequest); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody()).isEqualTo(testServiceResponseFailure); - } - - @Test - void testGetProjectComponent_whenSuccess_thenReturnOk() throws Exception { - Component testComponent = buildTestComponent(); - - when(componentsService.getProjectComponent(anyString(), anyString())) - .thenReturn(testComponent); - - ResponseEntity response = projectComponentsController.getProjectComponent("projectId", - "testId"); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody()).isEqualTo(testComponent); - } - - @Test - void testGetProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { - when(componentsService.getProjectComponent(anyString(), anyString())) - .thenReturn(null); - - ResponseEntity response = projectComponentsController.getProjectComponent("projectId", - "testId"); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(response.getBody()).isNull(); - } +package org.opendevstack.apiservice.project.controller; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.opendevstack.apiservice.project.service.ComponentsService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.opendevstack.apiservice.project.util.TestHelper.*; + +@ExtendWith(MockitoExtension.class) +class ProjectComponentsControllerTest { + + @Mock + private ComponentsService componentsService; + + private ProjectComponentsController projectComponentsController; + + @BeforeEach + void setup() { + projectComponentsController = new ProjectComponentsController(componentsService); + } + + @Test + void testCreateProjectComponent_whenSuccess_thenReturnOk() throws Exception { + Component testComponent = buildTestComponent(); + String testProjectId = "testProjectId"; + CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); + CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(testComponent.getName(), + testProjectId); + + when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) + .thenReturn(testComponent); + + ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, + testCreateComponentRequest); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody()).isEqualTo(testServiceResponseSuccess); + } + + @Test + void testCreateProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { + CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); + String testProjectId = "testProjectId"; + CreateComponentResponse testServiceResponseFailure = buildTestCreateComponentResponseFailure(testProjectId); + + when(componentsService.createProjectComponent(anyString(), any(CreateComponentRequest.class))) + .thenReturn(null); + + ResponseEntity response = projectComponentsController.createProjectComponent(testProjectId, + testCreateComponentRequest); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody()).isEqualTo(testServiceResponseFailure); + } + + @Test + void testGetProjectComponent_whenSuccess_thenReturnOk() throws Exception { + Component testComponent = buildTestComponent(); + + when(componentsService.getProjectComponent(anyString(), anyString())) + .thenReturn(testComponent); + + ResponseEntity response = projectComponentsController.getProjectComponent("projectId", + "testId"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody()).isEqualTo(testComponent); + } + + @Test + void testGetProjectComponent_whenFailure_thenReturnErrorResponse() throws Exception { + when(componentsService.getProjectComponent(anyString(), anyString())) + .thenReturn(null); + + ResponseEntity response = projectComponentsController.getProjectComponent("projectId", + "testId"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(response.getBody()).isNull(); + } } \ No newline at end of file diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java index 8589fbb..1ce3b3d 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/service/ComponentsServiceTest.java @@ -1,75 +1,74 @@ -package org.opendevstack.apiservice.project.service; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; -import static org.opendevstack.apiservice.project.util.TestHelper.buildTestComponent; -import static org.opendevstack.apiservice.project.util.TestHelper.buildTestCreateComponentRequest; - -@ExtendWith(MockitoExtension.class) -class ComponentsServiceTest { - - //TODO update this with actual marketplace service mocks once implemented and remove the placeholder - @Mock - private ComponentsService.MarketplaceExternalServicePlaceholder marketPlaceExternalServicePlaceholder; - - private ComponentsService componentsService; - - @BeforeEach - void setup() { - componentsService = new ComponentsService(marketPlaceExternalServicePlaceholder); - } - - @Test - void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { - Component testComponent = buildTestComponent(); - - when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) - .thenReturn(testComponent); - - Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); - assertThat(retrievedComponent).isEqualTo(testComponent); - } - - @Test - void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Exception { - when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) - .thenReturn(null); - - Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); - assertThat(retrievedComponent).isNull(); - } - - @Test - void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { - Component testComponent = buildTestComponent(); - CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - - when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) - .thenReturn(testComponent); - - Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); - assertThat(retrievedComponent).isEqualTo(testComponent); - } - - - @Test - void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { - CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - - when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) - .thenReturn(null); - - Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); - assertThat(retrievedComponent).isNull(); - } +package org.opendevstack.apiservice.project.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.opendevstack.apiservice.project.util.TestHelper.buildTestComponent; +import static org.opendevstack.apiservice.project.util.TestHelper.buildTestCreateComponentRequest; + +@ExtendWith(MockitoExtension.class) +class ComponentsServiceTest { + + @Mock + private ComponentsService.MarketplaceExternalServicePlaceholder marketPlaceExternalServicePlaceholder; + + private ComponentsService componentsService; + + @BeforeEach + void setup() { + componentsService = new ComponentsService(marketPlaceExternalServicePlaceholder); + } + + @Test + void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { + Component testComponent = buildTestComponent(); + + when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + .thenReturn(testComponent); + + Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); + assertThat(retrievedComponent).isEqualTo(testComponent); + } + + @Test + void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Exception { + when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + .thenReturn(null); + + Component retrievedComponent = componentsService.getProjectComponent("testId", "testId"); + assertThat(retrievedComponent).isNull(); + } + + @Test + void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { + Component testComponent = buildTestComponent(); + CreateComponentRequest testRequest = buildTestCreateComponentRequest(); + + when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + .thenReturn(testComponent); + + Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); + assertThat(retrievedComponent).isEqualTo(testComponent); + } + + + @Test + void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { + CreateComponentRequest testRequest = buildTestCreateComponentRequest(); + + when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + .thenReturn(null); + + Component retrievedComponent = componentsService.createProjectComponent("testId", testRequest); + assertThat(retrievedComponent).isNull(); + } } \ No newline at end of file diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java index 2034ee0..d8e13f0 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java @@ -1,40 +1,40 @@ -package org.opendevstack.apiservice.project.util; - -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; -import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; - -public class TestHelper { - - public static Component buildTestComponent() { - Component component = new Component(); - component.setId("testId"); - component.setName("testComponentName"); - component.environment("testEnv"); - component.setComponentType("testComponentType"); - return component; - } - - public static CreateComponentRequest buildTestCreateComponentRequest() { - CreateComponentRequest request = new CreateComponentRequest(); - request.setName("testComponentName"); - request.setProductId("testProductId"); - return request; - } - - public static CreateComponentResponse buildTestCreateComponentResponseSuccess(String componentName, String projectId) { - CreateComponentResponse response = new CreateComponentResponse(); - response.setErrorCode(HttpStatus.CREATED.value()); - response.setMessage(componentName + " component created successfully in project " + projectId); - return response; - } - - public static CreateComponentResponse buildTestCreateComponentResponseFailure(String projectId) { - CreateComponentResponse response = new CreateComponentResponse(); - response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); - response.setMessage("Failed to create component for project '" + projectId + "'"); - return response; - } -} +package org.opendevstack.apiservice.project.util; + +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; + +public class TestHelper { + + public static Component buildTestComponent() { + Component component = new Component(); + component.setId("testId"); + component.setName("testComponentName"); + component.environment("testEnv"); + component.setComponentType("testComponentType"); + return component; + } + + public static CreateComponentRequest buildTestCreateComponentRequest() { + CreateComponentRequest request = new CreateComponentRequest(); + request.setName("testComponentName"); + request.setProductId("testProductId"); + return request; + } + + public static CreateComponentResponse buildTestCreateComponentResponseSuccess(String componentName, String projectId) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.CREATED.value()); + response.setMessage(componentName + " component created successfully in project " + projectId); + return response; + } + + public static CreateComponentResponse buildTestCreateComponentResponseFailure(String projectId) { + CreateComponentResponse response = new CreateComponentResponse(); + response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setMessage("Failed to create component for project '" + projectId + "'"); + return response; + } +} From 8a2fc3beb00e024daa35c6245d8756feb13c58f3 Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Fri, 20 Mar 2026 15:39:55 +0100 Subject: [PATCH 6/7] Add mapper. --- .../controller/ComponentsResponseFactory.java | 4 ---- .../controller/ProjectComponentsController.java | 11 ++++++----- .../project/mapper/ComponentResponseMapper.java | 15 +++++++++++++++ .../ProjectComponentsControllerTest.java | 6 +++++- 4 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/ComponentResponseMapper.java diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java index 90ba586..c3ef127 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java @@ -22,8 +22,4 @@ public static CreateComponentResponse entityCreated(String projectId, String com response.setMessage(componentName + " component created successfully in project " + projectId); return response; } - - public static ResponseEntity toResponseEntity(CreateComponentResponse response) { - return new ResponseEntity<>(response, HttpStatus.valueOf(response.getErrorCode())); - } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java index ccfb7ea..2a49194 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java @@ -3,6 +3,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.opendevstack.apiservice.project.api.ProjectComponentsApi; +import org.opendevstack.apiservice.project.mapper.ComponentResponseMapper; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.opendevstack.apiservice.project.model.CreateComponentResponse; @@ -11,8 +12,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; -import static org.opendevstack.apiservice.project.controller.ComponentsResponseFactory.toResponseEntity; - @RestController @AllArgsConstructor @Slf4j @@ -20,18 +19,20 @@ public class ProjectComponentsController implements ProjectComponentsApi { private final ComponentsService componentsService; + private final ComponentResponseMapper componentResponseMapper; + @Override public ResponseEntity createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { try { Component component = componentsService.createProjectComponent(projectId, createComponentRequest); if (component == null) { log.error("Failed to create component for project '{}'", projectId); - return toResponseEntity(ComponentsResponseFactory.error(projectId)); + return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.error(projectId)); } - return toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); + return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); } catch (Exception e) { log.error("Error while trying to create component for project '" + projectId + "': " + e.getMessage(), e); - return toResponseEntity(ComponentsResponseFactory.error(projectId)); + return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.error(projectId)); } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/ComponentResponseMapper.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/ComponentResponseMapper.java new file mode 100644 index 0000000..4c3198b --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/ComponentResponseMapper.java @@ -0,0 +1,15 @@ +package org.opendevstack.apiservice.project.mapper; + +import org.mapstruct.Mapper; +import org.opendevstack.apiservice.project.model.CreateComponentResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +@Mapper(componentModel = "spring") +public interface ComponentResponseMapper { + + default ResponseEntity toResponseEntity(CreateComponentResponse response) { + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getErrorCode())); + } + +} diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java index 89ac444..4d46cbb 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java @@ -3,8 +3,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mapstruct.factory.Mappers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.mapper.ComponentResponseMapper; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.opendevstack.apiservice.project.model.CreateComponentResponse; @@ -24,11 +26,13 @@ class ProjectComponentsControllerTest { @Mock private ComponentsService componentsService; + private final ComponentResponseMapper componentResponseMapper = Mappers.getMapper(ComponentResponseMapper.class); + private ProjectComponentsController projectComponentsController; @BeforeEach void setup() { - projectComponentsController = new ProjectComponentsController(componentsService); + projectComponentsController = new ProjectComponentsController(componentsService, componentResponseMapper); } @Test From df4de1202beb1ec9f09946d97d13328816ecc28f Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Fri, 20 Mar 2026 15:45:25 +0100 Subject: [PATCH 7/7] Make test helper uninstantiable. --- .../org/opendevstack/apiservice/project/util/TestHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java index d8e13f0..40c0ac6 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestHelper.java @@ -4,10 +4,12 @@ import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.opendevstack.apiservice.project.model.CreateComponentResponse; import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; public class TestHelper { + private TestHelper() { + } + public static Component buildTestComponent() { Component component = new Component(); component.setId("testId");