Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/main/java/org/gridsuite/explore/server/ExploreController.java
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,43 @@ public ResponseEntity<Void> duplicateSpreadsheetConfig(@RequestParam("duplicateF
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@PostMapping(value = "/explore/workspaces", params = "workspaceId")
@Operation(summary = "Create a workspace by duplicating an existing workspace")
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Workspace created")})
@PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
public ResponseEntity<Void> createWorkspace(@RequestParam("workspaceId") UUID workspaceId,
@RequestParam("name") String workspaceName,
@RequestParam(QUERY_PARAM_DESCRIPTION) String description,
@RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
exploreService.createWorkspace(workspaceId, workspaceName, description, parentDirectoryUuid, userId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@PutMapping(value = "/explore/workspaces/{id}", params = "workspaceId")
@Operation(summary = "Replace a workspace with another workspace")
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Workspace has been successfully replaced")})
@PreAuthorize("@authorizationService.isAuthorized(#userId, #id, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
public ResponseEntity<Void> replaceWorkspace(@PathVariable UUID id,
@RequestParam("workspaceId") UUID workspaceId,
@RequestHeader(QUERY_PARAM_USER_ID) String userId,
@RequestParam(QUERY_PARAM_NAME) String name,
@RequestParam(QUERY_PARAM_DESCRIPTION) String description) {
exploreService.replaceWorkspace(id, workspaceId, userId, name, description);
return ResponseEntity.noContent().build();
}

@PostMapping(value = "/explore/workspaces", params = "duplicateFrom")
@Operation(summary = "Duplicate a workspace")
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Workspace has been successfully duplicated")})
@PreAuthorize("@authorizationService.isAuthorizedForDuplication(#userId, #sourceId, #targetDirectoryId)")
public ResponseEntity<Void> duplicateWorkspace(@RequestParam("duplicateFrom") UUID sourceId,
@RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId,
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
exploreService.duplicateWorkspace(sourceId, targetDirectoryId, userId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@PostMapping(value = "/explore/spreadsheet-config-collections", params = "duplicateFrom")
@Operation(summary = "Duplicate a spreadsheet configuration collection")
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Spreadsheet config collection has been successfully duplicated")})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class DirectoryService implements IDirectoryElementsService {
public DirectoryService(
FilterService filterService, ContingencyListService contingencyListService, StudyService studyService, NetworkModificationService networkModificationService,
CaseService caseService, SpreadsheetConfigService spreadsheetConfigService, SpreadsheetConfigCollectionService spreadsheetConfigCollectionService, ParametersService parametersService,
SingleLineDiagramService singleLineDiagramService, RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) {
SingleLineDiagramService singleLineDiagramService, WorkspaceService workspaceService, RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) {
this.directoryServerBaseUri = remoteServicesProperties.getServiceUri("directory-server");
this.restTemplate = restTemplate;
this.genericServices = Map.ofEntries(
Expand All @@ -75,6 +75,7 @@ public DirectoryService(
Map.entry(SPREADSHEET_CONFIG, spreadsheetConfigService),
Map.entry(SPREADSHEET_CONFIG_COLLECTION, spreadsheetConfigCollectionService),
Map.entry(DIAGRAM_CONFIG, singleLineDiagramService),
Map.entry(WORKSPACE, workspaceService),
Map.entry(ParametersType.VOLTAGE_INIT_PARAMETERS.name(), parametersService),
Map.entry(ParametersType.SECURITY_ANALYSIS_PARAMETERS.name(), parametersService),
Map.entry(ParametersType.LOADFLOW_PARAMETERS.name(), parametersService),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class ExploreService {
static final String SPREADSHEET_CONFIG = "SPREADSHEET_CONFIG";
static final String SPREADSHEET_CONFIG_COLLECTION = "SPREADSHEET_CONFIG_COLLECTION";
static final String DIAGRAM_CONFIG = "DIAGRAM_CONFIG";
static final String WORKSPACE = "WORKSPACE";

private final DirectoryService directoryService;
private final StudyService studyService;
Expand All @@ -51,6 +52,7 @@ public class ExploreService {
private final ParametersService parametersService;
private final SpreadsheetConfigService spreadsheetConfigService;
private final SpreadsheetConfigCollectionService spreadsheetConfigCollectionService;
private final WorkspaceService workspaceService;
private final UserIdentityService userIdentityService;
private final NotificationService notificationService;

Expand All @@ -69,6 +71,7 @@ public ExploreService(
UserAdminService userAdminService,
SpreadsheetConfigService spreadsheetConfigService,
SpreadsheetConfigCollectionService spreadsheetConfigCollectionService,
WorkspaceService workspaceService,
UserIdentityService userIdentityService,
NotificationService notificationService,
SingleLineDiagramService singleLineDiagramService) {
Expand All @@ -83,6 +86,7 @@ public ExploreService(
this.userAdminService = userAdminService;
this.spreadsheetConfigService = spreadsheetConfigService;
this.spreadsheetConfigCollectionService = spreadsheetConfigCollectionService;
this.workspaceService = workspaceService;
this.userIdentityService = userIdentityService;
this.notificationService = notificationService;
this.singleLineDiagramService = singleLineDiagramService;
Expand Down Expand Up @@ -319,6 +323,22 @@ public void duplicateSpreadsheetConfigCollection(UUID sourceId, UUID targetDirec
directoryService.duplicateElement(sourceId, newSpreadsheetConfigUuid, targetDirectoryId, userId);
}

public void createWorkspace(UUID workspaceId, String workspaceName, String description, UUID parentDirectoryUuid, String userId) {
UUID newWorkspaceId = workspaceService.duplicateWorkspace(workspaceId);
ElementAttributes elementAttributes = new ElementAttributes(newWorkspaceId, workspaceName, WORKSPACE, userId, 0, description);
directoryService.createElement(elementAttributes, parentDirectoryUuid, userId);
}

public void replaceWorkspace(UUID id, UUID workspaceId, String userId, String name, String description) {
workspaceService.replaceWorkspace(id, workspaceId);
updateElementNameAndDescription(id, name, description, userId);
}

public void duplicateWorkspace(UUID sourceId, UUID targetDirectoryId, String userId) {
UUID newWorkspaceId = workspaceService.duplicateWorkspace(sourceId);
directoryService.duplicateElement(sourceId, newWorkspaceId, targetDirectoryId, userId);
}

public void createCompositeModification(List<UUID> modificationUuids, String userId, String name,
String description, UUID parentDirectoryUuid) {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Copyright (c) 2026, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.gridsuite.explore.server.services;

import lombok.Setter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Objects;
import java.util.UUID;

/**
* @author Ayoub LABIDI <ayoub.labidi at rte-france.com>
*/
@Service
public class WorkspaceService implements IDirectoryElementsService {

private static final String WORKSPACES_API_VERSION = "v1";
private static final String DELIMITER = "/";
private static final String WORKSPACES_PATH = DELIMITER + WORKSPACES_API_VERSION + DELIMITER + "workspaces";
private static final String DUPLICATE_FROM_PARAMETER = "duplicateFrom";

private final RestTemplate restTemplate;

@Setter
private String studyConfigServerBaseUri;

public WorkspaceService(RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) {
this.studyConfigServerBaseUri = remoteServicesProperties.getServiceUri("study-config-server");
this.restTemplate = restTemplate;
}

public UUID duplicateWorkspace(UUID sourceWorkspaceId) {
Objects.requireNonNull(sourceWorkspaceId);

var path = UriComponentsBuilder
.fromPath(WORKSPACES_PATH)
.queryParam(DUPLICATE_FROM_PARAMETER, sourceWorkspaceId)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> httpEntity = new HttpEntity<>(headers);

return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, UUID.class).getBody();
}

public void replaceWorkspace(UUID workspaceId, UUID sourceWorkspaceId) {
Objects.requireNonNull(workspaceId);
Objects.requireNonNull(sourceWorkspaceId);

var path = UriComponentsBuilder
.fromPath(WORKSPACES_PATH + DELIMITER + workspaceId + "/replace")
.queryParam(DUPLICATE_FROM_PARAMETER, sourceWorkspaceId)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> httpEntity = new HttpEntity<>(headers);

restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.PUT, httpEntity, Void.class);
}

@Override
public void delete(UUID workspaceUuid, String userId) {
Objects.requireNonNull(workspaceUuid);

var path = UriComponentsBuilder
.fromPath(WORKSPACES_PATH + DELIMITER + workspaceUuid)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.add(HEADER_USER_ID, userId);

restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class);
}
}
Loading