Skip to content

Commit e8fc8f3

Browse files
committed
[RELEASE]-merging 'hotfix/2.0.15' into 'master'
2 parents a454ef1 + 2eccfb2 commit e8fc8f3

File tree

13 files changed

+295
-108
lines changed

13 files changed

+295
-108
lines changed

klass-api/src/main/java/no/ssb/klass/api/controllers/ClassificationController.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,19 @@ private CorrespondenceItemList correspondsInternal(Long id, Long targetClassific
391391
DateRangeHolder dateRangeHolder, String csvSeparator, Language language, Boolean includeFuture) {
392392
List<CorrespondenceDto> correspondences = classificationService.findCorrespondences(id, targetClassificationId,
393393
dateRangeHolder.dateRange, language, includeFuture);
394-
return new CorrespondenceItemList(csvSeparator, dateRangeHolder.withRange, includeFuture).convert(correspondences)
395-
.removeOutside(dateRangeHolder.dateRange).limit(dateRangeHolder.dateRange).compress().sort();
394+
return new CorrespondenceItemList(csvSeparator, dateRangeHolder.withRange, includeFuture)
395+
.convert(correspondences)
396+
.removeOutside(dateRangeHolder.dateRange)
397+
.limit(dateRangeHolder.dateRange)
398+
.group()
399+
.sort();
396400
}
397401

