From 3e7f559fe6a1b9d18ca45befa2b2666a2879addc Mon Sep 17 00:00:00 2001 From: Yuji Mise Date: Thu, 16 Jan 2025 18:04:49 +0900 Subject: [PATCH] feat(engine): enhance plateau processor with city code extraction and metadata handling --- engine/Cargo.lock | 1 + engine/Cargo.toml | 2 +- .../action-plateau-processor/src/lib.rs | 1 + .../action-plateau-processor/src/plateau4.rs | 1 + .../src/plateau4/city_code_extractor.rs | 155 ++++++++++++ .../src/plateau4/errors.rs | 4 + .../src/plateau4/mapping.rs | 5 +- .../action-plateau-processor/src/types.rs | 1 + .../src/types/dictionary.rs | 76 ++++++ .../src/feature/file_path_extractor.rs | 10 +- .../src/feature/reader/citygml.rs | 18 +- engine/runtime/common/src/uri.rs | 5 + .../plateau/example_feature_transformer.rs | 2 +- .../plateau4/01-bldg/workflow.yml | 11 +- .../02-tran-rwy-trk-squr-wwy/workflow.yml | 221 ++++++++++++++++++ .../plateau4/04-luse-lsld/workflow.yml | 7 +- .../plateau4/06-area-urf/workflow.yml | 9 +- 17 files changed, 506 insertions(+), 23 deletions(-) create mode 100644 engine/runtime/action-plateau-processor/src/plateau4/city_code_extractor.rs create mode 100644 engine/runtime/action-plateau-processor/src/types.rs create mode 100644 engine/runtime/action-plateau-processor/src/types/dictionary.rs create mode 100644 engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/02-tran-rwy-trk-squr-wwy/workflow.yml diff --git a/engine/Cargo.lock b/engine/Cargo.lock index db746ab96..a9c1d63f1 100644 --- a/engine/Cargo.lock +++ b/engine/Cargo.lock @@ -5321,6 +5321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" dependencies = [ "memchr", + "serde", ] [[package]] diff --git a/engine/Cargo.toml b/engine/Cargo.toml index ce25c052a..f117ae0d1 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -129,7 +129,7 @@ parking_lot = "0.12.3" petgraph = "0.6.5" pretty_assertions = "1.4.1" prost = "0.13.4" -quick-xml = "0.37.2" +quick-xml = { version = "0.37.2", features = ["serialize"] } rand = "0.8.5" rayon = "1.10.0" regex = "1.11.1" diff --git a/engine/runtime/action-plateau-processor/src/lib.rs b/engine/runtime/action-plateau-processor/src/lib.rs index f703d437b..b7a61846e 100644 --- a/engine/runtime/action-plateau-processor/src/lib.rs +++ b/engine/runtime/action-plateau-processor/src/lib.rs @@ -1,3 +1,4 @@ pub mod mapping; pub mod plateau3; pub mod plateau4; +pub(crate) mod types; diff --git a/engine/runtime/action-plateau-processor/src/plateau4.rs b/engine/runtime/action-plateau-processor/src/plateau4.rs index ac75ecef0..4992814fa 100644 --- a/engine/runtime/action-plateau-processor/src/plateau4.rs +++ b/engine/runtime/action-plateau-processor/src/plateau4.rs @@ -1,4 +1,5 @@ pub(crate) mod attribute_flattener; +pub(crate) mod city_code_extractor; pub(crate) mod errors; pub(crate) mod mapping; pub(crate) mod max_lod_extractor; diff --git a/engine/runtime/action-plateau-processor/src/plateau4/city_code_extractor.rs b/engine/runtime/action-plateau-processor/src/plateau4/city_code_extractor.rs new file mode 100644 index 000000000..b0bc52a2f --- /dev/null +++ b/engine/runtime/action-plateau-processor/src/plateau4/city_code_extractor.rs @@ -0,0 +1,155 @@ +use crate::types::dictionary::Dictionary; + +use super::errors::PlateauProcessorError; +use reearth_flow_common::uri::Uri; +use reearth_flow_runtime::{ + channels::ProcessorChannelForwarder, + errors::BoxedError, + event::EventHub, + executor_operation::{ExecutorContext, NodeContext}, + node::{Port, Processor, ProcessorFactory, DEFAULT_PORT}, +}; +use reearth_flow_types::{Attribute, AttributeValue}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::{collections::HashMap, str::FromStr}; + +#[derive(Debug, Clone, Default)] +pub struct CityCodeExtractorFactory; + +impl ProcessorFactory for CityCodeExtractorFactory { + fn name(&self) -> &str { + "PLATEAU4.CityCodeExtractor" + } + + fn description(&self) -> &str { + "Extracts Codelist" + } + + fn parameter_schema(&self) -> Option { + Some(schemars::schema_for!(CityCodeExtractorParam)) + } + + fn categories(&self) -> &[&'static str] { + &["PLATEAU"] + } + + fn get_input_ports(&self) -> Vec { + vec![DEFAULT_PORT.clone()] + } + + fn get_output_ports(&self) -> Vec { + vec![DEFAULT_PORT.clone()] + } + + fn build( + &self, + _ctx: NodeContext, + _event_hub: EventHub, + _action: String, + with: Option>, + ) -> Result, BoxedError> { + let params: CityCodeExtractorParam = if let Some(with) = with { + let value: Value = serde_json::to_value(with).map_err(|e| { + PlateauProcessorError::CityCodeExtractorFactory(format!( + "Failed to serialize `with` parameter: {}", + e + )) + })?; + serde_json::from_value(value).map_err(|e| { + PlateauProcessorError::CityCodeExtractorFactory(format!( + "Failed to deserialize `with` parameter: {}", + e + )) + })? + } else { + return Err(PlateauProcessorError::CityCodeExtractorFactory( + "Missing required parameter `with`".to_string(), + ) + .into()); + }; + let process = CityCodeExtractor { + city_code_attribute: params.city_code_attribute, + codelists_path_attribute: params.codelists_path_attribute, + }; + Ok(Box::new(process)) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub(crate) struct CityCodeExtractorParam { + city_code_attribute: Attribute, + codelists_path_attribute: Attribute, +} + +#[derive(Debug, Clone)] +pub(crate) struct CityCodeExtractor { + city_code_attribute: Attribute, + codelists_path_attribute: Attribute, +} + +impl Processor for CityCodeExtractor { + fn process( + &mut self, + ctx: ExecutorContext, + fw: &mut dyn ProcessorChannelForwarder, + ) -> Result<(), BoxedError> { + let feature = &ctx.feature; + let AttributeValue::String(city_code) = feature + .attributes + .get(&self.city_code_attribute) + .ok_or(PlateauProcessorError::CityCodeExtractor( + "cityCode attribute empty".to_string(), + )) + .cloned()? + else { + return Err(PlateauProcessorError::CityCodeExtractor( + "cityCode attribute error".to_string(), + ) + .into()); + }; + let AttributeValue::String(codelists_path) = feature + .attributes + .get(&self.codelists_path_attribute) + .ok_or(PlateauProcessorError::CityCodeExtractor( + "codelists path attribute empty".to_string(), + )) + .cloned()? + else { + return Err(PlateauProcessorError::CityCodeExtractor( + "codelists path attribute error".to_string(), + ) + .into()); + }; + let codelists_path = Uri::from_str(&codelists_path)?; + let authorities_path = codelists_path.join("Common_localPublicAuthorities.xml")?; + let storage = ctx.storage_resolver.resolve(&authorities_path)?; + let bytes = storage.get_sync(&authorities_path.as_path())?; + let dic: Dictionary = quick_xml::de::from_str(&String::from_utf8(bytes.to_vec())?)?; + let city_name = dic + .entries + .iter() + .find(|entry| entry.definition.name.value == city_code) + .map(|entry| entry.definition.description.clone()); + let mut feature = feature.clone(); + if let Some(city_name) = city_name { + feature.insert("cityName", AttributeValue::String(city_name.value)); + } + fw.send(ctx.new_with_feature_and_port(feature, DEFAULT_PORT.clone())); + Ok(()) + } + + fn finish( + &self, + _ctx: NodeContext, + _fw: &mut dyn ProcessorChannelForwarder, + ) -> Result<(), BoxedError> { + Ok(()) + } + + fn name(&self) -> &str { + "CityCodeExtractor" + } +} diff --git a/engine/runtime/action-plateau-processor/src/plateau4/errors.rs b/engine/runtime/action-plateau-processor/src/plateau4/errors.rs index eb23b6eff..25600ca31 100644 --- a/engine/runtime/action-plateau-processor/src/plateau4/errors.rs +++ b/engine/runtime/action-plateau-processor/src/plateau4/errors.rs @@ -13,6 +13,10 @@ pub(super) enum PlateauProcessorError { MaxLodExtractor(String), #[error("AttributeFlattener error: {0}")] AttributeFlattener(String), + #[error("CityCode Extractor Factory error: {0}")] + CityCodeExtractorFactory(String), + #[error("CityCode Extractor error: {0}")] + CityCodeExtractor(String), } pub(super) type Result = std::result::Result; diff --git a/engine/runtime/action-plateau-processor/src/plateau4/mapping.rs b/engine/runtime/action-plateau-processor/src/plateau4/mapping.rs index 632cfd9e9..c7cecbbf1 100644 --- a/engine/runtime/action-plateau-processor/src/plateau4/mapping.rs +++ b/engine/runtime/action-plateau-processor/src/plateau4/mapping.rs @@ -4,8 +4,8 @@ use once_cell::sync::Lazy; use reearth_flow_runtime::node::{NodeKind, ProcessorFactory}; use super::{ - attribute_flattener::AttributeFlattenerFactory, max_lod_extractor::MaxLodExtractorFactory, - udx_folder_extractor::UDXFolderExtractorFactory, + attribute_flattener::AttributeFlattenerFactory, city_code_extractor::CityCodeExtractorFactory, + max_lod_extractor::MaxLodExtractorFactory, udx_folder_extractor::UDXFolderExtractorFactory, }; pub(crate) static ACTION_FACTORY_MAPPINGS: Lazy> = Lazy::new(|| { @@ -13,6 +13,7 @@ pub(crate) static ACTION_FACTORY_MAPPINGS: Lazy> = Laz Box::::default(), Box::::default(), Box::::default(), + Box::::default(), ]; factories .into_iter() diff --git a/engine/runtime/action-plateau-processor/src/types.rs b/engine/runtime/action-plateau-processor/src/types.rs new file mode 100644 index 000000000..3a264b40e --- /dev/null +++ b/engine/runtime/action-plateau-processor/src/types.rs @@ -0,0 +1 @@ +pub(crate) mod dictionary; diff --git a/engine/runtime/action-plateau-processor/src/types/dictionary.rs b/engine/runtime/action-plateau-processor/src/types/dictionary.rs new file mode 100644 index 000000000..d4a064876 --- /dev/null +++ b/engine/runtime/action-plateau-processor/src/types/dictionary.rs @@ -0,0 +1,76 @@ +use serde::Deserialize; + +#[derive(Deserialize, Debug, PartialEq, Default)] +#[serde(rename = "Dictionary")] +pub(crate) struct Dictionary { + pub(crate) name: Name, + #[serde(rename = "dictionaryEntry")] + pub(crate) entries: Vec, +} + +#[derive(Deserialize, Debug, PartialEq, Default)] +#[serde(rename = "dictionaryEntry")] +pub(crate) struct DictionaryEntry { + #[serde(rename = "Definition")] + pub(crate) definition: Definition, +} + +#[derive(Deserialize, Debug, PartialEq, Default, Clone)] +#[serde(default)] +pub(crate) struct Definition { + #[serde(rename = "@id")] + pub(crate) id: String, + pub(crate) description: Description, + pub(crate) name: Name, +} + +#[derive(Deserialize, Debug, PartialEq, Default, Clone)] +#[serde(rename = "description")] +pub(crate) struct Description { + #[serde(rename = "$text")] + pub(crate) value: String, +} + +#[derive(Deserialize, Debug, PartialEq, Default, Clone)] +#[serde(rename = "name")] +pub(crate) struct Name { + #[serde(rename = "$text")] + pub(crate) value: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_XML: &str = r#" + + + Common_localPublicAuthoritiesType + + + 北海道 + 01 + + + + + 北海道札幌市 + 01100 + + + + "#; + + #[test] + fn test_deserialize_dictionary_entry() { + let dic: Dictionary = quick_xml::de::from_str(TEST_XML).unwrap(); + assert_eq!(dic.name.value, "Common_localPublicAuthoritiesType"); + assert_eq!(dic.entries.len(), 2); + assert_eq!(dic.entries[0].definition.id, "id1"); + assert_eq!(dic.entries[0].definition.description.value, "北海道"); + assert_eq!(dic.entries[0].definition.name.value, "01"); + assert_eq!(dic.entries[1].definition.id, "id2"); + assert_eq!(dic.entries[1].definition.description.value, "北海道札幌市"); + assert_eq!(dic.entries[1].definition.name.value, "01100"); + } +} diff --git a/engine/runtime/action-processor/src/feature/file_path_extractor.rs b/engine/runtime/action-processor/src/feature/file_path_extractor.rs index c8645afa4..01a8bfebe 100644 --- a/engine/runtime/action-processor/src/feature/file_path_extractor.rs +++ b/engine/runtime/action-processor/src/feature/file_path_extractor.rs @@ -126,6 +126,7 @@ impl Processor for FeatureFilePathExtractor { fw: &mut dyn ProcessorChannelForwarder, ) -> Result<(), BoxedError> { let feature = &ctx.feature; + let base_attributes = feature.attributes.clone(); let expr_engine = Arc::clone(&ctx.expr_engine); let scope = feature.new_scope(expr_engine, &self.with); let source_dataset = scope @@ -184,7 +185,14 @@ impl Processor for FeatureFilePathExtractor { } else { extract_zip(bytes, root_output_path, root_output_storage)? }; - for feature in features { + for mut feature in features { + feature.extend( + base_attributes + .iter() + .filter(|(k, _)| !feature.contains_key(k)) + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(), + ); fw.send(ctx.new_with_feature_and_port(feature, DEFAULT_PORT.clone())); } } else if source_dataset.is_dir() { diff --git a/engine/runtime/action-processor/src/feature/reader/citygml.rs b/engine/runtime/action-processor/src/feature/reader/citygml.rs index 366b0b838..7660d4f1b 100644 --- a/engine/runtime/action-processor/src/feature/reader/citygml.rs +++ b/engine/runtime/action-processor/src/feature/reader/citygml.rs @@ -157,6 +157,12 @@ fn parse_tree_reader( let attributes = entity.root.to_attribute_json(); let gml_id = entity.root.id(); let name = entity.root.typename(); + let lod = LodMask::find_lods_by_citygml_value(&entity.root); + let metadata = Metadata { + feature_id: gml_id.map(|id| id.to_string()), + feature_type: name.map(|name| name.to_string()), + lod: Some(lod), + }; let mut attributes = HashMap::::from([ (Attribute::new("cityGmlAttributes"), attributes.into()), ( @@ -175,13 +181,13 @@ fn parse_tree_reader( AttributeValue::String(format!("root_{}", to_hash(base_url.as_str()))), ), ]); + if let Some(max_lod) = lod.highest_lod() { + attributes.insert( + Attribute::new("maxLod"), + AttributeValue::String(max_lod.to_string()), + ); + } attributes.extend(base_attributes.clone()); - let lod = LodMask::find_lods_by_citygml_value(&entity.root); - let metadata = Metadata { - feature_id: gml_id.map(|id| id.to_string()), - feature_type: name.map(|name| name.to_string()), - lod: Some(lod), - }; let entities = if flatten { FlattenTreeTransform::transform(entity) } else { diff --git a/engine/runtime/common/src/uri.rs b/engine/runtime/common/src/uri.rs index 89d7096b0..73396bc02 100644 --- a/engine/runtime/common/src/uri.rs +++ b/engine/runtime/common/src/uri.rs @@ -537,6 +537,11 @@ mod tests { Uri::for_test("file:///foo/hoge/").join("../bar").unwrap(), "file:///foo/bar" ); + assert_eq!( + Uri::for_test("file:///foo/hoge/fuga/").join("..").unwrap().join("..").unwrap(), + "file:///foo" + ); + assert_eq!( Uri::for_test("ram://foo").join("bar").unwrap(), "ram://foo/bar" diff --git a/engine/runtime/examples/plateau/example_feature_transformer.rs b/engine/runtime/examples/plateau/example_feature_transformer.rs index 8d5757479..c9818d79d 100644 --- a/engine/runtime/examples/plateau/example_feature_transformer.rs +++ b/engine/runtime/examples/plateau/example_feature_transformer.rs @@ -1,5 +1,5 @@ mod helper; fn main() { - helper::execute("data-convert/plateau4/06-area-urf/workflow.yml"); + helper::execute("data-convert/plateau4/02-tran-rwy-trk-squr-wwy/workflow.yml"); } diff --git a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/01-bldg/workflow.yml b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/01-bldg/workflow.yml index d00ee4be3..7adaea87e 100644 --- a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/01-bldg/workflow.yml +++ b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/01-bldg/workflow.yml @@ -23,7 +23,8 @@ graphs: creator: | [ #{ - cityGmlPath: env.get("cityGmlPath") + cityGmlPath: env.get("cityGmlPath"), + cityCode: env.get("cityCode"), }, ] @@ -39,14 +40,14 @@ graphs: with: format: citygml dataset: | - env.get("__value").cityGmlPath + env.get("__value")["path"] - id: dc498449-5478-4bff-abaa-59f2d160925f name: PLATEAU4.MaxLodExtractor type: action action: PLATEAU4.MaxLodExtractor with: - cityGmlPathAttribute: cityGmlPath + cityGmlPathAttribute: path maxLodAttribute: maxLod - id: 1fb4ce1c-538a-436d-8dfa-79185e032de3 @@ -57,7 +58,7 @@ graphs: aggregateAttributes: - newAttribute: file attributeValue: | - file::extract_filename(env.get("__value").cityGmlPath) + file::extract_filename(env.get("__value")["path"]) - newAttribute: type attributeValue: | env.get("__feature_type") @@ -114,7 +115,7 @@ graphs: type: action action: FeatureLodFilter with: - filterKey: cityGmlPath + filterKey: path - id: 41d69f1f-2a4d-4bc1-a5d0-175698273571 name: cesium3DTilesWriterByLod1 diff --git a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/02-tran-rwy-trk-squr-wwy/workflow.yml b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/02-tran-rwy-trk-squr-wwy/workflow.yml new file mode 100644 index 000000000..f22aa2099 --- /dev/null +++ b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/02-tran-rwy-trk-squr-wwy/workflow.yml @@ -0,0 +1,221 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/reearth/reearth-flow/main/engine/schema/workflow.json +id: d6a556db-dfac-4ca1-9275-c490ef2d1ad8 +name: "PLATEAU4-DataConvert-02-tran-rwy-trk-squr-wwy" +entryGraphId: 34bf873b-3364-46b0-8153-efeb9568bb3c +with: + cityGmlPath: + cityCode: + codelistsPath: + schemasPath: + targetPackages: + - tran + - rwy + - trk + - squr + - wwy + outputPath: +graphs: + - !include ../../../../graphs/plateau4/folder_and_file_path_reader.yml + - id: 34bf873b-3364-46b0-8153-efeb9568bb3c + name: entry_point + nodes: + - id: 90f40a3e-61d3-48e2-a328-e7226c2ad1ae + name: FeatureCreator + type: action + action: FeatureCreator + with: + creator: | + [ + #{ + cityGmlPath: env.get("cityGmlPath"), + cityCode: env.get("cityCode"), + }, + ] + + - id: d376f32b-7ce8-4721-8b9e-bfa39d71b860 + name: FolderAndFilePathReader + type: subGraph + subGraphId: c6863b71-953b-4d15-af56-396fc93fc617 + + - id: 6f88a422-e69c-45c4-b873-e56db73fe637 + name: CityCodeExtractor + type: action + action: PLATEAU4.CityCodeExtractor + with: + codelistsPathAttribute: dirCodelists + cityCodeAttribute: cityCode + + - id: ded2e272-e05c-4918-86b3-aa9f763da6e6 + name: FeatureReaderByCityGml + type: action + action: FeatureReader + with: + format: citygml + dataset: | + env.get("__value")["path"] + + - id: dc498449-5478-4bff-abaa-59f2d160925f + name: PLATEAU4.MaxLodExtractor + type: action + action: PLATEAU4.MaxLodExtractor + with: + cityGmlPathAttribute: path + maxLodAttribute: maxLod + + - id: 1fb4ce1c-538a-436d-8dfa-79185e032de3 + name: AttributeAggregatorByMaxLod + type: action + action: AttributeAggregator + with: + aggregateAttributes: + - newAttribute: file + attributeValue: | + file::extract_filename(env.get("__value")["path"]) + - newAttribute: type + attributeValue: | + env.get("__feature_type") + - newAttribute: maxLod + attributeValue: | + env.get("__value").maxLod + calculation: | + 1 + calculationAttribute: count + method: count + + - id: 52ff7b3c-5fbb-4ad2-86d9-5df50429e3b4 + name: AttributeMapperByMaxLod + type: action + action: AttributeMapper + with: + mappers: + - attribute: code + expr: | + env.get("__value").file[0..6] + - attribute: type + expr: | + env.get("__value")["type"].split(":")[0] + - attribute: maxLod + expr: | + env.get("__value").maxLod + - attribute: file + expr: | + env.get("__value").file + + - id: 65074ffc-9113-4fbf-8957-9ba1de4c56ab + name: FileWriterTsvFilePath + type: action + action: FileWriter + with: + format: tsv + output: | + file::join_path(env.get("outputPath"), "maxLod.tsv") + + - id: c32a279d-97be-4584-b282-4d65627b1132 + name: FeatureLodFilter + type: action + action: FeatureLodFilter + with: + filterKey: path + + - id: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + name: FeatureDuplicateFilter + type: action + action: FeatureDuplicateFilter + + - id: 6e5ed9fc-006e-4dbe-8699-4663dba795cb + name: AttributeMapperByLod0-2 + type: action + action: AttributeMapper + with: + mappers: + - attribute: meshcode + expr: | + let file = file::extract_filename(env.get("__value")["path"]); + file[0..8] + - attribute: city_code + valueAttribute: cityCode + - attribute: city_name + valueAttribute: cityName + - attribute: feature_type + valueAttribute: gmlName + - attribute: gml_id + valueAttribute: gmlId + - attribute: lod + valueAttribute: maxLod + + - id: 7a17c4f9-dd4d-44b0-936c-50c394272016 + name: NoopSink + type: action + action: NoopSink + + edges: + - id: 5ebf24ab-1d98-49d5-8f58-eb7c18d27244 + from: 90f40a3e-61d3-48e2-a328-e7226c2ad1ae + to: d376f32b-7ce8-4721-8b9e-bfa39d71b860 + fromPort: default + toPort: default + - id: 64196428-ea1b-4177-9d66-28331fad14f8 + from: d376f32b-7ce8-4721-8b9e-bfa39d71b860 + to: 6f88a422-e69c-45c4-b873-e56db73fe637 + fromPort: default + toPort: default + - id: 7b81f501-3f07-4cec-bf9b-9cefcebdf47d + from: 6f88a422-e69c-45c4-b873-e56db73fe637 + to: ded2e272-e05c-4918-86b3-aa9f763da6e6 + fromPort: default + toPort: default + - id: cf845867-6ffc-4b83-9fd5-e376a22470e2 + from: ded2e272-e05c-4918-86b3-aa9f763da6e6 + to: dc498449-5478-4bff-abaa-59f2d160925f + fromPort: default + toPort: default + - id: 046c94ea-9937-4439-b5f8-c8a616f6599d + from: dc498449-5478-4bff-abaa-59f2d160925f + to: 1fb4ce1c-538a-436d-8dfa-79185e032de3 + fromPort: default + toPort: default + - id: 59c14dab-0e56-4f90-85e6-0c8cfa6d1d14 + from: 1fb4ce1c-538a-436d-8dfa-79185e032de3 + to: 52ff7b3c-5fbb-4ad2-86d9-5df50429e3b4 + fromPort: default + toPort: default + - id: 993360df-5cfd-4525-9626-bfe13fa62117 + from: 52ff7b3c-5fbb-4ad2-86d9-5df50429e3b4 + to: 65074ffc-9113-4fbf-8957-9ba1de4c56ab + fromPort: default + toPort: default + - id: ad52c3e6-68ff-4844-a7b2-d302fc0aef14 + from: ded2e272-e05c-4918-86b3-aa9f763da6e6 + to: c32a279d-97be-4584-b282-4d65627b1132 + fromPort: default + toPort: default + - id: dde1d751-fe3e-4283-8742-ec4a61a41574 + from: c32a279d-97be-4584-b282-4d65627b1132 + to: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + fromPort: up_to_lod0 + toPort: default + - id: 83c68df9-a61b-4cad-8f64-ea20186e9db1 + from: c32a279d-97be-4584-b282-4d65627b1132 + to: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + fromPort: up_to_lod1 + toPort: default + - id: dde1d751-fe3e-4283-8742-ec4a61a41574 + from: c32a279d-97be-4584-b282-4d65627b1132 + to: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + fromPort: up_to_lod0 + toPort: default + - id: 7303c673-ccf3-4075-9eec-97176ced4b86 + from: c32a279d-97be-4584-b282-4d65627b1132 + to: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + fromPort: up_to_lod2 + toPort: default + - id: 841f1bed-a4d3-4425-a754-4f0dd7461ead + from: 2ccf7b99-4123-446e-8ff7-049be1c604c7 + to: 6e5ed9fc-006e-4dbe-8699-4663dba795cb + fromPort: default + toPort: default + - id: bef08313-519f-48b5-b74c-6744bbc6bee2 + from: 6e5ed9fc-006e-4dbe-8699-4663dba795cb + to: 7a17c4f9-dd4d-44b0-936c-50c394272016 + fromPort: default + toPort: default diff --git a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/04-luse-lsld/workflow.yml b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/04-luse-lsld/workflow.yml index e78cebc48..dcea58852 100644 --- a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/04-luse-lsld/workflow.yml +++ b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/04-luse-lsld/workflow.yml @@ -24,7 +24,8 @@ graphs: creator: | [ #{ - cityGmlPath: env.get("cityGmlPath") + cityGmlPath: env.get("cityGmlPath"), + cityCode: env.get("cityCode"), }, ] @@ -40,14 +41,14 @@ graphs: with: format: citygml dataset: | - env.get("__value").cityGmlPath + env.get("__value")["path"] - id: dc498449-5478-4bff-abaa-59f2d160925f name: PLATEAU4.MaxLodExtractor type: action action: PLATEAU4.MaxLodExtractor with: - cityGmlPathAttribute: cityGmlPath + cityGmlPathAttribute: path maxLodAttribute: maxLod - id: 1fb4ce1c-538a-436d-8dfa-79185e032de3 diff --git a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/06-area-urf/workflow.yml b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/06-area-urf/workflow.yml index bbf3fd685..b213b4065 100644 --- a/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/06-area-urf/workflow.yml +++ b/engine/runtime/examples/plateau/testdata/workflow/data-convert/plateau4/06-area-urf/workflow.yml @@ -24,7 +24,8 @@ graphs: creator: | [ #{ - cityGmlPath: env.get("cityGmlPath") + cityGmlPath: env.get("cityGmlPath"), + cityCode: env.get("cityCode"), }, ] @@ -40,14 +41,14 @@ graphs: with: format: citygml dataset: | - env.get("__value").cityGmlPath + env.get("__value")["path"] - id: dc498449-5478-4bff-abaa-59f2d160925f name: PLATEAU4.MaxLodExtractor type: action action: PLATEAU4.MaxLodExtractor with: - cityGmlPathAttribute: cityGmlPath + cityGmlPathAttribute: path maxLodAttribute: maxLod - id: 1fb4ce1c-538a-436d-8dfa-79185e032de3 @@ -58,7 +59,7 @@ graphs: aggregateAttributes: - newAttribute: file attributeValue: | - file::extract_filename(env.get("__value").cityGmlPath) + file::extract_filename(env.get("__value")["path"]) - newAttribute: type attributeValue: | env.get("__feature_type")