dctap/
dctap.rs

1use crate::{
2    tap_config::TapConfig,
3    tap_error::TapError,
4    // TapReader,
5    TapReaderBuilder,
6    TapShape,
7};
8use serde::{Deserialize, Serialize};
9use std::{fmt::Display, io, path::Path};
10use tracing::{debug, info};
11
12#[derive(Debug, Serialize, Deserialize)]
13struct TapShapeId(String);
14
15#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
16pub struct DCTap {
17    version: String,
18
19    shapes: Vec<TapShape>,
20}
21
22impl Default for DCTap {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl DCTap {
29    pub fn new() -> DCTap {
30        DCTap {
31            version: "0.1".to_string(),
32            shapes: Vec::new(),
33        }
34    }
35
36    pub fn add_shape(&mut self, shape: &TapShape) {
37        self.shapes.push(shape.clone());
38    }
39
40    pub fn from_path<P: AsRef<Path>>(path: P, config: &TapConfig) -> Result<DCTap, TapError> {
41        let mut dctap = DCTap::new();
42        let mut tap_reader = TapReaderBuilder::from_path(path, config)?;
43        for maybe_shape in tap_reader.shapes() {
44            let shape = maybe_shape?;
45            dctap.add_shape(&shape)
46        }
47        if tap_reader.has_warnings() {
48            for warning in tap_reader.warnings() {
49                info!("Warning: {warning}");
50            }
51        }
52        Ok(dctap)
53    }
54
55    pub fn from_reader<R: io::Read>(reader: R, config: &TapConfig) -> Result<DCTap, TapError> {
56        let mut dctap = DCTap::new();
57        debug!("DCTap parsed: {:?}", dctap);
58        let mut tap_reader = TapReaderBuilder::from_reader(reader, config)?;
59        for maybe_shape in tap_reader.shapes() {
60            let shape = maybe_shape?;
61            dctap.add_shape(&shape)
62        }
63        Ok(dctap)
64    }
65
66    /*pub fn from_excel<P: AsRef<Path>>(
67        path: P,
68        sheet_name: Option<&str>,
69        config: &TapConfig,
70    ) -> Result<DCTap, TapError> {
71        let mut dctap = DCTap::new();
72        debug!("DCTap parsed: {:?}", dctap);
73        let mut tap_reader: TapReader<io::Empty> =
74            TapReaderBuilder::from_excel(path, sheet_name, config)?;
75        for maybe_shape in tap_reader.shapes() {
76            let shape = maybe_shape?;
77            dctap.add_shape(&shape)
78        }
79        Ok(dctap)
80    }*/
81
82    pub fn shapes(&self) -> impl Iterator<Item = &TapShape> {
83        self.shapes.iter()
84    }
85}
86
87impl Display for DCTap {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        for shape in self.shapes() {
90            write!(f, "{shape}")?;
91        }
92        Ok(())
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use crate::{PropertyId, ShapeId, TapShape, TapStatement};
99
100    use super::*;
101
102    #[test]
103    fn test_simple() {
104        let data = "\
105shapeId,shapeLabel,propertyId,propertyLabel
106Person,PersonLabel,knows,knowsLabel
107";
108        let dctap = DCTap::from_reader(data.as_bytes(), &TapConfig::default()).unwrap();
109        let mut expected_shape = TapShape::new(2);
110        expected_shape.set_shape_id(&ShapeId::new("Person", 2));
111        expected_shape.set_shape_label("PersonLabel");
112        let mut statement =
113            TapStatement::new(PropertyId::new("knows", 2)).with_source_line_number(2);
114        statement.set_property_label("knowsLabel");
115        expected_shape.add_statement(statement);
116        let mut expected_dctap = DCTap::new();
117        expected_dctap.add_shape(&expected_shape);
118        assert_eq!(dctap, expected_dctap);
119    }
120}