Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,11 @@ public void createFilterBasedContingencyList(String listName, String content, St
createDirectoryElementOrDeleteElement(elementAttributes, parentDirectoryUuid, userId, contingencyListService::delete);
}

public void createFilter(String filter, String filterName, String description, UUID parentDirectoryUuid, String userId) {
public UUID createFilter(String filter, String filterName, String description, UUID parentDirectoryUuid, String userId) {
ElementAttributes elementAttributes = new ElementAttributes(UUID.randomUUID(), filterName, FILTER, userId, 0, description);
filterService.insertFilter(filter, elementAttributes.getElementUuid(), userId);
createDirectoryElementOrDeleteElement(elementAttributes, parentDirectoryUuid, userId, filterService::delete);
return elementAttributes.getElementUuid();
}

public void duplicateFilter(UUID sourceFilterId, UUID targetDirectoryId, String userId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/
package org.gridsuite.explore.server.services;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.gridsuite.explore.server.dto.*;
import org.gridsuite.explore.server.error.ExploreException;
import org.slf4j.Logger;
Expand All @@ -15,6 +17,7 @@
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
Expand All @@ -27,6 +30,7 @@
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import static org.gridsuite.explore.server.error.ExploreBusinessErrorCode.IMPORT_STUDY_FAILED;
import static org.gridsuite.explore.server.services.ExploreService.STUDY;
Expand All @@ -39,6 +43,10 @@ public class StudyImportService {

private static final Logger LOGGER = LoggerFactory.getLogger(StudyImportService.class);

private static final String NETWORK_MODIFICATIONS_JSON = "network-modification.json";
private static final String NETWORK_MODIFICATION_FILTERS_JSON = "network-modification-filters.json";
private static final String NETWORK_MODIFICATION_LOAD_FLOW_PARAMETERS_JSON = "network-modification-load-flow-parameters.json";

private final CaseService caseService;
private final StudyService studyService;
private final ObjectMapper objectMapper;
Expand Down Expand Up @@ -90,6 +98,7 @@ private void importStudyFromArchive(MultipartFile archiveFile, String studyName,
}

Map<UUID, UUID> caseUuidMapping = new HashMap<>();
List<UUID> createdFilterIds = new ArrayList<>();
try {
Path casesDir = tempDir.resolve("cases");
if (!Files.exists(casesDir) || !Files.isDirectory(casesDir)) {
Expand All @@ -101,18 +110,68 @@ private void importStudyFromArchive(MultipartFile archiveFile, String studyName,
checkAllCasesWereImported(treeExportInfos, caseUuidMapping);
UUID createdStudyUuid = UUID.randomUUID();
TreeExportInfos updatedExportInfos = updateCaseUuidsAndStudyUuidInExportInfos(treeExportInfos, caseUuidMapping, createdStudyUuid);
createStudyFromImport(createdStudyUuid, studyName, userId, description, parentDirectoryUuid, updatedExportInfos);
byte[] modificationsArchive = recreateFiltersAndBuildModificationsArchive(tempDir, parentDirectoryUuid, userId, createdFilterIds);
createStudyFromImport(createdStudyUuid, studyName, userId, description, parentDirectoryUuid, updatedExportInfos, modificationsArchive);
} catch (Exception e) {
deleteImportedCases(caseUuidMapping, userId);
deleteImportedFilters(createdFilterIds, userId);
throw new ExploreException(IMPORT_STUDY_FAILED, "Failed to import study: " + e.getMessage());
}
}

private byte[] recreateFiltersAndBuildModificationsArchive(Path tempDir, UUID parentDirectoryUuid, String userId, List<UUID> createdFilterIds) throws IOException {
Path filtersJsonPath = tempDir.resolve(NETWORK_MODIFICATION_FILTERS_JSON);
Map<UUID, ObjectNode> updatedFiltersByOldId = new LinkedHashMap<>();
if (Files.exists(filtersJsonPath)) {
Map<UUID, ObjectNode> filtersByOldId = objectMapper.readValue(filtersJsonPath.toFile(), new TypeReference<Map<UUID, ObjectNode>>() { });
for (Map.Entry<UUID, ObjectNode> entry : filtersByOldId.entrySet()) {
ObjectNode filter = entry.getValue();
String filterType = filter.path("type").asText("filter");
UUID newFilterId = exploreService.createFilter(filter.toString(), "Imported " + filterType + " " + entry.getKey(), null, parentDirectoryUuid, userId);
createdFilterIds.add(newFilterId);
filter.put("id", newFilterId.toString());
updatedFiltersByOldId.put(entry.getKey(), filter);
}
}

ByteArrayOutputStream archiveBytes = new ByteArrayOutputStream();
try (ZipOutputStream zipOut = new ZipOutputStream(archiveBytes)) {
addFileEntryIfPresent(zipOut, tempDir.resolve(NETWORK_MODIFICATIONS_JSON), NETWORK_MODIFICATIONS_JSON);
addJsonEntry(zipOut, NETWORK_MODIFICATION_FILTERS_JSON, updatedFiltersByOldId);
addFileEntryIfPresent(zipOut, tempDir.resolve(NETWORK_MODIFICATION_LOAD_FLOW_PARAMETERS_JSON), NETWORK_MODIFICATION_LOAD_FLOW_PARAMETERS_JSON);
}
return archiveBytes.toByteArray();
}

private void addFileEntryIfPresent(ZipOutputStream zipOut, Path filePath, String entryName) throws IOException {
if (Files.exists(filePath)) {
zipOut.putNextEntry(new ZipEntry(entryName));
Files.copy(filePath, zipOut);
zipOut.closeEntry();
}
}

private void addJsonEntry(ZipOutputStream zipOut, String entryName, Object content) throws IOException {
zipOut.putNextEntry(new ZipEntry(entryName));
zipOut.write(objectMapper.writeValueAsBytes(content));
zipOut.closeEntry();
}

private void deleteImportedFilters(List<UUID> filterIds, String userId) {
filterIds.forEach(filterId -> {
try {
exploreService.deleteElement(filterId, userId).join();
} catch (Exception cleanupException) {
LOGGER.error("Failed to cleanup imported filter {} after error", filterId, cleanupException);
}
});
}

private void createStudyFromImport(UUID createdStudyUuid, String studyName, String userId, String description,
UUID parentDirectoryUuid, TreeExportInfos updatedExportInfos) {
UUID parentDirectoryUuid, TreeExportInfos updatedExportInfos, byte[] modificationsArchive) {
try {
ElementAttributes elementAttributes = new ElementAttributes(createdStudyUuid, studyName, STUDY, userId, 0L, description, DirectoryElementStatus.CREATING);
studyService.importStudy(userId, updatedExportInfos);
studyService.importStudy(userId, updatedExportInfos, modificationsArchive);
exploreService.createDirectoryElementOrDeleteElement(elementAttributes, parentDirectoryUuid, userId, studyService::delete);
} catch (Exception e) {
deleteStudy(createdStudyUuid, userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
import org.gridsuite.explore.server.dto.NodeInfos;
import org.gridsuite.explore.server.dto.TreeExportInfos;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

Expand Down Expand Up @@ -119,13 +122,26 @@ public ResponseEntity<Void> notifyStudyUpdate(UUID studyUuid, String userId) {
return restTemplate.exchange(studyServerBaseUri + path, HttpMethod.POST, new HttpEntity<>(headers), Void.class);
}

public void importStudy(String userId, TreeExportInfos treeExportInfos) {
public void importStudy(String userId, TreeExportInfos treeExportInfos, byte[] modificationsArchive) {
String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_SERVER_API_VERSION + "/studies/import").toUriString();

HttpHeaders treeExportInfosPartHeaders = new HttpHeaders();
treeExportInfosPartHeaders.setContentType(MediaType.APPLICATION_JSON);

MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("treeExportInfos", new HttpEntity<>(treeExportInfos, treeExportInfosPartHeaders));
body.add("modificationsArchive", new ByteArrayResource(modificationsArchive) {
@Override
public String getFilename() {
return "modifications.zip";
}
});

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add(HEADER_USER_ID, userId);

HttpEntity<TreeExportInfos> request = new HttpEntity<>(treeExportInfos, headers);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(body, headers);
restTemplate.exchange(studyServerBaseUri + path, HttpMethod.POST, request, Void.class);
}
}
Loading