Skip to content

Commit cc0fc72

Browse files
Ensure column id and column name unicity when duplicating a column (#71)
* Ensure column id and column name unicity when duplicating a column * Fix duplicated column renaming, to avoid unaccepted characters Signed-off-by: Franck LECUYER <[email protected]>
1 parent 843c0cd commit cc0fc72

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

src/main/java/org/gridsuite/studyconfig/server/service/SpreadsheetConfigService.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import jakarta.persistence.EntityNotFoundException;
1010
import lombok.RequiredArgsConstructor;
11+
import org.apache.commons.lang3.tuple.Pair;
1112
import org.gridsuite.studyconfig.server.dto.*;
1213
import org.gridsuite.studyconfig.server.entities.ColumnEntity;
1314
import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity;
@@ -371,16 +372,48 @@ private static void reorderColumns(List<UUID> columnOrder, List<ColumnEntity> co
371372
columns.sort(Comparator.comparingInt(column -> columnOrder.indexOf(column.getUuid())));
372373
}
373374

375+
private String newCandidate(String base, int n) {
376+
return base + '_' + n;
377+
}
378+
379+
/**
380+
* Generates a unique value by appending a numeric suffix if the original value already exists.
381+
*
382+
* @param originalValue the original value to make unique
383+
* @param existingValues set of existing values to avoid conflicts with
384+
* @return a unique value, either the original or with a numeric suffix
385+
*/
386+
private String getUniqueValue(String originalValue, Set<String> existingValues) {
387+
if (!existingValues.contains(originalValue)) {
388+
return originalValue;
389+
}
390+
391+
int i = 1;
392+
while (existingValues.contains(newCandidate(originalValue, i))) {
393+
++i;
394+
}
395+
return newCandidate(originalValue, i);
396+
}
397+
398+
private Pair<String, String> getDuplicateIdAndNameCandidate(SpreadsheetConfigEntity entity, String columnId, String columnName) {
399+
var existingColumnIds = entity.getColumns().stream().map(ColumnEntity::getId).collect(Collectors.toSet());
400+
var existingColumnNames = entity.getColumns().stream().map(ColumnEntity::getName).collect(Collectors.toSet());
401+
String newColumnId = getUniqueValue(columnId, existingColumnIds);
402+
String newColumnName = getUniqueValue(columnName, existingColumnNames);
403+
404+
return Pair.of(newColumnId, newColumnName);
405+
}
406+
374407
@Transactional
375408
public void duplicateColumn(UUID id, UUID columnId) {
376409
SpreadsheetConfigEntity entity = findEntityById(id);
377410
ColumnEntity columnEntity = entity.getColumns().stream().filter(col -> col.getUuid().equals(columnId))
378411
.findFirst().orElseThrow(() -> new EntityNotFoundException(COLUMN_NOT_FOUND + columnId));
379412
ColumnEntity columnCopy = columnEntity.toBuilder().build();
380413
columnCopy.setUuid(UUID.randomUUID());
381-
columnCopy.setId(columnCopy.getId() + "copy");
382-
columnCopy.setName(columnCopy.getName() + "-copy");
383-
414+
Pair<String, String> idAndName = getDuplicateIdAndNameCandidate(entity, columnCopy.getId(), columnCopy.getName());
415+
columnCopy.setId(idAndName.getLeft());
416+
columnCopy.setName(idAndName.getRight());
384417
List<ColumnEntity> columns = entity.getColumns();
385418
columns.add(columns.indexOf(columnEntity) + 1, columnCopy);
386419
entity.setColumns(columns);

src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigIntegrationTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.stream.Collectors;
3131

3232
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.junit.jupiter.api.Assertions.assertEquals;
3334
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
3435
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
3536

@@ -328,12 +329,22 @@ void testDuplicateColumn() throws Exception {
328329
ColumnInfos duplicatedColumnInfos = configAfterDuplicate.columns().get(1);
329330

330331
assertThat(columnInfos.uuid()).isNotEqualTo(duplicatedColumnInfos.uuid());
331-
assertThat(columnInfos.id()).isNotEqualTo(duplicatedColumnInfos.id());
332+
assertEquals(columnInfos.id() + "_1", duplicatedColumnInfos.id());
333+
assertEquals(columnInfos.name() + "_1", duplicatedColumnInfos.name());
332334
assertThat(columnInfos.visible()).isEqualTo(duplicatedColumnInfos.visible());
333335
assertThat(columnInfos.formula()).isEqualTo(duplicatedColumnInfos.formula());
334336
assertThat(columnInfos.dependencies()).isEqualTo(duplicatedColumnInfos.dependencies());
335337
assertThat(columnInfos.precision()).isEqualTo(duplicatedColumnInfos.precision());
336338

339+
mockMvc.perform(post(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE + "/" + columnId + "/duplicate"))
340+
.andExpect(status().isNoContent());
341+
configAfterDuplicate = getSpreadsheetConfig(configId);
342+
assertThat(configAfterDuplicate.columns()).hasSize(6);
343+
duplicatedColumnInfos = configAfterDuplicate.columns().get(1);
344+
assertThat(columnInfos.uuid()).isNotEqualTo(duplicatedColumnInfos.uuid());
345+
assertEquals(columnInfos.id() + "_2", duplicatedColumnInfos.id());
346+
assertEquals(columnInfos.name() + "_2", duplicatedColumnInfos.name());
347+
337348
mockMvc.perform(post(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE + "/" + UUID.randomUUID() + "/duplicate"))
338349
.andExpect(status().isNotFound());
339350
}

0 commit comments

Comments
 (0)