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

org.opentripplanner.netex.loader.NetexBundle Maven / Gradle / Ivy

package org.opentripplanner.netex.loader;

import org.opentripplanner.datastore.CompositeDataSource;
import org.opentripplanner.datastore.DataSource;
import org.opentripplanner.graph_builder.DataImportIssueStore;
import org.opentripplanner.model.impl.OtpTransitServiceBuilder;
import org.opentripplanner.netex.NetexModule;
import org.opentripplanner.netex.loader.mapping.NetexMapper;
import org.opentripplanner.netex.loader.parser.NetexDocumentParser;
import org.opentripplanner.routing.trippattern.Deduplicator;
import org.opentripplanner.standalone.config.NetexConfig;
import org.rutebanken.netex.model.PublicationDeliveryStructure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBException;
import java.io.Closeable;
import java.io.IOException;
import java.util.Deque;
import java.util.LinkedList;

import static java.util.Collections.singletonList;

/**
 * Loads/reads a NeTEx bundle of a data source(zip file/directory/cloud storage) and maps it into
 * the OTP internal transit model.
 * 

* The NeTEx loader will use a file naming convention to load files in a particular order and * keeping an index of entities to enable linking. The convention is documented here *{@link NetexConfig#sharedFilePattern} and here * {@link NetexDataSourceHierarchy}. *

* This class is also responsible for logging progress and exception handling. */ public class NetexBundle implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(NetexModule.class); /** stack of NeTEx elements needed to link the input to existing data */ private Deque netexIndex = new LinkedList<>(); private final CompositeDataSource source; private final NetexDataSourceHierarchy hierarchy; /** maps the NeTEx XML document to OTP transit model. */ private NetexMapper otpMapper; private NetexXmlParser xmlParser; private final String netexFeedId; public NetexBundle( String netexFeedId, CompositeDataSource source, NetexDataSourceHierarchy hierarchy ) { this.netexFeedId = netexFeedId; this.source = source; this.hierarchy = hierarchy; } /** load the bundle, map it to the OTP transit model and return */ public OtpTransitServiceBuilder loadBundle( Deduplicator deduplicator, DataImportIssueStore issueStore ) { LOG.info("Reading {}", hierarchy.description()); // Store result in a mutable OTP Transit Model OtpTransitServiceBuilder transitBuilder = new OtpTransitServiceBuilder(); // init parser and mapper xmlParser = new NetexXmlParser(); otpMapper = new NetexMapper(transitBuilder, netexFeedId, deduplicator, issueStore); // Load data loadZipFileEntries(); return transitBuilder; } public void checkInputs() { if (!source.exists()) { throw new RuntimeException("NeTEx " + source.path() + " does not exist."); } } /* private methods */ /** Load all files entries in the bundle */ private void loadZipFileEntries() { // Add a global(this zip file) shared NeTEX DAO netexIndex.addFirst(new NetexImportDataIndex()); // Load global shared files loadFilesThenMapToOtpTransitModel("shared file", hierarchy.sharedEntries()); for (GroupEntries group : hierarchy.groups()) { LOG.info("reading group {}", group.name()); newNetexImportDataScope(() -> { // Load shared group files loadFilesThenMapToOtpTransitModel( "shared group file", group.sharedEntries() ); for (DataSource entry : group.independentEntries()) { newNetexImportDataScope(() -> { // Load each independent file in group loadFilesThenMapToOtpTransitModel("group file", singletonList(entry)); }); } }); } } /** * make a new index and pushes it on the index stack, before executing the task and * at the end pop of the index. */ private void newNetexImportDataScope(Runnable task) { netexIndex.addFirst(new NetexImportDataIndex(index())); task.run(); netexIndex.removeFirst(); } /** * Load a set of files and map the entries to OTP Transit model after the loading is * complete. It is important to do this in 2 steps to be able to link references. * An attempt to map each entry, when read, would lead to missing references, since * the order entries are read is not enforced in any way. */ private void loadFilesThenMapToOtpTransitModel(String fileDescription, Iterable entries) { for (DataSource entry : entries) { // Load entry and store it in the index loadSingeFileEntry(fileDescription, entry); } // map current NeTEx objects into the OTP Transit Model otpMapper.mapNetexToOtp(index().readOnlyView()); } private NetexImportDataIndex index() { return netexIndex.peekFirst(); } /** Load a single entry and store it in the index for later */ private void loadSingeFileEntry(String fileDescription, DataSource entry) { try { LOG.info("reading entity {}: {}", fileDescription, entry.name()); PublicationDeliveryStructure doc = xmlParser.parseXmlDoc(entry.asInputStream()); NetexDocumentParser.parseAndPopulateIndex(index(), doc); } catch (JAXBException e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void close() throws IOException { source.close(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy