Skip to content

Commit 86994b8

Browse files
authored
Fix sorting bug (#2404)
Fix sorting bug RISDEV-5333
1 parent 1c403b1 commit 86994b8

File tree

9 files changed

+136
-101
lines changed

9 files changed

+136
-101
lines changed

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/database/jpa/DependentLiteratureCitationDTO.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import jakarta.persistence.JoinColumn;
99
import jakarta.persistence.ManyToOne;
1010
import jakarta.persistence.Table;
11+
import jakarta.persistence.Transient;
1112
import jakarta.validation.constraints.NotBlank;
1213
import jakarta.validation.constraints.NotNull;
1314
import java.util.UUID;
@@ -55,4 +56,6 @@ public class DependentLiteratureCitationDTO {
5556
private String documentTypeRawValue;
5657

5758
private Integer rank;
59+
60+
@Transient private Integer editionRank;
5861
}

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/database/jpa/LegalPeriodicalEditionDTO.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.time.LocalDate;
1414
import java.util.ArrayList;
1515
import java.util.List;
16+
import java.util.Map;
1617
import java.util.UUID;
1718
import java.util.stream.Collectors;
1819
import lombok.AllArgsConstructor;
@@ -54,18 +55,18 @@ public class LegalPeriodicalEditionDTO {
5455
private List<EditionReferenceDTO> editionReferences = new ArrayList<>();
5556

5657
// Methods to get references and literature citations
57-
public List<UUID> getLiteratureCitations() {
58+
public Map<UUID, Integer> getLiteratureCitations() {
5859
return editionReferences.stream()
5960
.filter(ref -> LITERATURE.equals(ref.getDtype()))
60-
.map(EditionReferenceDTO::getReferenceId)
61-
.collect(Collectors.toList());
61+
.collect(
62+
Collectors.toMap(EditionReferenceDTO::getReferenceId, EditionReferenceDTO::getRank));
6263
}
6364

64-
public List<UUID> getReferences() {
65+
public Map<UUID, Integer> getReferences() {
6566
return editionReferences.stream()
6667
.filter(ref -> REFERENCE.equals(ref.getDtype()))
67-
.map(EditionReferenceDTO::getReferenceId)
68-
.collect(Collectors.toList());
68+
.collect(
69+
Collectors.toMap(EditionReferenceDTO::getReferenceId, EditionReferenceDTO::getRank));
6970
}
7071

7172
public void setLiteratureCitations(List<DependentLiteratureCitationDTO> literatureCitations) {
@@ -77,7 +78,7 @@ public void setLiteratureCitations(List<DependentLiteratureCitationDTO> literatu
7778
EditionReferenceDTO editionReference = new EditionReferenceDTO();
7879
editionReference.setEdition(this);
7980
editionReference.setReferenceId(citation.getId());
80-
editionReference.setRank(citation.getRank());
81+
editionReference.setRank(citation.getEditionRank());
8182
editionReference.setDtype(LITERATURE);
8283
editionReferences.add(editionReference);
8384
}
@@ -91,7 +92,7 @@ public void setReferences(List<ReferenceDTO> references) {
9192
for (ReferenceDTO reference : references) {
9293
EditionReferenceDTO editionReference = new EditionReferenceDTO();
9394
editionReference.setReferenceId(reference.getId());
94-
editionReference.setRank(reference.getRank());
95+
editionReference.setRank(reference.getEditionRank());
9596
editionReference.setDtype(REFERENCE);
9697
editionReference.setEdition(this);
9798
editionReferences.add(editionReference);

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/database/jpa/PostgresLegalPeriodicalEditionRepositoryImpl.java

Lines changed: 93 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import java.util.ArrayList;
1111
import java.util.Comparator;
1212
import java.util.List;
13+
import java.util.Map;
1314
import java.util.Optional;
1415
import java.util.UUID;
15-
import org.jetbrains.annotations.NotNull;
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
import java.util.stream.Collectors;
1618
import org.springframework.stereotype.Repository;
1719
import org.springframework.transaction.annotation.Transactional;
1820

@@ -60,15 +62,34 @@ public List<LegalPeriodicalEdition> findAllByLegalPeriodicalId(UUID legalPeriodi
6062
@Transactional(transactionManager = "jpaTransactionManager")
6163
public LegalPeriodicalEdition save(LegalPeriodicalEdition legalPeriodicalEdition) {
6264

63-
List<ReferenceDTO> referenceDTOS = createReferenceDTOs(legalPeriodicalEdition);
64-
List<DependentLiteratureCitationDTO> dependentLiteratureCitationDTOS =
65-
createLiteratureReferenceDTOs(legalPeriodicalEdition);
66-
deleteDocUnitLinksForDeletedReferences(legalPeriodicalEdition);
65+
List<ReferenceDTO> referenceDTOS = new ArrayList<>();
66+
List<DependentLiteratureCitationDTO> dependentLiteratureCitationDTOS = new ArrayList<>();
67+
68+
AtomicInteger editionRank = new AtomicInteger(1);
69+
for (Reference reference :
70+
Optional.ofNullable(legalPeriodicalEdition.references()).orElse(List.of())) {
71+
72+
var docUnit =
73+
documentationUnitRepository.findByDocumentNumber(
74+
reference.documentationUnit().getDocumentNumber());
75+
76+
if (docUnit.isEmpty()) {
77+
continue;
78+
}
79+
if (reference.referenceType().equals(ReferenceType.CASELAW)) {
80+
referenceDTOS.add(createReferenceDTO(reference, docUnit.get(), editionRank));
81+
}
82+
if (reference.referenceType().equals(ReferenceType.LITERATURE)) {
83+
dependentLiteratureCitationDTOS.add(
84+
createLiteratureCitationDTO(reference, docUnit.get(), editionRank));
85+
}
86+
}
6787

6888
var editionDTO = LegalPeriodicalEditionTransformer.transformToDTO(legalPeriodicalEdition);
69-
editionDTO.setReferences(referenceDTOS); // Add the new references
70-
editionDTO.setLiteratureCitations(
71-
dependentLiteratureCitationDTOS); // Add the new literature references
89+
editionDTO.setReferences(referenceDTOS);
90+
editionDTO.setLiteratureCitations(dependentLiteratureCitationDTOS);
91+
92+
deleteDocUnitLinksForDeletedReferences(legalPeriodicalEdition);
7293

7394
return LegalPeriodicalEditionTransformer.transformToDomain(repository.save(editionDTO))
7495
.toBuilder()
@@ -81,20 +102,32 @@ private ArrayList<Reference> addReferences(LegalPeriodicalEditionDTO editionDTO)
81102

82103
if (editionDTO.getReferences() != null) {
83104
references.addAll(
84-
editionDTO.getReferences().stream()
85-
.map(id -> referenceRepository.findById(id).orElse(null))
105+
editionDTO.getReferences().entrySet().stream()
106+
.map(
107+
entry ->
108+
referenceRepository
109+
.findById(entry.getKey())
110+
.map(dto -> dto.toBuilder().editionRank(entry.getValue()).build())
111+
.orElse(null))
86112
.map(ReferenceTransformer::transformToDomain)
87113
.toList());
88114
}
89115

90116
if (editionDTO.getLiteratureCitations() != null) {
91117
references.addAll(
92-
editionDTO.getLiteratureCitations().stream()
93-
.map(id -> dependentLiteratureCitationRepository.findById(id).orElse(null))
118+
editionDTO.getLiteratureCitations().entrySet().stream()
119+
.map(
120+
entry ->
121+
dependentLiteratureCitationRepository
122+
.findById(entry.getKey())
123+
.map(dto -> dto.toBuilder().editionRank(entry.getValue()).build())
124+
.orElse(null))
94125
.map(DependentLiteratureTransformer::transformToDomain)
95126
.toList());
96127
}
97-
return references;
128+
return references.stream()
129+
.sorted(Comparator.comparingInt(Reference::rank))
130+
.collect(Collectors.toCollection(ArrayList::new));
98131
}
99132

100133
private void deleteDocUnitLinksForDeletedReferences(LegalPeriodicalEdition updatedEdition) {
@@ -103,12 +136,12 @@ private void deleteDocUnitLinksForDeletedReferences(LegalPeriodicalEdition updat
103136
return;
104137
}
105138
// Ensure it's removed from DocumentationUnit's references
106-
for (UUID reference : oldEdition.get().getReferences()) {
139+
for (Map.Entry<UUID, Integer> reference : oldEdition.get().getReferences().entrySet()) {
107140
// skip all existing and null references
108-
var referenceDTO = referenceRepository.findById(reference);
141+
var referenceDTO = referenceRepository.findById(reference.getKey());
109142
if (referenceDTO.isEmpty()
110143
|| updatedEdition.references().stream()
111-
.anyMatch(newReference -> newReference.id().equals(reference))) {
144+
.anyMatch(newReference -> newReference.id().equals(reference.getKey()))) {
112145
continue;
113146
}
114147

@@ -121,7 +154,7 @@ private void deleteDocUnitLinksForDeletedReferences(LegalPeriodicalEdition updat
121154
if (docUnit.getSource().stream()
122155
.findFirst()
123156
.map(SourceDTO::getReference)
124-
.filter(ref -> ref.getId().equals(reference))
157+
.filter(ref -> ref.getId().equals(reference.getKey()))
125158
.isPresent()) {
126159
docUnit.getSource().removeFirst();
127160
}
@@ -130,74 +163,51 @@ private void deleteDocUnitLinksForDeletedReferences(LegalPeriodicalEdition updat
130163
}
131164
}
132165

133-
@NotNull
134-
private List<ReferenceDTO> createReferenceDTOs(LegalPeriodicalEdition legalPeriodicalEdition) {
135-
List<ReferenceDTO> referenceDTOS = new ArrayList<>();
136-
if (legalPeriodicalEdition.references() == null) {
137-
return referenceDTOS;
138-
}
139-
for (Reference reference : legalPeriodicalEdition.references()) {
140-
var docUnit =
141-
documentationUnitRepository.findByDocumentNumber(
142-
reference.documentationUnit().getDocumentNumber());
143-
if (docUnit.isEmpty() || !reference.referenceType().equals(ReferenceType.CASELAW)) {
144-
continue;
145-
}
146-
var newReference = ReferenceTransformer.transformToDTO(reference);
147-
newReference.setDocumentationUnit(docUnit.get());
148-
149-
// keep rank for existing references and set to max rank +1 for new references
150-
newReference.setRank(
151-
docUnit.get().getReferences().stream()
152-
.filter(referenceDTO -> referenceDTO.getId().equals(reference.id()))
153-
.findFirst()
154-
.map(ReferenceDTO::getRank)
155-
.orElseGet(
156-
() ->
157-
docUnit.get().getReferences().stream()
158-
.map(ReferenceDTO::getRank)
159-
.max(Comparator.naturalOrder())
160-
.orElse(0)
161-
+ 1));
162-
163-
referenceDTOS.add(referenceRepository.save(newReference));
164-
}
165-
166-
return referenceDTOS;
166+
private ReferenceDTO createReferenceDTO(
167+
Reference reference, DocumentationUnitDTO docUnit, AtomicInteger editionRank) {
168+
var newReference = ReferenceTransformer.transformToDTO(reference);
169+
newReference.setDocumentationUnit(docUnit);
170+
171+
// keep rank for existing references and set to max rank +1 for new references
172+
newReference.setRank(
173+
docUnit.getReferences().stream()
174+
.filter(referenceDTO -> referenceDTO.getId().equals(reference.id()))
175+
.findFirst()
176+
.map(ReferenceDTO::getRank)
177+
.orElseGet(
178+
() ->
179+
docUnit.getReferences().stream()
180+
.map(ReferenceDTO::getRank)
181+
.max(Comparator.naturalOrder())
182+
.orElse(0)
183+
+ 1));
184+
185+
return referenceRepository.save(newReference).toBuilder()
186+
.editionRank(editionRank.getAndIncrement())
187+
.build();
167188
}
168189

169-
private List<DependentLiteratureCitationDTO> createLiteratureReferenceDTOs(
170-
LegalPeriodicalEdition legalPeriodicalEdition) {
171-
List<DependentLiteratureCitationDTO> dependentLiteratureCitationDTOS = new ArrayList<>();
172-
if (legalPeriodicalEdition.references() == null) {
173-
return dependentLiteratureCitationDTOS;
174-
}
175-
for (Reference reference : legalPeriodicalEdition.references()) {
176-
var docUnit =
177-
documentationUnitRepository.findByDocumentNumber(
178-
reference.documentationUnit().getDocumentNumber());
179-
if (docUnit.isEmpty() || !reference.referenceType().equals(ReferenceType.LITERATURE)) {
180-
continue;
181-
}
182-
183-
var newReference = DependentLiteratureTransformer.transformToDTO(reference);
184-
newReference.setDocumentationUnit(docUnit.get());
185-
// keep rank for existing references and set to max rank +1 for new references
186-
newReference.setRank(
187-
docUnit.get().getReferences().stream()
188-
.filter(referenceDTO -> referenceDTO.getId().equals(reference.id()))
189-
.findFirst()
190-
.map(ReferenceDTO::getRank)
191-
.orElseGet(
192-
() ->
193-
docUnit.get().getDependentLiteratureCitations().stream()
194-
.map(DependentLiteratureCitationDTO::getRank)
195-
.max(Comparator.naturalOrder())
196-
.orElse(0)
197-
+ 1));
198-
dependentLiteratureCitationDTOS.add(dependentLiteratureCitationRepository.save(newReference));
199-
}
200-
return dependentLiteratureCitationDTOS;
190+
private DependentLiteratureCitationDTO createLiteratureCitationDTO(
191+
Reference reference, DocumentationUnitDTO docUnit, AtomicInteger editionRank) {
192+
var newReference = DependentLiteratureTransformer.transformToDTO(reference);
193+
newReference.setDocumentationUnit(docUnit);
194+
195+
// keep rank for existing references and set to max rank +1 for new references
196+
newReference.setRank(
197+
docUnit.getReferences().stream()
198+
.filter(referenceDTO -> referenceDTO.getId().equals(reference.id()))
199+
.findFirst()
200+
.map(ReferenceDTO::getRank)
201+
.orElseGet(
202+
() ->
203+
docUnit.getDependentLiteratureCitations().stream()
204+
.map(DependentLiteratureCitationDTO::getRank)
205+
.max(Comparator.naturalOrder())
206+
.orElse(0)
207+
+ 1));
208+
return dependentLiteratureCitationRepository.save(newReference).toBuilder()
209+
.editionRank(editionRank.getAndIncrement())
210+
.build();
201211
}
202212

203213
@Override

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/database/jpa/ReferenceDTO.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import jakarta.persistence.ManyToOne;
99
import jakarta.persistence.OneToMany;
1010
import jakarta.persistence.Table;
11+
import jakarta.persistence.Transient;
1112
import jakarta.validation.constraints.NotNull;
1213
import java.util.List;
1314
import java.util.UUID;
@@ -60,4 +61,6 @@ public class ReferenceDTO {
6061
insertable = false,
6162
updatable = false)
6263
private List<EditionReferenceDTO> editionReferences;
64+
65+
@Transient private Integer editionRank;
6366
}

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DependentLiteratureTransformer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public static Reference transformToDomain(DependentLiteratureCitationDTO literat
3535
.documentationUnit(
3636
RelatedDocumentationUnitTransformer.transformToDomain(
3737
literatureCitationDTO.getDocumentationUnit()))
38+
// editionRank is only set if reference is requested from edition
39+
.rank(
40+
literatureCitationDTO.getEditionRank() != null
41+
? literatureCitationDTO.getEditionRank()
42+
: literatureCitationDTO.getRank())
3843
.build();
3944
}
4045

backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/ReferenceTransformer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public static Reference transformToDomain(ReferenceDTO referenceDTO) {
3232
.documentationUnit(
3333
RelatedDocumentationUnitTransformer.transformToDomain(
3434
referenceDTO.getDocumentationUnit()))
35+
// editionRank is only set if reference is requested from edition
36+
.rank(
37+
referenceDTO.getEditionRank() != null
38+
? referenceDTO.getEditionRank()
39+
: referenceDTO.getRank())
3540
.build();
3641
}
3742

backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/Reference.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ public record Reference(
2727
DocumentType documentType,
2828
String author,
2929
ReferenceType referenceType,
30-
RelatedDocumentationUnit documentationUnit) {}
30+
RelatedDocumentationUnit documentationUnit,
31+
int rank) {}

backend/src/test/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/ReferencesTransformerTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,18 @@ private static Stream<Arguments> provideReferencesTestData_toDomain() {
3636
.legalPeriodical(createTestLegalPeriodicalDTO())
3737
.build(),
3838
Reference.builder()
39+
.rank(1)
3940
.citation("2024, 123")
4041
.footnote("footnote")
4142
.referenceSupplement("Klammerzusatz")
4243
.referenceType(ReferenceType.CASELAW)
4344
.documentationUnit(createTestRelatedDocument())
4445
.legalPeriodical(createTestLegalPeriodical())
4546
.build()),
46-
// without legal periodical
47+
// without legal periodical, with editionRank
4748
Arguments.of(
4849
ReferenceDTO.builder()
50+
.editionRank(3)
4951
.rank(1)
5052
.citation("2024, 123")
5153
.footnote("footnote")
@@ -54,6 +56,7 @@ private static Stream<Arguments> provideReferencesTestData_toDomain() {
5456
.documentationUnit(createTestDocumentationUnitDTO())
5557
.build(),
5658
Reference.builder()
59+
.rank(3)
5760
.citation("2024, 123")
5861
.footnote("footnote")
5962
.referenceSupplement("Klammerzusatz")

0 commit comments

Comments
 (0)