diff --git a/examples/gtfs_reader.rs b/examples/gtfs_reader.rs index 3e4f3c50f..a117f9e21 100644 --- a/examples/gtfs_reader.rs +++ b/examples/gtfs_reader.rs @@ -13,18 +13,23 @@ // along with this program. If not, see use serde_json::json; -use std::path::Path; -use transit_model::Result; +use std::collections::BTreeMap; +use transit_model::{ + gtfs, + objects::{Contributor, Dataset}, + Result, +}; fn run() -> Result<()> { - let configuration: transit_model::gtfs::Configuration<&Path> = - transit_model::gtfs::Configuration { - config_path: None, - prefix: None, - on_demand_transport: false, - on_demand_transport_comment: None, - }; - let objects = transit_model::gtfs::read_from_path(".", configuration)?; + let configuration: gtfs::Configuration = gtfs::Configuration { + contributor: Contributor::default(), + dataset: Dataset::default(), + feed_infos: BTreeMap::new(), + prefix_conf: None, + on_demand_transport: false, + on_demand_transport_comment: None, + }; + let objects = gtfs::read_from_path(".", configuration)?; let json_objs = json!(objects); println!("{:?}", json_objs.to_string()); Ok(()) diff --git a/gtfs2netexfr/src/main.rs b/gtfs2netexfr/src/main.rs index b3fce24ca..984907529 100644 --- a/gtfs2netexfr/src/main.rs +++ b/gtfs2netexfr/src/main.rs @@ -21,7 +21,7 @@ use slog::{slog_o, Drain}; use slog_async::OverflowStrategy; use std::path::PathBuf; use structopt::StructOpt; -use transit_model::Result; +use transit_model::{read_utils, Result}; #[derive(Debug, StructOpt)] #[structopt(name = "gtfs2netexfr", about = "Convert a GTFS to NeTEx France.")] @@ -96,9 +96,12 @@ fn init_logger() -> slog_scope::GlobalLoggerGuard { fn run(opt: Opt) -> Result<()> { info!("Launching gtfs2netexfr..."); + let (contributor, dataset, feed_infos) = read_utils::read_config(opt.config)?; let configuration = transit_model::gtfs::Configuration { - config_path: opt.config, - prefix: None, + contributor, + dataset, + feed_infos, + prefix_conf: None, on_demand_transport: opt.odt, on_demand_transport_comment: opt.odt_comment, }; diff --git a/gtfs2ntfs/src/main.rs b/gtfs2ntfs/src/main.rs index f10c7faaf..dea8799cc 100644 --- a/gtfs2ntfs/src/main.rs +++ b/gtfs2ntfs/src/main.rs @@ -21,7 +21,7 @@ use slog::{slog_o, Drain}; use slog_async::OverflowStrategy; use std::path::PathBuf; use structopt::StructOpt; -use transit_model::{transfers::generates_transfers, Result}; +use transit_model::{read_utils, transfers::generates_transfers, PrefixConfiguration, Result}; #[derive(Debug, StructOpt)] #[structopt(name = "gtfs2ntfs", about = "Convert a GTFS to an NTFS.")] @@ -99,9 +99,17 @@ fn init_logger() -> slog_scope::GlobalLoggerGuard { fn run(opt: Opt) -> Result<()> { info!("Launching gtfs2ntfs..."); + let (contributor, dataset, feed_infos) = read_utils::read_config(opt.config)?; + let mut prefix_conf = PrefixConfiguration::default(); + if let Some(data_prefix) = opt.prefix { + prefix_conf.set_data_prefix(data_prefix); + } + prefix_conf.set_dataset_id(&dataset.id); let configuration = transit_model::gtfs::Configuration { - config_path: opt.config, - prefix: opt.prefix, + contributor, + dataset, + feed_infos, + prefix_conf: Some(prefix_conf), on_demand_transport: opt.odt, on_demand_transport_comment: opt.odt_comment, }; diff --git a/src/gtfs/mod.rs b/src/gtfs/mod.rs index e72e16e20..92318ac48 100644 --- a/src/gtfs/mod.rs +++ b/src/gtfs/mod.rs @@ -21,8 +21,7 @@ use crate::{ calendars::{manage_calendars, write_calendar_dates}, gtfs::read::EquipmentList, model::{Collections, Model}, - objects, - objects::{Availability, StopPoint, StopType, Time}, + objects::{self, Availability, Contributor, Dataset, StopPoint, StopType, Time}, read_utils, utils::*, validity_period, AddPrefix, PrefixConfiguration, Result, @@ -30,8 +29,7 @@ use crate::{ use derivative::Derivative; use log::info; use serde::{Deserialize, Serialize}; -use std::fmt; -use std::path::Path; +use std::{collections::BTreeMap, fmt, path::Path}; use typed_index_collection::{CollectionWithId, Idx}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] @@ -257,33 +255,42 @@ struct Shape { } ///parameters consolidation -#[derive(Clone)] -pub struct Configuration> { - /// path to configuration file - pub config_path: Option