398402
@Transactional
399403
@RequestMapping(value = "/classifications/{classificationId}/trackChanges", method = RequestMethod.POST)
400404
public ResponseEntity<SubscribeResponse> trackChanges(@PathVariable Long classificationId, @RequestParam(
401405
value = "email") String email) {
402-
ClassificationSeries classification = null;
406+
ClassificationSeries classification;
403407
try {
404408
classification = classificationService.getClassificationSeries(classificationId);
405409
if (subscriberService.containsTracking(email, classification)) {
@@ -493,6 +497,14 @@ private static class DateRangeHolder {
493497
this.dateRange = DateRange.create(date, date.plusDays(1));
494498
this.withRange = false;
495499
}
500+
501+
@Override
502+
public String toString() {
503+
return "DateRangeHolder{" +
504+
"dateRange=" + dateRange +
505+
", withRange=" + withRange +
506+
'}';
507+
}
496508
}
497509

498510
private static class CaseInsensitiveConverter<T extends Enum<T>> extends PropertyEditorSupport {

klass-api/src/main/java/no/ssb/klass/api/dto/CorrespondenceItem.java

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,31 @@
1313
import no.ssb.klass.core.util.DateRange;
1414
import no.ssb.klass.core.util.TimeUtil;
1515
import no.ssb.klass.api.util.CustomLocalDateSerializer;
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
1618

1719
@JsonPropertyOrder(value = { "sourceCode", "sourceName", "sourceShortName", "targetCode", "targetName",
1820
"targetShortName" })
1921
public class CorrespondenceItem implements Comparable<CorrespondenceItem> {
22+
2023
private final String sourceCode;
2124
private final String sourceName;
2225
private final String sourceShortName;
2326
private final String targetCode;
2427
private final String targetName;
2528
private final String targetShortName;
2629

30+
public CorrespondenceItem(String sourceCode, String sourceName, String sourceShortName,
31+
String targetCode, String targetName, String targetShortName)
32+
{
33+
this.sourceCode = sourceCode;
34+
this.sourceName = sourceName;
35+
this.sourceShortName = sourceShortName;
36+
this.targetCode = targetCode;
37+
this.targetName = targetName;
38+
this.targetShortName = targetShortName;
39+
}
40+
2741
public CorrespondenceItem(CorrespondenceItem correspondenceItem) {
2842
this.sourceCode = correspondenceItem.getSourceCode();
2943
this.sourceName = correspondenceItem.getSourceName();
@@ -73,28 +87,24 @@ public int hashCode() {
7387

7488
@Override
7589
public boolean equals(Object obj) {
76-
if (obj == null) {
77-
return false;
78-
}
79-
if (getClass() != obj.getClass()) {
80-
return false;
81-
}
82-
83-
CorrespondenceItem other = (CorrespondenceItem) obj;
84-
return Objects.equals(this.sourceCode, other.sourceCode) && Objects.equals(this.sourceName, other.sourceName)
85-
&& Objects.equals(this.targetCode, other.targetCode) && Objects.equals(this.targetName,
86-
other.targetName);
90+
return obj != null && getClass() == obj.getClass() &&
91+
Objects.equals(this.sourceCode, ((CorrespondenceItem) obj).sourceCode) &&
92+
Objects.equals(this.sourceName, ((CorrespondenceItem) obj).sourceName) &&
93+
Objects.equals(this.targetCode, ((CorrespondenceItem) obj).targetCode) &&
94+
Objects.equals(this.targetName, ((CorrespondenceItem) obj).targetName);
8795
}
8896

8997
@Override
9098
public int compareTo(CorrespondenceItem other) {
91-
return ComparisonChain.start().compare(this.sourceCode, other.sourceCode).compare(this.sourceName,
92-
other.sourceName).compare(this.targetCode, other.targetCode).compare(this.targetName, other.targetName)
93-
.result();
99+
return ComparisonChain.start()
100+
.compare(this.sourceCode, other.sourceCode)
101+
.compare(this.sourceName, other.sourceName)
102+
.compare(this.targetCode, other.targetCode)
103+
.compare(this.targetName, other.targetName).result();
94104
}
95105

96106
/**
97-
* A CorrespondenceItem that has a valid range
107+
* A CorrespondenceItem that has a validity range
98108
*/
99109
@JsonPropertyOrder(value = { "sourceCode", "sourceName", "sourceShortName", "targetCode", "targetName",
100110
"targetShortName", "validFrom", "validTo" })
@@ -113,27 +123,30 @@ public RangedCorrespondenceItem(CorrespondenceItem correspondenceItem, DateRange
113123

114124
@JsonSerialize(using = CustomLocalDateSerializer.class)
115125
public LocalDate getValidFrom() {
116-
if (TimeUtil.isMinDate(validRange.getFrom())) {
117-
return null;
118-
}
119-
return validRange.getFrom();
126+
return TimeUtil.isMinDate(validRange.getFrom()) ? null : validRange.getFrom();
120127
}
121128

122129
@JsonSerialize(using = CustomLocalDateSerializer.class)
123130
public LocalDate getValidTo() {
124-
if (TimeUtil.isMaxDate(validRange.getTo())) {
125-
return null;
126-
}
127-
return validRange.getTo();
131+
return TimeUtil.isMaxDate(validRange.getTo()) ? null : validRange.getTo();
128132
}
129133

130134
@JsonIgnore
131135
public DateRange getDateRange(boolean includeFuture) {
132-
if (!includeFuture && validRange.isCurrentVersion() ) {
133-
return new DateRange(validRange.getFrom(), LocalDate.MAX);
134-
}
135-
return validRange;
136+
return !includeFuture && validRange.isCurrentVersion()
137+
? new DateRange(validRange.getFrom(), LocalDate.MAX)
138+
: validRange;
136139
}
137140

141+
@Override
142+
public String toString() {
143+
return "RangedCorrespondenceItem{" +
144+
"sourceCode='" + super.sourceCode + '\'' +
145+
", sourceName='" + super.sourceName + '\'' +
146+
", targetCode='" + super.targetCode + '\'' +
147+
", targetName='" + super.targetName + '\'' +
148+
", validRange=" + validRange +
149+
'}';
150+
}
138151
}
139152
}
Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
package no.ssb.klass.api.dto;
22

33
import static java.util.stream.Collectors.*;
4-
5-
import java.time.LocalDate;
6-
import java.util.ArrayList;
7-
import java.util.Collections;
8-
import java.util.List;
9-
import java.util.Map;
10-
4+
import java.util.*;
115
import com.fasterxml.jackson.annotation.JsonIgnore;
126
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
137
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
148
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
159
import com.google.common.base.Preconditions;
16-
1710
import no.ssb.klass.core.service.dto.CorrespondenceDto;
1811
import no.ssb.klass.core.util.DateRange;
19-
import no.ssb.klass.core.util.TimeUtil;
2012
import no.ssb.klass.api.dto.CorrespondenceItem.RangedCorrespondenceItem;
2113

2214
@JacksonXmlRootElement(localName = "correspondenceItemList")
@@ -50,7 +42,7 @@ public List<? extends CorrespondenceItem> getCorrespondenceItems() {
5042
if (displayWithValidRange) {
5143
return correspondenceItems;
5244
}
53-
return correspondenceItems.stream().map(i -> new CorrespondenceItem(i)).collect(toList());
45+
return correspondenceItems.stream().map(CorrespondenceItem::new).collect(toList());
5446
}
5547

5648
@JsonIgnore
@@ -59,47 +51,59 @@ public char getCsvSeparator() {
5951
}
6052

6153
public CorrespondenceItemList convert(List<CorrespondenceDto> correspondences) {
62-
return newCorrespondenceItemList(correspondences.stream().map(RangedCorrespondenceItem::new).collect(toList()));
54+
return newList(correspondences.stream()
55+
.map(RangedCorrespondenceItem::new)
56+
.collect(toList()));
6357
}
6458

65-
private CorrespondenceItemList newCorrespondenceItemList(List<RangedCorrespondenceItem> items) {
59+
private CorrespondenceItemList newList(List<RangedCorrespondenceItem> items) {
6660
return new CorrespondenceItemList(csvSeparator, displayWithValidRange, items, includeFuture);
6761
}
6862

6963
public CorrespondenceItemList removeOutside(DateRange dateRange) {
7064
Preconditions.checkNotNull(dateRange);
71-
return newCorrespondenceItemList(correspondenceItems.stream().filter(correspondenceItem -> correspondenceItem
72-
.getDateRange(includeFuture).overlaps(dateRange)).collect(toList()));
65+
return newList(correspondenceItems.stream()
66+
.filter(i -> i.getDateRange(includeFuture).overlaps(dateRange))
67+
.collect(toList()));
7368
}
7469

7570
public CorrespondenceItemList limit(DateRange dateRange) {
76-
return newCorrespondenceItemList(correspondenceItems.stream().map(
77-
correspondenceItem -> new RangedCorrespondenceItem(correspondenceItem, correspondenceItem.getDateRange(includeFuture)
78-
.subRange(dateRange))).collect(toList()));
71+
return newList(correspondenceItems.stream()
72+
.map(i -> new RangedCorrespondenceItem(i, i.getDateRange(includeFuture).subRange(dateRange)))
73+
.collect(toList()));
7974
}
8075

81-
public CorrespondenceItemList compress() {
82-
Map<RangedCorrespondenceItem, List<RangedCorrespondenceItem>> grouped = correspondenceItems.stream().collect(
83-
groupingBy(correspondenceItem -> correspondenceItem));
84-
return newCorrespondenceItemList(grouped.entrySet().stream().map(entry -> combineCorrespondenceItems(entry
85-
.getKey(), entry.getValue())).collect(toList()));
86-
}
76+
public CorrespondenceItemList group() {
77+
Map<RangedCorrespondenceItem, List<RangedCorrespondenceItem>> grouped = correspondenceItems.stream().collect(groupingBy(i -> i));
8778

88-
private RangedCorrespondenceItem combineCorrespondenceItems(RangedCorrespondenceItem base,
89-
List<RangedCorrespondenceItem> correspondenceItems) {
90-
// TODO kmgv need to check dateRanges of correspondenceItems, and group those that are back to back.
91-
DateRange dateRange = DateRange.create(minValidFrom(correspondenceItems), maxValidTo(correspondenceItems));
92-
return new RangedCorrespondenceItem(base, dateRange);
79+
return newList(grouped.values().stream()
80+
.map(i -> newList(i).merge())
81+
.flatMap(Collection::stream)
82+
.collect(toList()));
9383
}
9484

95-
private LocalDate maxValidTo(List<RangedCorrespondenceItem> correspondenceItems) {
96-
return TimeUtil.max(correspondenceItems.stream().map(correspondenceItem -> correspondenceItem.getDateRange(includeFuture)
97-
.getTo()).collect(toList()));
98-
}
85+
// NB! suits for equal correspondence items (source and target, but not range)
86+
public List<RangedCorrespondenceItem> merge() {
87+
if (correspondenceItems == null || correspondenceItems.isEmpty()) {
88+
return Collections.emptyList();
89+
}
9990

100-
private LocalDate minValidFrom(List<RangedCorrespondenceItem> correspondenceItems) {
101-
return TimeUtil.min(correspondenceItems.stream().map(correspondenceItem -> correspondenceItem.getDateRange(includeFuture)
102-
.getFrom()).collect(toList()));
91+
correspondenceItems.sort(Comparator.comparing(RangedCorrespondenceItem::getValidFrom));
92+
93+
List<DateRange> ranges = new ArrayList<>();
94+
95+
correspondenceItems.forEach(i -> {
96+
DateRange next = i.getDateRange(includeFuture);
97+
DateRange prev = ranges.isEmpty() ? next : ranges.get(ranges.size() - 1);
98+
99+
if (prev.contiguous(next)) {
100+
ranges.set(ranges.size() - 1, new DateRange(prev.getFrom(), next.getTo()));
101+
} else {
102+
ranges.add(next);
103+
}
104+
});
105+
106+
return ranges.stream().map(i -> new RangedCorrespondenceItem(correspondenceItems.get(0), i)).collect(toList());
103107
}
104108

105109
public CorrespondenceItemList sort() {
@@ -111,4 +115,13 @@ public Class<?> classificationItemsJavaType() {
111115
return displayWithValidRange ? RangedCorrespondenceItem.class : CorrespondenceItem.class;
112116
}
113117

118+
@Override
119+
public String toString() {
120+
return "CorrespondenceItemList{" +
121+
"csvSeparator=" + csvSeparator +
122+
", displayWithValidRange=" + displayWithValidRange +
123+
", correspondenceItems=" + correspondenceItems +
124+
", includeFuture=" + includeFuture +
125+
'}';
126+
}
114127
}

klass-api/src/test/java/no/ssb/klass/api/applicationtest/RestApiCorrespondsIntegrationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.hamcrest.Matchers.*;
55

66
import no.ssb.klass.testutil.TestDataProvider;
7+
import org.junit.Ignore;
78
import org.junit.Test;
89
import org.springframework.http.HttpStatus;
910

klass-api/src/test/java/no/ssb/klass/api/dto/CodeChangeItemTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package no.ssb.klass.api.dto;
22

33
import static org.junit.Assert.*;
4-
5-
import java.time.LocalDate;
6-
74
import org.junit.Test;
8-
5+
import java.time.LocalDate;
96
import no.ssb.klass.core.model.ClassificationItem;
107
import no.ssb.klass.core.model.ConcreteClassificationItem;
118
import no.ssb.klass.core.model.CorrespondenceMap;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package no.ssb.klass.api.dto.hal;
2+
3+
import static org.junit.Assert.*;
4+
5+
import no.ssb.klass.api.dto.CorrespondenceItem;
6+
import no.ssb.klass.api.dto.CorrespondenceItem.RangedCorrespondenceItem;
7+
import no.ssb.klass.api.dto.CorrespondenceItemList;
8+
import no.ssb.klass.core.util.DateRange;
9+
import org.junit.Test;
10+
11+
import java.util.Arrays;
12+
import java.util.List;
13+
14+
15+
public class CorrespondenceItemListTest {
16+
17+
@Test
18+
public void mergeTest() {
19+
// given
20+
CorrespondenceItem item = new CorrespondenceItem("1", "A", "a", "2", "B", "b");
21+
List<RangedCorrespondenceItem> items = Arrays.asList(
22+
new RangedCorrespondenceItem(item, DateRange.create("2010-01-01", "2011-01-01")),
23+
24+
new RangedCorrespondenceItem(item, DateRange.create("2006-01-01", "2007-01-01")),
25+
new RangedCorrespondenceItem(item, DateRange.create("2007-01-01", "2008-01-01")),
26+
27+
new RangedCorrespondenceItem(item, DateRange.create("2012-01-01", "2013-01-01")),
28+
new RangedCorrespondenceItem(item, DateRange.create("2013-01-01", "2014-01-01")),
29+
new RangedCorrespondenceItem(item, DateRange.create("2014-01-01", null))
30+
);
31+
CorrespondenceItemList list = new CorrespondenceItemList('-', true, items, true);
32+
33+
// when
34+
List<RangedCorrespondenceItem> result = list.merge();
35+
36+
// then
37+
assertEquals(result.get(0).getDateRange(true), DateRange.create("2006-01-01", "2008-01-01"));
38+
assertEquals(result.get(1).getDateRange(false), DateRange.create("2010-01-01", "2011-01-01"));
39+
assertEquals(result.get(2).getDateRange(true), DateRange.create("2012-01-01", null));
40+
}
41+
}

klass-shared/src/main/java/no/ssb/klass/core/model/ClassificationVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import javax.persistence.ManyToOne;
1414
import javax.persistence.OneToMany;
1515

16+
import jdk.nashorn.internal.ir.annotations.Ignore;
1617
import org.springframework.util.StringUtils;
1718

1819
import no.ssb.klass.core.util.DateRange;

klass-shared/src/main/java/no/ssb/klass/core/service/dto/CorrespondenceDto.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,14 @@ public String getTargetShortName() {
5656
public DateRange getValidRange() {
5757
return validRange;
5858
}
59+
60+
@Override
61+
public String toString() {
62+
return "CorrespondenceDto{" +
63+
"sourceCode='" + sourceCode + '\'' +
64+
", sourceName='" + sourceName + '\'' +
65+
", targetCode='" + targetName + '\'' +
66+
", validRange=" + validRange +
67+
'}';
68+
}
5969
}

0 commit comments

Comments
 (0)