prehnite_core/db/schema/app_global/
book_search_result.rs

1use crate::db::schema::{Bibliography, BibliographyAuthor, Publisher, RelBibliographyAuthor};
2use crate::db::util::cushion_types::{OptionString, VecString};
3use crate::to_hash_map_key_name;
4use indexmap::IndexMap;
5use rhai::{CustomType, Dynamic, EvalAltResult, Position, TypeBuilder};
6use sqlx::{Acquire, SqliteConnection};
7
8#[derive(Default, Clone, CustomType, Debug, PartialEq)]
9pub struct BookSearchResult {
10    pub isbn: Option<String>,
11    pub url: Option<String>,
12    pub title: String,
13    pub detail: Option<String>,
14    pub authors: Vec<String>,
15    pub publisher: Option<String>,
16    pub publication_date: Option<String>,
17}
18
19impl BookSearchResult {
20    pub(crate) fn new(
21        isbn: Dynamic,
22        url: Dynamic,
23        title: String,
24        detail: Dynamic,
25        authors: Dynamic,
26        publisher: Dynamic,
27        publication_date: Dynamic,
28    ) -> Self {
29        BookSearchResult {
30            isbn: OptionString::from(isbn).into(),
31            url: OptionString::from(url).into(),
32            title,
33            detail: OptionString::from(detail).into(),
34            authors: VecString::from(authors).into(),
35            publisher: OptionString::from(publisher).into(),
36            publication_date: OptionString::from(publication_date).into(),
37        }
38    }
39
40    pub(crate) fn example() -> Self {
41        BookSearchResult {
42            isbn: Some("000-0-00-000000-0".to_string()),
43            url: None,
44            title: "The Book of Example".to_string(),
45            detail: Some(
46                "This book is an example! This Book Search API configuration is for illustrative purposes only and cannot be used.".to_string(),
47            ),
48            authors: vec![
49                "Hanako T".to_string(),
50                "Taro T".to_string()
51            ],
52            publisher: Some("FooBar Printing Exm".to_string()),
53            publication_date: Some("0000-01-01".to_string()),
54        }
55    }
56
57    fn publishers_from_bsr(bsr: &[BookSearchResult]) -> Vec<Publisher> {
58        bsr.iter()
59            .filter_map(|v| {
60                Some(Publisher {
61                    name: v.publisher.clone()?,
62                    ..Default::default()
63                })
64            })
65            .collect()
66    }
67
68    fn authors_from_bsr(bsr: &[BookSearchResult]) -> Vec<BibliographyAuthor> {
69        bsr.iter()
70            .filter_map(|v| {
71                Some(v.authors.clone().into_iter().map(|v| BibliographyAuthor {
72                    name: v,
73                    ..Default::default()
74                }))
75            })
76            .flatten()
77            .collect()
78    }
79
80    fn bibliographies_from_bsr(
81        bsr: &[BookSearchResult],
82        publishers: &IndexMap<String, Publisher>,
83    ) -> Vec<Bibliography> {
84        bsr.iter()
85            .enumerate()
86            .map(|(i, v)| Bibliography {
87                isbn: v.isbn.clone(),
88                url: v.url.clone(),
89                title: v.title.clone(),
90                detail: v.detail.clone(),
91                publisher: v
92                    .publisher
93                    .as_ref()
94                    .and_then(|v| publishers.get(v).cloned()),
95                publication_date: v.publication_date.clone(),
96                tmp_registration_id: Some(i),
97                ..Default::default()
98            })
99            .collect()
100    }
101
102    fn rel_bibliography_author_from_bibliographies(
103        bsr: &[BookSearchResult],
104        bibliographies: &[Bibliography],
105        authors: &IndexMap<String, BibliographyAuthor>,
106    ) -> Vec<RelBibliographyAuthor> {
107        bibliographies
108            .iter()
109            .filter_map(|b| {
110                Some(bsr[b.tmp_registration_id?].authors.iter().filter_map(|a| {
111                    Some(RelBibliographyAuthor {
112                        id: 0,
113                        bibliography_id: b.id,
114                        bibliography_author_id: authors.get(a)?.id,
115                    })
116                }))
117            })
118            .flatten()
119            .collect()
120    }
121
122    pub async fn register(
123        conn: &mut SqliteConnection,
124        book_search_result_list: Vec<BookSearchResult>,
125    ) -> Result<Vec<Bibliography>, sqlx::Error> {
126        let mut tx = conn.begin().await?;
127        let publishers: IndexMap<String, Publisher> = to_hash_map_key_name!(
128            Publisher::register_many(
129                Self::publishers_from_bsr(book_search_result_list.as_slice()).as_slice(),
130                &mut *tx,
131                true,
132            )
133            .await?
134        );
135        let authors: IndexMap<String, BibliographyAuthor> = to_hash_map_key_name!(
136            BibliographyAuthor::register_many(
137                Self::authors_from_bsr(book_search_result_list.as_slice()).as_slice(),
138                &mut *tx,
139                true,
140            )
141            .await?
142        );
143        let bibliographies = Bibliography::register_many(
144            Self::bibliographies_from_bsr(book_search_result_list.as_slice(), &publishers)
145                .as_slice(),
146            &mut *tx,
147            true,
148        )
149        .await?;
150        RelBibliographyAuthor::register_many(
151            Self::rel_bibliography_author_from_bibliographies(
152                book_search_result_list.as_slice(),
153                bibliographies.as_slice(),
154                &authors,
155            )
156            .as_slice(),
157            &mut *tx,
158            true,
159        )
160        .await?;
161        tx.commit().await?;
162        Ok(bibliographies)
163    }
164}