ecitygml-io 0.0.2-alpha.5

IO operations for processing CityGML data.
Documentation
use crate::Error;
use crate::gml::codec::core::{
    deserialize_abstract_filling_surface, serialize_abstract_filling_surface,
};
use crate::gml::util::CityGmlElement;
use ecitygml_core::model::construction::{AsAbstractFillingSurface, WindowSurface};
use egml::io::util::{Formatting, XmlNode, extract_xml_element_spans};
use serde::{Deserialize, Serialize};

pub fn deserialize_window_surface(xml_document: &[u8]) -> Result<WindowSurface, Error> {
    let spans = extract_xml_element_spans(xml_document)?;
    let abstract_filling_surface = deserialize_abstract_filling_surface(xml_document, &spans)?;
    let window_surface = WindowSurface::from_abstract_filling_surface(abstract_filling_surface);

    Ok(window_surface)
}

pub fn serialize_window_surface(
    window_surface: &WindowSurface,
    formatting: Formatting,
) -> Result<XmlNode, Error> {
    let xml_node_parts =
        serialize_abstract_filling_surface(window_surface.abstract_filling_surface(), formatting)?;

    Ok(XmlNode::new(
        CityGmlElement::WindowSurface.into(),
        xml_node_parts,
    ))
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct GmlWindowSurface {}

impl From<&WindowSurface> for GmlWindowSurface {
    fn from(_item: &WindowSurface) -> Self {
        Self {}
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ecitygml_core::model::core::{AsAbstractFeature, AsAbstractThematicSurface};
    use egml::model::base::{AsAbstractGml, Id};
    use egml::model::basic_types::Code;
    use itertools::Itertools;
    use quick_xml::{DeError, de};

    #[test]
    fn test_serialize_round_trip() {
        let xml_document = b"
            <con:WindowSurface gml:id=\"GML_d0f329f3-5b05-428d-87c3-945b3868337f\">
              <gml:name>Window West</gml:name>
              <lod3MultiSurface>
                <gml:MultiSurface>
                  <gml:surfaceMember>
                    <gml:Polygon gml:id=\"PolyID58821_1939_612838_272028\">
                      <gml:exterior>
                        <gml:LinearRing gml:id=\"PolyID58821_1939_612838_272028_0\">
                          <gml:pos>457843.79 5439083.12 112.8</gml:pos>
                          <gml:pos>457845.79 5439083.12 112.8</gml:pos>
                          <gml:pos>457845.79 5439083.12 114.0</gml:pos>
                          <gml:pos>457843.79 5439083.12 114.0</gml:pos>
                          <gml:pos>457843.79 5439083.12 112.8</gml:pos>
                        </gml:LinearRing>
                      </gml:exterior>
                    </gml:Polygon>
                  </gml:surfaceMember>
                </gml:MultiSurface>
              </lod3MultiSurface>
            </con:WindowSurface>";

        let window_surface = deserialize_window_surface(xml_document).unwrap();
        let xml_output = serialize_window_surface(&window_surface, Formatting::default())
            .unwrap()
            .to_string(Formatting::default())
            .unwrap();

        assert!(xml_output.contains("con:WindowSurface"));
        assert!(xml_output.contains("gml:id=\"GML_d0f329f3-5b05-428d-87c3-945b3868337f\""));
        assert!(xml_output.contains("gml:name"));
        assert!(xml_output.contains("Window West"));
        assert!(xml_output.contains("lod3MultiSurface"));
        assert!(xml_output.contains("gml:MultiSurface"));
        assert!(xml_output.contains("gml:Polygon"));
    }

    #[test]
    fn test_serialize_with_generic_attributes() {
        let xml_document = b"
            <con:WindowSurface gml:id=\"test-window-id\">
              <genericAttribute>
                <gen:StringAttribute>
                  <gen:name>material</gen:name>
                  <gen:value>glass</gen:value>
                </gen:StringAttribute>
              </genericAttribute>
              <lod2MultiSurface>
                <gml:MultiSurface>
                  <gml:surfaceMember>
                    <gml:Polygon>
                      <gml:exterior>
                        <gml:LinearRing>
                          <gml:pos>0.0 0.0 0.0</gml:pos>
                          <gml:pos>1.0 0.0 0.0</gml:pos>
                          <gml:pos>1.0 1.0 0.0</gml:pos>
                          <gml:pos>0.0 0.0 0.0</gml:pos>
                        </gml:LinearRing>
                      </gml:exterior>
                    </gml:Polygon>
                  </gml:surfaceMember>
                </gml:MultiSurface>
              </lod2MultiSurface>
            </con:WindowSurface>";

        let window_surface = deserialize_window_surface(xml_document).unwrap();
        let xml_output = serialize_window_surface(&window_surface, Formatting::default())
            .unwrap()
            .to_string(Formatting::default())
            .unwrap();

        assert!(xml_output.contains("genericAttribute"));
        assert!(xml_output.contains("material"));
        assert!(xml_output.contains("glass"));
        assert!(xml_output.contains("lod2MultiSurface"));
    }

    #[test]
    fn test_deserialize_with_lod3_multi_surface() {
        let xml_document = b"
            <con:WindowSurface gml:id=\"GML_d0f329f3-5b05-428d-87c3-945b3868337f\">
              <gml:name>Window West</gml:name>
              <lod3MultiSurface>
                <gml:MultiSurface>
                  <gml:surfaceMember>
                    <gml:Polygon gml:id=\"PolyID58821_1939_612838_272028\">
                      <gml:exterior>
                        <gml:LinearRing gml:id=\"PolyID58821_1939_612838_272028_0\">
                          <gml:pos>457843.79 5439083.12 112.8</gml:pos>
                          <gml:pos>457845.79 5439083.12 112.8</gml:pos>
                          <gml:pos>457845.79 5439083.12 114.0</gml:pos>
                          <gml:pos>457843.79 5439083.12 114.0</gml:pos>
                          <gml:pos>457843.79 5439083.12 112.8</gml:pos>
                        </gml:LinearRing>
                      </gml:exterior>
                    </gml:Polygon>
                  </gml:surfaceMember>
                </gml:MultiSurface>
              </lod3MultiSurface>
            </con:WindowSurface>";

        let window_surface = deserialize_window_surface(xml_document).unwrap();

        assert_eq!(
            window_surface.feature_id(),
            &Id::try_from("GML_d0f329f3-5b05-428d-87c3-945b3868337f").expect("should work")
        );
        assert_eq!(
            window_surface.names().first().unwrap(),
            &Code::new("Window West")
        );
        assert!(window_surface.lod3_multi_surface().is_some());
    }
}