Skip to content

Commit 59fd5e3

Browse files
authored
Merge pull request #327 from entur/renovate/netex-parser-java.version-fix
Renovate/netex parser java.version fix
2 parents 6d15367 + 4a533dc commit 59fd5e3

File tree

11 files changed

+228
-14
lines changed

11 files changed

+228
-14
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<properties>
1616
<java.version>21</java.version>
1717
<entur.helpers.version>5.50.0</entur.helpers.version>
18-
<netex-parser-java.version>3.0.5</netex-parser-java.version>
18+
<netex-parser-java.version>3.1.77</netex-parser-java.version>
1919
<jakarta-xml-bind.version>4.0.5</jakarta-xml-bind.version>
2020
<glassfish-jaxb.version>4.0.6</glassfish-jaxb.version>
2121
</properties>

src/main/java/no/entur/mummu/config/SwaggerConfiguration.java

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@
99
import io.swagger.v3.oas.models.OpenAPI;
1010
import io.swagger.v3.oas.models.info.Contact;
1111
import io.swagger.v3.oas.models.info.Info;
12+
import io.swagger.v3.oas.models.media.ArraySchema;
13+
import io.swagger.v3.oas.models.media.Schema;
1214
import io.swagger.v3.oas.models.servers.Server;
1315
import io.swagger.v3.oas.models.tags.Tag;
16+
import org.springdoc.core.customizers.OpenApiCustomizer;
1417
import org.springdoc.core.properties.SpringDocConfigProperties;
1518
import org.springdoc.core.providers.ObjectMapperProvider;
1619
import org.springframework.beans.factory.annotation.Value;
1720
import org.springframework.context.annotation.Bean;
1821
import org.springframework.context.annotation.Configuration;
1922

23+
import java.util.LinkedHashMap;
2024
import java.util.List;
25+
import java.util.Map;
2126

2227
@Configuration
2328
public class SwaggerConfiguration {
@@ -82,6 +87,120 @@ public OpenAPI customOpenAPI() {
8287
));
8388
}
8489

