Skip to content

Commit 8e74cac

Browse files
committed
Save changed_by value to quays
1 parent db33c68 commit 8e74cac

File tree

1 file changed

+140
-4
lines changed

1 file changed

+140
-4
lines changed

src/main/java/org/rutebanken/tiamat/versioning/save/StopPlaceVersionedSaverService.java

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package org.rutebanken.tiamat.versioning.save;
1717

18+
import com.google.common.collect.Sets;
1819
import org.rutebanken.tiamat.auth.StopPlaceAuthorizationService;
1920
import org.rutebanken.tiamat.auth.UsernameFetcher;
2021
import org.rutebanken.tiamat.changelog.EntityChangedListener;
@@ -47,6 +48,7 @@
4748

4849
import java.time.Instant;
4950
import java.util.HashSet;
51+
import java.util.List;
5052
import java.util.Set;
5153
import java.util.stream.Collectors;
5254

@@ -64,6 +66,17 @@ public class StopPlaceVersionedSaverService {
6466

6567
public static final InterchangeWeightingEnumeration DEFAULT_WEIGHTING = InterchangeWeightingEnumeration.INTERCHANGE_ALLOWED;
6668

69+
private static final Set<String> QUAY_DIFF_IGNORE_FIELDS = Sets.newHashSet(
70+
"id", "version", "changed", "changedBy", "status", "modification", "envelope", "polygon"
71+
);
72+
73+
private static final Set<String> STOP_PLACE_DIFF_IGNORE_FIELDS = Sets.newHashSet(
74+
"id", "version", "changed", "changedBy", "status", "modification", "envelope", "polygon", "quays", "children", "validBetween", "accessibilityAssessment"
75+
);
76+
77+
private final org.rutebanken.tiamat.diff.generic.GenericDiffConfig quayDiffConfig;
78+
private final org.rutebanken.tiamat.diff.generic.GenericDiffConfig stopPlaceDiffConfig;
79+
6780
@Value("${tiamat.multimodal.allowSameNameForChild:false}")
6881
private boolean allowSameNameForChild;
6982

@@ -115,9 +128,25 @@ public class StopPlaceVersionedSaverService {
115128
@Autowired
116129
private TiamatObjectDiffer tiamatObjectDiffer;
117130

131+
@Autowired
132+
private org.rutebanken.tiamat.diff.generic.GenericObjectDiffer genericObjectDiffer;
133+
118134
@Autowired
119135
private PrometheusMetricsService prometheusMetricsService;
120136

137+
public StopPlaceVersionedSaverService() {
138+
this.quayDiffConfig = org.rutebanken.tiamat.diff.generic.GenericDiffConfig.builder()
139+
.identifiers(Sets.newHashSet("netexId", "ref"))
140+
.ignoreFields(QUAY_DIFF_IGNORE_FIELDS)
141+
.onlyDoEqualsCheck(Sets.newHashSet(org.locationtech.jts.geom.Geometry.class))
142+
.build();
143+
this.stopPlaceDiffConfig = org.rutebanken.tiamat.diff.generic.GenericDiffConfig.builder()
144+
.identifiers(Sets.newHashSet("netexId", "ref"))
145+
.ignoreFields(STOP_PLACE_DIFF_IGNORE_FIELDS)
146+
.onlyDoEqualsCheck(Sets.newHashSet(org.locationtech.jts.geom.Geometry.class))
147+
.build();
148+
}
149+
121150
public StopPlace saveNewVersion(StopPlace existingVersion, StopPlace newVersion, Instant defaultValidFrom) {
122151
return saveNewVersion(existingVersion, newVersion, defaultValidFrom, new HashSet<>());
123152
}
@@ -133,7 +162,7 @@ public StopPlace saveNewVersion(StopPlace existingStopPlace, StopPlace newVersio
133162
public StopPlace saveNewVersion(StopPlace newVersion) {
134163
return saveNewVersion(null, newVersion);
135164
}
136-
165+
137166
public StopPlace saveNewVersion(StopPlace existingVersion, StopPlace newVersion, Instant defaultValidFrom, Set<String> childStopsUpdated) {
138167

139168
versionValidator.validate(existingVersion, newVersion);
@@ -158,11 +187,18 @@ public StopPlace saveNewVersion(StopPlace existingVersion, StopPlace newVersion,
158187
submodeValidator.validate(newVersion);
159188

160189
Instant changed = Instant.now();
161-
newVersion.setChanged(changed);
162190

163-
logger.debug("Rearrange accessibility assessments for: {}", newVersion);
164191
accessibilityAssessmentOptimizer.optimizeAccessibilityAssessments(newVersion);
165192

193+
// Clean up empty/invalid fields before comparison
194+
cleanEmptyFields(newVersion);
195+
if (existingVersion != null) {
196+
cleanEmptyFields(existingVersion);
197+
}
198+
199+
// Check if the stop place itself (excluding quays) has changed
200+
boolean stopPlaceChanged = hasStopPlaceChanged(existingVersion, newVersion);
201+
166202
Instant newVersionValidFrom = validityUpdater.updateValidBetween(existingVersion, newVersion, defaultValidFrom);
167203

168204
if (existingVersion == null) {
@@ -177,9 +213,42 @@ public StopPlace saveNewVersion(StopPlace existingVersion, StopPlace newVersion,
177213
stopPlaceAuthorizationService.assertAuthorizedToEdit(existingVersionRefetched, newVersion, childStopsUpdated);
178214
}
179215

216+
// Identify which quays actually changed by comparing their content
217+
final Set<String> modifiedQuayNetexIds = newVersion.getQuays() == null ? new HashSet<>() :
218+
newVersion.getQuays().stream()
219+
.filter(quay -> {
220+
if (existingVersion == null || existingVersion.getQuays() == null) {
221+
return true;
222+
}
223+
var existingQuay = existingVersion.getQuays().stream()
224+
.filter(eq -> eq.getNetexId() != null && eq.getNetexId().equals(quay.getNetexId()))
225+
.findFirst()
226+
.orElse(null);
227+
return hasQuayChanged(existingQuay, quay);
228+
})
229+
.map(quay -> quay.getNetexId())
230+
.collect(Collectors.toSet());
231+
180232
newVersion = versionIncrementor.initiateOrIncrementVersions(newVersion);
181233

182-
newVersion.setChangedBy(usernameFetcher.getUserNameForAuthenticatedUser());
234+
String changedByUser = usernameFetcher.getUserNameForAuthenticatedUser();
235+
236+
// Only update stop place's changed/changedBy if stop place itself changed
237+
if (stopPlaceChanged) {
238+
newVersion.setChanged(changed);
239+
newVersion.setChangedBy(changedByUser);
240+
}
241+
242+
// Set changed and changedBy only on quays that were actually modified
243+
if (newVersion.getQuays() != null) {
244+
newVersion.getQuays().forEach(quay -> {
245+
if (modifiedQuayNetexIds.contains(quay.getNetexId())) {
246+
quay.setChanged(changed);
247+
quay.setChangedBy(changedByUser);
248+
}
249+
});
250+
}
251+
183252
logger.info("StopPlace [{}], version {} changed by user [{}]. {}", newVersion.getNetexId(), newVersion.getVersion(), newVersion.getChangedBy(), newVersion.getValidBetween());
184253

185254
if (newVersion.getWeighting() == null) {
@@ -194,6 +263,7 @@ public StopPlace saveNewVersion(StopPlace existingVersion, StopPlace newVersion,
194263
if (newVersion.getChildren() != null) {
195264
newVersion.getChildren().forEach(child -> {
196265
child.setChanged(changed);
266+
child.setChangedBy(changedByUser);
197267
tariffZonesLookupService.populateTariffZone(child);
198268
});
199269

@@ -307,4 +377,70 @@ private void updateParentSiteRefsForChildren(StopPlace parentStopPlace) {
307377
logger.info("Updated {} childs with parent site refs", count);
308378
}
309379

380+
/**
381+
* Check if a quay has actual changes by comparing with its previous version.
382+
* Ignores auto-generated fields like polygon, version, changed, etc.
383+
*
384+
* @param existingQuay the previous version of the quay (optional)
385+
* @param newQuay the new version of the quay
386+
* @return true if the quay has actual changes or is new
387+
*/
388+
private boolean hasQuayChanged(org.rutebanken.tiamat.model.Quay existingQuay, org.rutebanken.tiamat.model.Quay newQuay) {
389+
if (existingQuay == null) {
390+
return true;
391+
}
392+
393+
try {
394+
return !genericObjectDiffer.compareObjects(existingQuay, newQuay, quayDiffConfig).isEmpty();
395+
} catch (IllegalAccessException e) {
396+
logger.warn("Could not compare quay {}, marking as modified", newQuay.getNetexId(), e);
397+
return true;
398+
}
399+
}
400+
401+
/**
402+
* Check if a stop place has actual changes by comparing with its previous version.
403+
* Excludes quays and children from comparison.
404+
*
405+
* @param existingStopPlace the previous version of the stop place (optional)
406+
* @param newStopPlace the new version of the stop place
407+
* @return true if the stop place has actual changes or is new
408+
*/
409+
private boolean hasStopPlaceChanged(StopPlace existingStopPlace, StopPlace newStopPlace) {
410+
if (existingStopPlace == null) {
411+
return true;
412+
}
413+
414+
try {
415+
return !genericObjectDiffer.compareObjects(existingStopPlace, newStopPlace, stopPlaceDiffConfig).isEmpty();
416+
} catch (IllegalAccessException e) {
417+
logger.warn("Could not compare stop place {}, marking as modified", newStopPlace.getNetexId(), e);
418+
return true;
419+
}
420+
}
421+
422+
/**
423+
* Remove empty or invalid fields that shouldn't count as actual changes.
424+
*/
425+
private void cleanEmptyFields(StopPlace stopPlace) {
426+
// Clean empty alternative names
427+
if (stopPlace.getAlternativeNames() != null) {
428+
stopPlace.getAlternativeNames().removeIf(altName ->
429+
altName.getName() == null ||
430+
altName.getName().getValue() == null ||
431+
altName.getName().getValue().trim().isEmpty() ||
432+
"null".equalsIgnoreCase(altName.getName().getValue().trim())
433+
);
434+
}
435+
436+
// Clean empty keyValues entries
437+
if (stopPlace.getKeyValues() != null) {
438+
stopPlace.getKeyValues().entrySet().removeIf(entry ->
439+
entry.getValue() == null ||
440+
entry.getValue().getItems() == null ||
441+
entry.getValue().getItems().isEmpty()
442+
);
443+
}
444+
}
445+
310446
}

0 commit comments

Comments
 (0)