, +pub struct Configuration { + /// The Contributor providing the Dataset + pub contributor: Contributor, + /// Describe the Dataset being parsed + pub dataset: Dataset, + /// Additional key-values for the 'feed_infos.txt' + pub feed_infos: BTreeMap, /// used to prefix objects - pub prefix: Option, + pub prefix_conf: Option, /// stop time precision management pub on_demand_transport: bool, /// on demand transport comment template pub on_demand_transport_comment: Option, } -fn read>(file_handler: &mut H, configuration: Configuration

) -> Result +fn read(file_handler: &mut H, configuration: Configuration) -> Result where for<'a> &'a mut H: read_utils::FileHandler, { let mut collections = Collections::default(); let mut equipments = EquipmentList::default(); - manage_calendars(file_handler, &mut collections)?; + let Configuration { + contributor, + mut dataset, + feed_infos, + prefix_conf, + on_demand_transport, + on_demand_transport_comment, + } = configuration; - let (contributor, mut dataset, feed_infos) = - read_utils::read_config(configuration.config_path)?; + manage_calendars(file_handler, &mut collections)?; validity_period::compute_dataset_validity_period(&mut dataset, &collections.calendars)?; - collections.contributors = CollectionWithId::new(vec![contributor])?; - collections.datasets = CollectionWithId::new(vec![dataset])?; + collections.contributors = CollectionWithId::from(contributor); + collections.datasets = CollectionWithId::from(dataset); collections.feed_infos = feed_infos; let (networks, companies) = read::read_agency(file_handler)?; @@ -303,17 +310,15 @@ where read::manage_stop_times( &mut collections, file_handler, - configuration.on_demand_transport, - configuration.on_demand_transport_comment, + on_demand_transport, + on_demand_transport_comment, )?; read::manage_frequencies(&mut collections, file_handler)?; read::manage_pathways(&mut collections, file_handler)?; collections.levels = read_utils::read_opt_collection(file_handler, "levels.txt")?; //add prefixes - if let Some(prefix) = configuration.prefix { - let mut prefix_conf = PrefixConfiguration::default(); - prefix_conf.set_data_prefix(prefix); + if let Some(prefix_conf) = prefix_conf { collections.prefix(&prefix_conf); } @@ -331,10 +336,7 @@ where /// The `prefix` argument is a string that will be prepended to every /// identifiers, allowing to namespace the dataset. By default, no /// prefix will be added to the identifiers. -pub fn read_from_path>( - p: P, - configuration: Configuration>, -) -> Result { +pub fn read_from_path>(p: P, configuration: Configuration) -> Result { let mut file_handle = read_utils::PathFileHandler::new(p.as_ref().to_path_buf()); read(&mut file_handle, configuration) } @@ -349,10 +351,7 @@ pub fn read_from_path>( /// The `prefix` argument is a string that will be prepended to every /// identifiers, allowing to namespace the dataset. By default, no /// prefix will be added to the identifiers. -pub fn read_from_zip>( - path: P, - configuration: Configuration>, -) -> Result { +pub fn read_from_zip>(path: P, configuration: Configuration) -> Result { let mut file_handler = read_utils::ZipHandler::new(path)?; read(&mut file_handler, configuration) } diff --git a/tests/gtfs2ntfs.rs b/tests/gtfs2ntfs.rs index 03be34730..2152cf201 100644 --- a/tests/gtfs2ntfs.rs +++ b/tests/gtfs2ntfs.rs @@ -12,24 +12,32 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see -use std::path::Path; -use transit_model::gtfs::Configuration; -use transit_model::test_utils::*; - -static DEFAULT_CONFIGURATION: Configuration<&Path> = Configuration { - config_path: None, - prefix: None, - on_demand_transport: false, - on_demand_transport_comment: None, +use std::collections::BTreeMap; +use transit_model::{ + gtfs, ntfs, + objects::{Contributor, Dataset}, + read_utils::read_config, + test_utils::*, + PrefixConfiguration, }; +fn default_configuration() -> gtfs::Configuration { + gtfs::Configuration { + contributor: Contributor::default(), + dataset: Dataset::default(), + feed_infos: BTreeMap::new(), + prefix_conf: None, + on_demand_transport: false, + on_demand_transport_comment: None, + } +} + #[test] fn test_frequencies_generate_trips() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/frequencies/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec![ @@ -48,9 +56,8 @@ fn test_frequencies_generate_trips() { fn test_minimal_gtfs() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/minimal/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected(&path, None, "./tests/fixtures/gtfs2ntfs/minimal/output"); }); } @@ -59,15 +66,21 @@ fn test_minimal_gtfs() { fn test_minimal_gtfs_with_feed_infos() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/minimal_with_config/input"; - let configuration = transit_model::gtfs::Configuration { - config_path: Some("./tests/fixtures/gtfs2ntfs/minimal_with_config/config.json"), - prefix: None, + let (contributor, dataset, feed_infos) = read_config(Some( + "./tests/fixtures/gtfs2ntfs/minimal_with_config/config.json", + )) + .unwrap(); + let configuration = gtfs::Configuration { + contributor, + dataset, + feed_infos, + prefix_conf: None, on_demand_transport: false, on_demand_transport_comment: None, }; - let model = transit_model::gtfs::read_from_path(input_dir, configuration).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, configuration).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec![ @@ -85,9 +98,8 @@ fn test_minimal_gtfs_with_feed_infos() { fn test_gtfs_physical_modes() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/physical_modes/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec![ @@ -105,9 +117,8 @@ fn test_gtfs_physical_modes() { fn test_gtfs_remove_vjs_with_no_traffic() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/no_traffic/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec![ @@ -127,9 +138,8 @@ fn test_gtfs_remove_vjs_with_no_traffic() { fn test_minimal_ziped_gtfs() { test_in_tmp_dir(|path| { let input = "./tests/fixtures/ziped_gtfs/gtfs.zip"; - let model = - transit_model::gtfs::read_from_zip(input, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_zip(input, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected(&path, None, "./tests/fixtures/gtfs2ntfs/minimal/output"); }); } @@ -138,9 +148,8 @@ fn test_minimal_ziped_gtfs() { fn test_minimal_ziped_sub_dir_gtfs() { test_in_tmp_dir(|path| { let input = "./tests/fixtures/ziped_gtfs/sub_dir_gtfs.zip"; - let model = - transit_model::gtfs::read_from_zip(input, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_zip(input, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected(&path, None, "./tests/fixtures/gtfs2ntfs/minimal/output"); }); } @@ -149,9 +158,8 @@ fn test_minimal_ziped_sub_dir_gtfs() { fn test_minimal_ziped_sub_dir_gtfs_with_hidden_files() { test_in_tmp_dir(|path| { let input = "./tests/fixtures/ziped_gtfs/sub_dir_gtfs_with_hidden_files.zip"; - let model = - transit_model::gtfs::read_from_zip(input, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_zip(input, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected(&path, None, "./tests/fixtures/gtfs2ntfs/minimal/output"); }); } @@ -160,9 +168,8 @@ fn test_minimal_ziped_sub_dir_gtfs_with_hidden_files() { fn test_gtfs_with_platforms() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/platforms/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec!["stops.txt"]), @@ -175,9 +182,8 @@ fn test_gtfs_with_platforms() { fn test_gtfs_with_levels() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/levels_and_pathways/input"; - let model = - transit_model::gtfs::read_from_path(input_dir, DEFAULT_CONFIGURATION.clone()).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let model = gtfs::read_from_path(input_dir, default_configuration()).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec!["stops.txt", "pathways.txt", "levels.txt"]), @@ -190,17 +196,20 @@ fn test_gtfs_with_levels() { fn test_minimal_gtfs_with_odt_comment() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/minimal/input"; - let configuration: transit_model::gtfs::Configuration<&Path> = - transit_model::gtfs::Configuration { - config_path: None, - prefix: Some("test".to_string()), - on_demand_transport: false, - on_demand_transport_comment: Some( - "Service à réservation {agency_name} {agency_phone}".to_string(), - ), - }; - let model = transit_model::gtfs::read_from_path(input_dir, configuration).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let mut prefix_conf = PrefixConfiguration::default(); + prefix_conf.set_data_prefix("test"); + let configuration = gtfs::Configuration { + contributor: Contributor::default(), + dataset: Dataset::default(), + feed_infos: BTreeMap::new(), + prefix_conf: Some(prefix_conf), + on_demand_transport: false, + on_demand_transport_comment: Some( + "Service à réservation {agency_name} {agency_phone}".to_string(), + ), + }; + let model = gtfs::read_from_path(input_dir, configuration).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec!["comment_links.txt", "comments.txt", "stop_times.txt"]), @@ -213,18 +222,21 @@ fn test_minimal_gtfs_with_odt_comment() { fn test_minimal_gtfs_frequencies_with_odt_comment() { test_in_tmp_dir(|path| { let input_dir = "./tests/fixtures/gtfs2ntfs/frequencies/input"; - let configuration: transit_model::gtfs::Configuration<&Path> = - transit_model::gtfs::Configuration { - config_path: None, - prefix: Some("test".to_string()), - on_demand_transport: false, - on_demand_transport_comment: Some( - "Service à réservation {agency_name} {agency_phone}".to_string(), - ), - }; - - let model = transit_model::gtfs::read_from_path(input_dir, configuration).unwrap(); - transit_model::ntfs::write(&model, path, get_test_datetime()).unwrap(); + let mut prefix_conf = PrefixConfiguration::default(); + prefix_conf.set_data_prefix("test"); + let configuration = gtfs::Configuration { + contributor: Contributor::default(), + dataset: Dataset::default(), + feed_infos: BTreeMap::new(), + prefix_conf: Some(prefix_conf), + on_demand_transport: false, + on_demand_transport_comment: Some( + "Service à réservation {agency_name} {agency_phone}".to_string(), + ), + }; + + let model = gtfs::read_from_path(input_dir, configuration).unwrap(); + ntfs::write(&model, path, get_test_datetime()).unwrap(); compare_output_dir_with_expected( &path, Some(vec!["comment_links.txt", "comments.txt", "stop_times.txt"]), diff --git a/tests/write_netex_france.rs b/tests/write_netex_france.rs index 231e43117..35d341ec7 100644 --- a/tests/write_netex_france.rs +++ b/tests/write_netex_france.rs @@ -12,11 +12,16 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see -use std::fs; -use std::path::Path; +use std::{collections::BTreeMap, fs}; #[cfg(feature = "xmllint")] use std::{ffi::OsStr, process::Command}; -use transit_model::{self, model::Model, netex_france, test_utils::*}; +use transit_model::{ + gtfs, + model::Model, + netex_france, ntfs, + objects::{Contributor, Dataset}, + test_utils::*, +}; fn test_write_netex_france(model: Model) { test_in_tmp_dir(|output_dir| { @@ -52,31 +57,30 @@ fn test_write_netex_france(model: Model) { #[test] fn test_write_netex_france_from_ntfs() { - let model = transit_model::ntfs::read("tests/fixtures/netex_france/input_ntfs").unwrap(); + let model = ntfs::read("tests/fixtures/netex_france/input_ntfs").unwrap(); test_write_netex_france(model); } #[test] fn test_write_netex_france_from_gtfs() { - let configuration: transit_model::gtfs::Configuration<&Path> = - transit_model::gtfs::Configuration { - config_path: None, - prefix: None, - on_demand_transport: false, - on_demand_transport_comment: None, - }; + let configuration = gtfs::Configuration { + contributor: Contributor::default(), + dataset: Dataset::default(), + feed_infos: BTreeMap::new(), + prefix_conf: None, + on_demand_transport: false, + on_demand_transport_comment: None, + }; - let model = transit_model::gtfs::read_from_path( - "tests/fixtures/netex_france/input_gtfs", - configuration, - ) - .unwrap(); + let model = + gtfs::read_from_path("tests/fixtures/netex_france/input_gtfs", configuration).unwrap(); test_write_netex_france(model); } #[test] #[cfg(feature = "xmllint")] fn validate_xml_schemas() { + use std::path::Path; fn check_xml_in_folder

(path: P) where P: AsRef,