90+
@Bean
91+
public OpenApiCustomizer netexModelCompatibilityCustomizer() {
92+
return openApi -> {
93+
Map<String, Schema> schemas = openApi.getComponents().getSchemas();
94+
if (schemas == null) return;
95+
96+
// Fix TariffZoneRefs_RelStructure: rename tariffZoneRef_ back to tariffZoneRef
97+
Schema tariffZoneRefs = schemas.get("TariffZoneRefs_RelStructure");
98+
if (tariffZoneRefs != null && tariffZoneRefs.getProperties() != null) {
99+
Map<String, Schema> props = tariffZoneRefs.getProperties();
100+
if (props.containsKey("tariffZoneRef_")) {
101+
Schema tariffZoneRefProp = props.remove("tariffZoneRef_");
102+
// Restore original schema: array of TariffZoneRef with XML name
103+
Schema restoredProp = new ArraySchema()
104+
.items(new Schema<>().$ref("#/components/schemas/TariffZoneRef"));
105+
restoredProp.xml(new io.swagger.v3.oas.models.media.XML().name("TariffZoneRef"));
106+
props.put("tariffZoneRef", restoredProp);
107+
// Re-sort properties alphabetically
108+
Map<String, Schema> sorted = new LinkedHashMap<>();
109+
props.entrySet().stream()
110+
.sorted(Map.Entry.comparingByKey())
111+
.forEach(e -> sorted.put(e.getKey(), e.getValue()));
112+
tariffZoneRefs.setProperties(sorted);
113+
// Restore required field
114+
tariffZoneRefs.setRequired(List.of("tariffZoneRef"));
115+
}
116+
}
117+
118+
// Fix Quays_RelStructure: restore quayRefOrQuay items to empty schema
119+
Schema quaysRel = schemas.get("Quays_RelStructure");
120+
if (quaysRel != null && quaysRel.getProperties() != null) {
121+
Map<String, Schema> props = quaysRel.getProperties();
122+
Schema quayProp = props.get("quayRefOrQuay");
123+
if (quayProp != null && quayProp.getItems() != null) {
124+
quayProp.setItems(new Schema<>());
125+
}
126+
}
127+
128+
// Fix ParkingAreas_RelStructure: rename parkingAreaRefOrParkingArea_ back
129+
renameProperty(schemas, "ParkingAreas_RelStructure",
130+
"parkingAreaRefOrParkingArea_", "parkingAreaRefOrParkingArea");
131+
132+
// Fix StopPlacesInFrame_RelStructure: rename stopPlace_ back to stopPlace
133+
Schema stopPlacesInFrame = schemas.get("StopPlacesInFrame_RelStructure");
134+
if (stopPlacesInFrame != null && stopPlacesInFrame.getProperties() != null) {
135+
Map<String, Schema> spProps = stopPlacesInFrame.getProperties();
136+
if (spProps.containsKey("stopPlace_")) {
137+
spProps.remove("stopPlace_");
138+
Schema stopPlaceProp = new ArraySchema()
139+
.items(new Schema<>().$ref("#/components/schemas/StopPlace"));
140+
stopPlaceProp.xml(new io.swagger.v3.oas.models.media.XML().name("StopPlace"));
141+
spProps.put("stopPlace", stopPlaceProp);
142+
// Re-sort alphabetically
143+
Map<String, Schema> sorted = new LinkedHashMap<>();
144+
spProps.entrySet().stream()
145+
.sorted(Map.Entry.comparingByKey())
146+
.forEach(e -> sorted.put(e.getKey(), e.getValue()));
147+
stopPlacesInFrame.setProperties(sorted);
148+
stopPlacesInFrame.setRequired(List.of("stopPlace"));
149+
}
150+
}
151+
152+
// Fix StopPlaceRefs_RelStructure: restore items ref and required
153+
restoreJaxbElementArrayProp(schemas, "StopPlaceRefs_RelStructure",
154+
"stopPlaceRef", "StopPlaceRefStructure", "StopPlaceRef");
155+
156+
// Fix ParkingAreaRefs_RelStructure: restore items ref and required
157+
restoreJaxbElementArrayProp(schemas, "ParkingAreaRefs_RelStructure",
158+
"parkingAreaRef", "ParkingAreaRefStructure", "ParkingAreaRef");
159+
160+
// Restore TariffZoneRef schema (removed in new model, still referenced)
161+
if (!schemas.containsKey("TariffZoneRef")) {
162+
schemas.put("TariffZoneRef", schemas.getOrDefault("ZoneRefStructure", new Schema<>()));
163+
}
164+
};
165+
}
166+
167+
private static void restoreJaxbElementArrayProp(Map<String, Schema> schemas,
168+
String schemaName, String propName,
169+
String itemsRef, String xmlName) {
170+
Schema schema = schemas.get(schemaName);
171+
if (schema != null && schema.getProperties() != null) {
172+
Map<String, Schema> props = schema.getProperties();
173+
Schema prop = props.get(propName);
174+
if (prop != null) {
175+
prop.setItems(new Schema<>().$ref("#/components/schemas/" + itemsRef));
176+
prop.xml(new io.swagger.v3.oas.models.media.XML().name(xmlName));
177+
schema.setRequired(List.of(propName));
178+
}
179+
}
180+
}
181+
182+
private static void renameProperty(Map<String, Schema> schemas, String schemaName,
183+
String oldPropName, String newPropName) {
184+
Schema schema = schemas.get(schemaName);
185+
if (schema != null && schema.getProperties() != null) {
186+
Map<String, Schema> props = schema.getProperties();
187+
if (props.containsKey(oldPropName)) {
188+
Schema prop = props.remove(oldPropName);
189+
// Reset items to empty schema (unwrapped JAXBElements)
190+
if (prop.getItems() != null) {
191+
prop.setItems(new Schema<>());
192+
}
193+
props.put(newPropName, prop);
194+
// Re-sort alphabetically
195+
Map<String, Schema> sorted = new LinkedHashMap<>();
196+
props.entrySet().stream()
197+
.sorted(Map.Entry.comparingByKey())
198+
.forEach(e -> sorted.put(e.getKey(), e.getValue()));
199+
schema.setProperties(sorted);
200+
}
201+
}
202+
}
203+
85204
@Bean
86205
public ObjectMapperProvider springDocObjectMapperProvider() {
87206
return new ObjectMapperProvider(new SpringDocConfigProperties()) {

src/main/java/no/entur/mummu/config/WebConfig.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
import com.fasterxml.jackson.databind.SerializationFeature;
88
import com.fasterxml.jackson.databind.module.SimpleModule;
99
import no.entur.mummu.serializers.CustomSerializers;
10+
import no.entur.mummu.serializers.NetexJsonMixins;
11+
import org.rutebanken.netex.model.ParkingAreaRefs_RelStructure;
12+
import org.rutebanken.netex.model.ParkingAreas_RelStructure;
13+
import org.rutebanken.netex.model.Quays_RelStructure;
14+
import org.rutebanken.netex.model.StopPlaceRefs_RelStructure;
15+
import org.rutebanken.netex.model.TariffZoneRefs_RelStructure;
1016
import org.springframework.beans.factory.annotation.Autowired;
1117
import org.springframework.context.annotation.Configuration;
1218
import org.springframework.format.FormatterRegistry;
@@ -67,6 +73,11 @@ public ObjectMapper jsonObjectMapper() {
6773
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
6874
.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
6975
.modules(modules)
76+
.mixIn(Quays_RelStructure.class, NetexJsonMixins.QuaysRelStructureMixin.class)
77+
.mixIn(TariffZoneRefs_RelStructure.class, NetexJsonMixins.TariffZoneRefsRelStructureMixin.class)
78+
.mixIn(ParkingAreas_RelStructure.class, NetexJsonMixins.ParkingAreasRelStructureMixin.class)
79+
.mixIn(StopPlaceRefs_RelStructure.class, NetexJsonMixins.StopPlaceRefsRelStructureMixin.class)
80+
.mixIn(ParkingAreaRefs_RelStructure.class, NetexJsonMixins.ParkingAreaRefsRelStructureMixin.class)
7081
.build();
7182
}
7283

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package no.entur.mummu.serializers;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import com.fasterxml.jackson.databind.JsonSerializer;
5+
import com.fasterxml.jackson.databind.SerializerProvider;
6+
import jakarta.xml.bind.JAXBElement;
7+
8+
import java.io.IOException;
9+
import java.util.List;
10+
11+
public class JAXBElementUnwrappingSerializer extends JsonSerializer<List<JAXBElement<?>>> {
12+
13+
@Override
14+
public void serialize(List<JAXBElement<?>> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
15+
gen.writeStartArray();
16+
for (JAXBElement<?> element : value) {
17+
gen.writeObject(element.getValue());
18+
}
19+
gen.writeEndArray();
20+
}
21+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package no.entur.mummu.serializers;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
5+
import jakarta.xml.bind.JAXBElement;
6+
import org.rutebanken.netex.model.ParkingAreaRefStructure;
7+
import org.rutebanken.netex.model.StopPlaceRefStructure;
8+
import org.rutebanken.netex.model.ZoneRefStructure;
9+
10+
import java.util.List;
11+
12+
public class NetexJsonMixins {
13+
14+
public abstract static class QuaysRelStructureMixin {
15+
@JsonSerialize(using = JAXBElementUnwrappingSerializer.class)
16+
@JsonProperty("quayRefOrQuay")
17+
public abstract List<JAXBElement<?>> getQuayRefOrQuay();
18+
}
19+
20+
@SuppressWarnings("rawtypes")
21+
public abstract static class TariffZoneRefsRelStructureMixin {
22+
@JsonSerialize(using = JAXBElementUnwrappingSerializer.class)
23+
@JsonProperty("tariffZoneRef")
24+
public abstract List getTariffZoneRef_();
25+
}
26+
27+
public abstract static class ParkingAreasRelStructureMixin {
28+
@JsonSerialize(using = JAXBElementUnwrappingSerializer.class)
29+
@JsonProperty("parkingAreaRefOrParkingArea")
30+
public abstract List<JAXBElement<?>> getParkingAreaRefOrParkingArea_();
31+
}
32+
33+
public abstract static class StopPlaceRefsRelStructureMixin {
34+
@JsonSerialize(using = JAXBElementUnwrappingSerializer.class)
35+
@JsonProperty("stopPlaceRef")
36+
public abstract List<JAXBElement<? extends StopPlaceRefStructure>> getStopPlaceRef();
37+
}
38+
39+
public abstract static class ParkingAreaRefsRelStructureMixin {
40+
@JsonSerialize(using = JAXBElementUnwrappingSerializer.class)
41+
@JsonProperty("parkingAreaRef")
42+
public abstract List<JAXBElement<? extends ParkingAreaRefStructure>> getParkingAreaRef();
43+
}
44+
}

src/main/java/no/entur/mummu/services/NetexEntitiesService.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public List<ScheduledStopPoint> getScheduledStopPoints(
329329
public Collection<ScheduledStopPoint> getScheduledStopPointsForStopPlaceWithId(String id) {
330330
return netexEntitiesIndex.getPassengerStopAssignmentsByStopPointRefIndex().entries().stream().filter(entry -> {
331331
var passengerStopAssignment = entry.getValue();
332-
return passengerStopAssignment.getStopPlaceRef() != null && passengerStopAssignment.getStopPlaceRef().getRef().equals(id);
332+
return passengerStopAssignment.getStopPlaceRef() != null && passengerStopAssignment.getStopPlaceRef().getValue().getRef().equals(id);
333333
}).map(entry -> {
334334
var stopPointRef = entry.getKey();
335335
return netexEntitiesIndex.getScheduledStopPointIndex().getLatestVersion(stopPointRef);
@@ -347,10 +347,10 @@ public StopPlace getStopPlaceByScheduledStopPointId(String id) {
347347
.map(
348348
passengerStopAssignment ->
349349
netexEntitiesIndex.getStopPlaceIndex().getVersion(
350-
passengerStopAssignment.getStopPlaceRef().getRef(),
351-
passengerStopAssignment.getStopPlaceRef().getVersion()
350+
passengerStopAssignment.getStopPlaceRef().getValue().getRef(),
351+
passengerStopAssignment.getStopPlaceRef().getValue().getVersion()
352352
)
353353

354-
).findFirst().orElseThrow(NotFoundException::new);
354+
).map(StopPlace.class::cast).findFirst().orElseThrow(NotFoundException::new);
355355
}
356356
}

src/main/java/no/entur/mummu/services/NetexObjectFactory.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.rutebanken.netex.model.Quays_RelStructure;
1515
import org.rutebanken.netex.model.ScheduledStopPoint;
1616
import org.rutebanken.netex.model.ScheduledStopPointsInFrame_RelStructure;
17+
import org.rutebanken.netex.model.Site_VersionStructure;
1718
import org.rutebanken.netex.model.StopPlace;
1819
import org.rutebanken.netex.model.StopPlacesInFrame_RelStructure;
1920
import org.rutebanken.netex.model.TariffZone;
@@ -46,7 +47,10 @@ public JAXBElement<GroupsOfStopPlacesInFrame_RelStructure> createGroupsOfStopPla
4647
}
4748

4849
public JAXBElement<StopPlacesInFrame_RelStructure> createStopPlaces(List<StopPlace> stopPlaces) {
49-
var stopPlacesInFrame = createStopPlacesInFrame_RelStructure().withStopPlace(stopPlaces);
50+
Collection<JAXBElement<? extends Site_VersionStructure>> elements = stopPlaces.stream()
51+
.map(this::createStopPlace)
52+
.collect(Collectors.toList());
53+
var stopPlacesInFrame = createStopPlacesInFrame_RelStructure().withStopPlace_(elements);
5054
return new JAXBElement<>(_stopPlaces_QNAME, StopPlacesInFrame_RelStructure.class, stopPlacesInFrame);
5155
}
5256

@@ -85,7 +89,10 @@ public JAXBElement<ScheduledStopPointsInFrame_RelStructure> createScheduledStopP
8589
}
8690

8791
public JAXBElement<Quays_RelStructure> createQuays(Collection<Quay> quays) {
88-
var quaysRelStructure = createQuays_RelStructure().withQuayRefOrQuay(quays);
92+
Collection<JAXBElement<?>> elements = quays.stream()
93+
.map(this::createQuay)
94+
.collect(Collectors.toList());
95+
var quaysRelStructure = createQuays_RelStructure().withQuayRefOrQuay(elements);
8996
return new JAXBElement<>(_quays_QNAME, Quays_RelStructure.class, quaysRelStructure);
9097
}
9198
}

src/main/java/no/entur/mummu/util/StopPlaceByQuayIdsFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package no.entur.mummu.util;
22

3+
import jakarta.xml.bind.JAXBElement;
34
import org.rutebanken.netex.model.Quay;
45
import org.rutebanken.netex.model.StopPlace;
56

@@ -27,6 +28,6 @@ public boolean test(StopPlace stopPlace) {
2728

2829
return stopPlace.getQuays().getQuayRefOrQuay().stream()
2930
.filter(Objects::nonNull)
30-
.anyMatch(v -> quayIds.contains(((Quay) v).getId()));
31+
.anyMatch(v -> quayIds.contains(((Quay) ((JAXBElement<?>) v).getValue()).getId()));
3132
}
3233
}

src/main/java/no/entur/mummu/util/TransportModesFilter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ public TransportModesFilter(List<VehicleModeEnumeration> transportModes) {
1515

1616
@Override
1717
public boolean test(StopPlace stopPlace) {
18-
return transportModes == null || transportModes.contains(stopPlace.getTransportMode());
18+
if (transportModes == null) {
19+
return true;
20+
}
21+
if (stopPlace.getTransportMode() == null) {
22+
return false;
23+
}
24+
return transportModes.stream()
25+
.anyMatch(mode -> mode.value().equals(stopPlace.getTransportMode().value()));
1926
}
2027
}

src/main/resources/public/openapi.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)