diff --git a/rest/resource-server/src/docs/asciidoc/components.adoc b/rest/resource-server/src/docs/asciidoc/components.adoc index b3e7927293..1e210c5bcd 100644 --- a/rest/resource-server/src/docs/asciidoc/components.adoc +++ b/rest/resource-server/src/docs/asciidoc/components.adoc @@ -330,6 +330,22 @@ include::{snippets}/should_document_merge_components/http-response.adoc[] ===== Links include::{snippets}/should_document_merge_components/links.adoc[] +[[resources-components-update]] +==== Split a component + +A `PATCH` request is used to split two components + +===== Response structure +include::{snippets}/should_document_split_components/response-fields.adoc[] + +===== Example request +include::{snippets}/should_document_split_components/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_split_components/http-response.adoc[] + +===== Links +include::{snippets}/should_document_split_components/links.adoc[] [[resources-components-delete]] ==== Delete a component diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/ComponentController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/ComponentController.java index cdbb696864..d8b7be3a1e 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/ComponentController.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/ComponentController.java @@ -734,4 +734,20 @@ public ResponseEntity mergeComponents( return new ResponseEntity<>(requestStatus, HttpStatus.OK); } + + @PreAuthorize("hasAuthority('WRITE')") + @RequestMapping(value = COMPONENTS_URL + "/splitComponents", method = RequestMethod.PATCH) + public ResponseEntity splitComponents( + @RequestBody Map componentMap) throws TException { + + User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + + Component srcComponent = componentMap.get("srcComponent"); + Component targetComponent = componentMap.get("targetComponent"); + + // perform the real merge, update merge target and delete merge source + RequestStatus requestStatus = componentService.splitComponents(srcComponent, targetComponent, sw360User); + + return new ResponseEntity<>(requestStatus, HttpStatus.OK); + } } diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/Sw360ComponentService.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/Sw360ComponentService.java index 91b7041a8e..2c622e07f8 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/Sw360ComponentService.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/component/Sw360ComponentService.java @@ -294,4 +294,19 @@ public RequestStatus mergeComponents(String componentTargetId, String componentS return requestStatus; } + public RequestStatus splitComponents(Component srcComponent, Component targetComponent, User sw360User) throws TException { + ComponentService.Iface sw360ComponentClient = getThriftComponentClient(); + RequestStatus requestStatus; + requestStatus = sw360ComponentClient.splitComponent(srcComponent, targetComponent, sw360User); + + if (requestStatus == RequestStatus.IN_USE) { + throw new HttpMessageNotReadableException("Component already in use."); + } else if (requestStatus == RequestStatus.FAILURE) { + throw new HttpMessageNotReadableException("Cannot split these components"); + } else if (requestStatus == RequestStatus.ACCESS_DENIED) { + throw new RuntimeException("Access denied...!"); + } + + return requestStatus; + } } diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java index fc5d07e2a9..2508c5c9ea 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java @@ -113,6 +113,9 @@ public class ComponentSpecTest extends TestRestDocsSpecBase { private Attachment sBOMAttachment; private RequestSummary requestSummary = new RequestSummary(); + private Release release; + private Release release2; + @Before public void before() throws TException, IOException { Set licenseIds = new HashSet<>(); @@ -346,7 +349,7 @@ public void before() throws TException, IOException { given(this.vendorServiceMock.getVendorById("vendorId")).willReturn(vendor); List releaseList = new ArrayList<>(); - Release release = new Release(); + release = new Release(); release.setId("3765276512"); release.setName("Angular 2.3.0"); release.setCpeid("cpe:/a:Google:Angular:2.3.0:"); @@ -358,7 +361,7 @@ public void before() throws TException, IOException { release.setComponentId(springComponent.getId()); releaseList.add(release); - Release release2 = new Release(); + release2 = new Release(); release2.setId("3765276512"); release2.setName("Angular 2.3.1"); release2.setCpeid("cpe:/a:Google:Angular:2.3.1:"); @@ -946,6 +949,7 @@ public void should_document_merge_components() throws Exception { fieldWithPath("blog").description("The blog of component"), fieldWithPath("homepage").description("The homepage url of the component"), fieldWithPath("modifiedOn").description("The date the component was modified"), + fieldWithPath("moderators").description("The component moderators"), fieldWithPath("name").description("The updated name of the component"), @@ -966,6 +970,60 @@ public void should_document_merge_components() throws Exception { ))); } + @Test + public void should_document_split_components() throws Exception { + + + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + Component srcComponent = new Component(); + srcComponent.setId("17653524"); + srcComponent.setName("Angular"); + srcComponent.setComponentOwner("John"); + srcComponent.setDescription("Angular is a development platform for building mobile and desktop web applications."); + List releaseList = new ArrayList<>(); + releaseList.add(release); + Release release2 = new Release(); + releaseList.add(release2); + + srcComponent.setReleases(releaseList); + Component targetComponent = new Component(); + targetComponent.setId("87654321"); + targetComponent.setName("Angular"); + targetComponent.setComponentOwner("John"); + targetComponent.setDescription("Angular is a development platform for building mobile and desktop web applications."); + targetComponent.setReleases(releaseList); + Map componentsMap = new HashMap<>(); + componentsMap.put("srcComponent", srcComponent); + componentsMap.put("targetComponent", targetComponent); + + mockMvc.perform(patch("/api/components/splitComponents") + .contentType(MediaTypes.HAL_JSON) + .content(this.objectMapper.writeValueAsString(componentsMap)) + .header("Authorization", "Bearer " + accessToken) + .accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + requestFields( + fieldWithPath("srcComponent.id").description("The ID of the source component"), + fieldWithPath("srcComponent.name").description("The name of the source component"), + fieldWithPath("srcComponent.description").description("The description of the source component"), + fieldWithPath("srcComponent.type").description("The type of the source component"), + fieldWithPath("srcComponent.componentOwner").description("The owner of the source component"), + fieldWithPath("srcComponent.visbility").description("The visibility of the source component"), + fieldWithPath("srcComponent.setVisbility").description("Flag indicating if the visibility is set"), + fieldWithPath("srcComponent.setBusinessUnit").description("Flag indicating if the business unit is set"), + fieldWithPath("targetComponent.id").description("The ID of the target component"), + fieldWithPath("targetComponent.name").description("The name of the target component"), + fieldWithPath("targetComponent.description").description("The description of the target component"), + fieldWithPath("targetComponent.type").description("The type of the target component"), + fieldWithPath("targetComponent.componentOwner").description("The owner of the target component"), + fieldWithPath("targetComponent.visbility").description("The visibility of the target component"), + fieldWithPath("targetComponent.setVisbility").description("Flag indicating if the visibility is set"), + fieldWithPath("targetComponent.setBusinessUnit").description("Flag indicating if the business unit is set") + + ))); + } + @Test public void should_document_delete_components() throws Exception { String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword);