prehnite_core/db/schema/app_global/
book_search_result.rs1use 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}