All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.netex.loader.mapping.StopAndStationMapper Maven / Gradle / Ivy

package org.opentripplanner.netex.loader.mapping;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.opentripplanner.graph_builder.DataImportIssueStore;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.model.Station;
import org.opentripplanner.model.Stop;
import org.opentripplanner.model.FareZone;
import org.opentripplanner.model.impl.EntityById;
import org.opentripplanner.netex.loader.util.ReadOnlyHierarchicalVersionMapById;
import org.opentripplanner.netex.support.StopPlaceVersionAndValidityComparator;
import org.rutebanken.netex.model.Quay;
import org.rutebanken.netex.model.Quays_RelStructure;
import org.rutebanken.netex.model.StopPlace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * This maps a NeTEx StopPlace and its child quays to and OTP parent stop and child stops. NeTEx also contains
 * GroupsOfStopPlaces and these are also mapped to parent stops, because searching from a StopPlace and searching from
 * a GroupOfStopPlaces both corresponding to searching from all of its underlying quays. Model changes in OTP are
 * required if we want to preserve the original NeTEx hierarchy.
 * 

* A NeTEx StopPlace can contain both a version and a validity period. Since none of these are present in the OTP model * we have to choose which version should be mapped based on both of these parameters. *

* To ensure compatibility with older data sets, we also have to keep quays that are only present in older versions * of the StopPlace. */ class StopAndStationMapper { private static final Logger LOG = LoggerFactory.getLogger(StopAndStationMapper.class); private final ReadOnlyHierarchicalVersionMapById quayIndex; private final StationMapper stationMapper; private final StopMapper stopMapper; private final EntityById tariffZonesById; private final FeedScopedIdFactory idFactory; /** * Quay ids for all processed stop places */ private final Set quaysAlreadyProcessed = new HashSet<>(); final List resultStops = new ArrayList<>(); final List resultStations = new ArrayList<>(); final Multimap resultStationByMultiModalStationRfs = ArrayListMultimap.create(); StopAndStationMapper( FeedScopedIdFactory idFactory, ReadOnlyHierarchicalVersionMapById quayIndex, EntityById tariffZonesById, DataImportIssueStore issueStore ) { this.stationMapper = new StationMapper(idFactory); this.stopMapper = new StopMapper(idFactory, issueStore); this.quayIndex = quayIndex; this.tariffZonesById = tariffZonesById; this.idFactory = idFactory; } /** * @param stopPlaces all stop places including multiple versions of each. */ void mapParentAndChildStops(final Collection stopPlaces) { // Prioritize StopPlace versions. Highest priority first. // TODO OTP2 - This should pushed up into the ReadOnlyHierarchicalVersionMapById as part of // - Issue: Netex import resolve version for all entities , not just stops #2781 List stopPlaceAllVersions = sortStopPlacesByValidityAndVersionDesc(stopPlaces); Station station = mapStopPlaceAllVersionsToStation(stopPlaceAllVersions); List fareZones = mapTariffZones(stopPlaceAllVersions); // Loop through all versions of the StopPlace in order to collect all quays, even if they were deleted in // never versions of the StopPlace for (StopPlace stopPlace : stopPlaceAllVersions) { for (Quay quay : listOfQuays(stopPlace)) { addNewStopToParentIfNotPresent(quay, station, fareZones); } } } private Station mapStopPlaceAllVersionsToStation(List stopPlaceAllVersions) { // Map the highest priority StopPlace version to station StopPlace selectedStopPlace = first(stopPlaceAllVersions); Station station = stationMapper.map(selectedStopPlace); if (selectedStopPlace.getParentSiteRef() != null) { resultStationByMultiModalStationRfs.put( selectedStopPlace.getParentSiteRef().getRef(), station ); } resultStations.add(station); return station; } private List mapTariffZones(List stopPlaceAllVersions) { StopPlace selectedStopPlace = first(stopPlaceAllVersions); return selectedStopPlace.getTariffZones() != null ? selectedStopPlace .getTariffZones() .getTariffZoneRef() .stream() .map(t -> tariffZonesById.get(idFactory.createId(t.getRef()))) .filter(Objects::nonNull) .collect(Collectors.toList()) : Collections.emptyList(); } /** * Sort stop places on version with latest version first (descending order). */ private List sortStopPlacesByValidityAndVersionDesc(Collection stopPlaces) { return stopPlaces.stream() .sorted(new StopPlaceVersionAndValidityComparator()) .collect(toList()); } private void addNewStopToParentIfNotPresent( Quay quay, Station station, List fareZones ) { // TODO OTP2 - This assumtion is only valid because Norway have a // - national stop register, we should add all stops/quays // - for version resolution. // Continue if this is not newest version of quay if (!quayIndex.isNewerOrSameVersionComparedWithExistingValues(quay)) { return; } if (quaysAlreadyProcessed.contains(quay.getId())) { return; } Stop stop = stopMapper.mapQuayToStop(quay, station, fareZones); if (stop == null) return; station.addChildStop(stop); resultStops.add(stop); quaysAlreadyProcessed.add(quay.getId()); } /** * Return the list of quays for the given {@code stopPlace} or an empty list if * no quays exist. *

* We do not support quay references, all quays must be included as part of the * given stopPlace. */ private static List listOfQuays(StopPlace stopPlace) { Quays_RelStructure quays = stopPlace.getQuays(); if(quays == null) { LOG.warn("StopPlace {} has no quays.", stopPlace.getId()); return Collections.emptyList(); } List result = new ArrayList<>(); for (Object it : quays.getQuayRefOrQuay()) { if(it instanceof Quay) { result.add((Quay) it); } else { LOG.warn("StopPlace {} has unsupported quay reference: {}", stopPlace.getId(), it); } } return result; } private static StopPlace first(List stops) { return stops.get(0); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy