1use std::any::TypeId;
11use std::fmt::Display;
12
13use async_trait::async_trait;
14use indexmap::IndexMap;
15use serde_json::Value;
16use vantage_core::{Result, error};
17use vantage_dataset::traits::{ReadableValueSet, ValueSet, WritableValueSet};
18use vantage_types::{Entity, Record};
19
20pub type AnyRecord = Record<Value>;
22
23use crate::{
24 conditions::ConditionHandle,
25 pagination::Pagination,
26 table::Table,
27 traits::{table_like::TableLike, table_source::TableSource},
28};
29
30pub struct AnyTable {
33 inner: Box<dyn TableLike<Value = Value, Id = String>>,
34 datasource_type_id: TypeId,
35 entity_type_id: TypeId,
36 datasource_name: &'static str,
37 entity_name: &'static str,
38}
39
40impl AnyTable {
41 pub fn new<T: TableSource<Value = Value, Id = String> + 'static, E: Entity<Value> + 'static>(
44 table: Table<T, E>,
45 ) -> Self {
46 Self {
47 inner: Box::new(table),
48 datasource_type_id: TypeId::of::<T>(),
49 entity_type_id: TypeId::of::<E>(),
50 datasource_name: std::any::type_name::<T>(),
51 entity_name: std::any::type_name::<E>(),
52 }
53 }
54
55 pub fn from_table<T, E>(table: Table<T, E>) -> Self
60 where
61 T: TableSource + 'static,
62 T::Value: Into<Value> + From<Value>,
63 T::Id: Display + From<String>,
64 E: Entity<T::Value> + 'static,
65 {
66 Self {
67 inner: Box::new(JsonAdapter { inner: table }),
68 datasource_type_id: TypeId::of::<T>(),
69 entity_type_id: TypeId::of::<E>(),
70 datasource_name: std::any::type_name::<T>(),
71 entity_name: std::any::type_name::<E>(),
72 }
73 }
74
75 pub fn downcast<
79 T: TableSource<Value = Value, Id = String> + 'static,
80 E: Entity<Value> + 'static,
81 >(
82 self,
83 ) -> Result<Table<T, E>> {
84 if self.datasource_type_id != TypeId::of::<T>() {
86 let expected = std::any::type_name::<T>();
87 return Err(error!(
88 "DataSource type mismatch",
89 expected = expected,
90 actual = self.datasource_name
91 ));
92 }
93 if self.entity_type_id != TypeId::of::<E>() {
94 let expected = std::any::type_name::<E>();
95 return Err(error!(
96 "Entity type mismatch",
97 expected = expected,
98 actual = self.entity_name
99 ));
100 }
101
102 self.inner
104 .into_any()
105 .downcast::<Table<T, E>>()
106 .map(|boxed| *boxed)
107 .map_err(|_| error!("Failed to downcast table"))
108 }
109
110 pub fn datasource_name(&self) -> &str {
112 self.datasource_name
113 }
114
115 pub fn entity_name(&self) -> &str {
117 self.entity_name
118 }
119
120 pub fn datasource_type_id(&self) -> TypeId {
122 self.datasource_type_id
123 }
124
125 pub fn entity_type_id(&self) -> TypeId {
127 self.entity_type_id
128 }
129
130 pub fn is_type<T: TableSource + 'static, E: Entity<Value> + 'static>(&self) -> bool {
132 self.datasource_type_id == TypeId::of::<T>() && self.entity_type_id == TypeId::of::<E>()
133 }
134}
135
136impl Clone for AnyTable {
137 fn clone(&self) -> Self {
138 Self {
139 inner: self.inner.clone_box(),
140 datasource_type_id: self.datasource_type_id,
141 entity_type_id: self.entity_type_id,
142 datasource_name: self.datasource_name,
143 entity_name: self.entity_name,
144 }
145 }
146}
147
148impl std::fmt::Debug for AnyTable {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 f.debug_struct("AnyTable")
151 .field("datasource", &self.datasource_name)
152 .field("entity", &self.entity_name)
153 .finish()
154 }
155}
156
157impl ValueSet for AnyTable {
159 type Id = String;
160 type Value = Value;
161}
162
163#[async_trait]
165impl ReadableValueSet for AnyTable {
166 async fn list_values(&self) -> Result<IndexMap<Self::Id, Record<Self::Value>>> {
167 self.inner.list_values().await
168 }
169
170 async fn get_value(&self, id: &Self::Id) -> Result<Record<Self::Value>> {
171 self.inner.get_value(id).await
172 }
173
174 async fn get_some_value(&self) -> Result<Option<(Self::Id, Record<Self::Value>)>> {
175 self.inner.get_some_value().await
176 }
177}
178
179#[async_trait]
181impl WritableValueSet for AnyTable {
182 async fn insert_value(
183 &self,
184 id: &Self::Id,
185 record: &Record<Self::Value>,
186 ) -> Result<Record<Self::Value>> {
187 self.inner.insert_value(id, record).await
188 }
189
190 async fn replace_value(
191 &self,
192 id: &Self::Id,
193 record: &Record<Self::Value>,
194 ) -> Result<Record<Self::Value>> {
195 self.inner.replace_value(id, record).await
196 }
197
198 async fn patch_value(
199 &self,
200 id: &Self::Id,
201 partial: &Record<Self::Value>,
202 ) -> Result<Record<Self::Value>> {
203 self.inner.patch_value(id, partial).await
204 }
205
206 async fn delete(&self, id: &Self::Id) -> Result<()> {
207 self.inner.delete(id).await
208 }
209
210 async fn delete_all(&self) -> Result<()> {
211 self.inner.delete_all().await
212 }
213}
214
215#[async_trait]
217impl TableLike for AnyTable {
218 fn table_name(&self) -> &str {
219 self.inner.table_name()
220 }
221
222 fn table_alias(&self) -> &str {
223 self.inner.table_alias()
224 }
225
226 fn column_names(&self) -> Vec<String> {
227 self.inner.column_names()
228 }
229
230 fn add_condition(&mut self, condition: Box<dyn std::any::Any + Send + Sync>) -> Result<()> {
231 self.inner.add_condition(condition)
232 }
233
234 fn temp_add_condition(
235 &mut self,
236 condition: vantage_expressions::AnyExpression,
237 ) -> Result<ConditionHandle> {
238 self.inner.temp_add_condition(condition)
239 }
240
241 fn temp_remove_condition(&mut self, handle: ConditionHandle) -> Result<()> {
242 self.inner.temp_remove_condition(handle)
243 }
244
245 fn search_expression(&self, search_value: &str) -> Result<vantage_expressions::AnyExpression> {
246 self.inner.search_expression(search_value)
247 }
248
249 fn clone_box(&self) -> Box<dyn TableLike<Value = Self::Value, Id = Self::Id>> {
250 Box::new(self.clone())
251 }
252
253 fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
254 self
255 }
256
257 fn as_any_ref(&self) -> &dyn std::any::Any {
258 self
259 }
260
261 fn set_pagination(&mut self, pagination: Option<Pagination>) {
262 self.inner.set_pagination(pagination)
263 }
264
265 fn get_pagination(&self) -> Option<&Pagination> {
266 self.inner.get_pagination()
267 }
268
269 async fn get_count(&self) -> vantage_core::Result<i64> {
270 self.inner.get_count().await
271 }
272}
273
274impl AnyTable {
275 pub fn with_pagination<F>(&mut self, func: F)
277 where
278 F: FnOnce(&mut Pagination),
279 {
280 let mut pagination = self.inner.get_pagination().copied().unwrap_or_default();
281 func(&mut pagination);
282 self.inner.set_pagination(Some(pagination));
283 }
284}
285
286struct JsonAdapter<T: TableSource, E: Entity<T::Value>> {
291 inner: Table<T, E>,
292}
293
294impl<T: TableSource, E: Entity<T::Value>> Clone for JsonAdapter<T, E> {
295 fn clone(&self) -> Self {
296 Self {
297 inner: self.inner.clone(),
298 }
299 }
300}
301
302impl<T, E> JsonAdapter<T, E>
303where
304 T: TableSource,
305 T::Value: Into<Value>,
306 T::Id: Display,
307 E: Entity<T::Value>,
308{
309 fn convert_record(record: Record<T::Value>) -> Record<Value> {
310 record.into_iter().map(|(k, v)| (k, v.into())).collect()
311 }
312
313 fn convert_record_back(record: &Record<Value>) -> Record<T::Value>
314 where
315 T::Value: From<Value>,
316 {
317 record
318 .iter()
319 .map(|(k, v)| (k.clone(), T::Value::from(v.clone())))
320 .collect()
321 }
322}
323
324impl<T, E> ValueSet for JsonAdapter<T, E>
325where
326 T: TableSource,
327 E: Entity<T::Value>,
328{
329 type Id = String;
330 type Value = Value;
331}
332
333#[async_trait]
334impl<T, E> ReadableValueSet for JsonAdapter<T, E>
335where
336 T: TableSource,
337 T::Value: Into<Value>,
338 T::Id: Display + From<String>,
339 E: Entity<T::Value>,
340{
341 async fn list_values(&self) -> Result<IndexMap<String, Record<Value>>> {
342 let raw = self
343 .inner
344 .data_source()
345 .list_table_values(&self.inner)
346 .await?;
347 Ok(raw
348 .into_iter()
349 .map(|(id, rec)| (id.to_string(), Self::convert_record(rec)))
350 .collect())
351 }
352
353 async fn get_value(&self, id: &String) -> Result<Record<Value>> {
354 let native_id: T::Id = id.clone().into();
355 let rec = self
356 .inner
357 .data_source()
358 .get_table_value(&self.inner, &native_id)
359 .await?;
360 Ok(Self::convert_record(rec))
361 }
362
363 async fn get_some_value(&self) -> Result<Option<(String, Record<Value>)>> {
364 let result = self
365 .inner
366 .data_source()
367 .get_table_some_value(&self.inner)
368 .await?;
369 Ok(result.map(|(id, rec)| (id.to_string(), Self::convert_record(rec))))
370 }
371}
372
373#[async_trait]
374impl<T, E> WritableValueSet for JsonAdapter<T, E>
375where
376 T: TableSource,
377 T::Value: Into<Value> + From<Value>,
378 T::Id: Display + From<String>,
379 E: Entity<T::Value>,
380{
381 async fn insert_value(&self, id: &String, record: &Record<Value>) -> Result<Record<Value>> {
382 let native_id: T::Id = id.clone().into();
383 let native_rec = Self::convert_record_back(record);
384 let returned = self
385 .inner
386 .data_source()
387 .insert_table_value(&self.inner, &native_id, &native_rec)
388 .await?;
389 Ok(Self::convert_record(returned))
390 }
391
392 async fn replace_value(&self, id: &String, record: &Record<Value>) -> Result<Record<Value>> {
393 let native_id: T::Id = id.clone().into();
394 let native_rec = Self::convert_record_back(record);
395 let returned = self
396 .inner
397 .data_source()
398 .replace_table_value(&self.inner, &native_id, &native_rec)
399 .await?;
400 Ok(Self::convert_record(returned))
401 }
402
403 async fn patch_value(&self, id: &String, partial: &Record<Value>) -> Result<Record<Value>> {
404 let native_id: T::Id = id.clone().into();
405 let native_rec = Self::convert_record_back(partial);
406 let returned = self
407 .inner
408 .data_source()
409 .patch_table_value(&self.inner, &native_id, &native_rec)
410 .await?;
411 Ok(Self::convert_record(returned))
412 }
413
414 async fn delete(&self, id: &String) -> Result<()> {
415 let native_id: T::Id = id.clone().into();
416 self.inner
417 .data_source()
418 .delete_table_value(&self.inner, &native_id)
419 .await
420 }
421
422 async fn delete_all(&self) -> Result<()> {
423 self.inner
424 .data_source()
425 .delete_table_all_values(&self.inner)
426 .await
427 }
428}
429
430#[async_trait]
431impl<T, E> TableLike for JsonAdapter<T, E>
432where
433 T: TableSource + 'static,
434 T::Value: Into<Value> + From<Value>,
435 T::Id: Display + From<String>,
436 E: Entity<T::Value> + 'static,
437{
438 fn table_name(&self) -> &str {
439 self.inner.table_name()
440 }
441
442 fn table_alias(&self) -> &str {
443 self.inner.table_name()
444 }
445
446 fn column_names(&self) -> Vec<String> {
447 self.inner.columns().keys().cloned().collect()
448 }
449
450 fn add_condition(&mut self, _condition: Box<dyn std::any::Any + Send + Sync>) -> Result<()> {
451 Err(error!("add_condition not supported through JsonAdapter"))
452 }
453
454 fn temp_add_condition(
455 &mut self,
456 _condition: vantage_expressions::AnyExpression,
457 ) -> Result<ConditionHandle> {
458 Err(error!(
459 "temp_add_condition not supported through JsonAdapter"
460 ))
461 }
462
463 fn temp_remove_condition(&mut self, _handle: ConditionHandle) -> Result<()> {
464 Err(error!(
465 "temp_remove_condition not supported through JsonAdapter"
466 ))
467 }
468
469 fn search_expression(&self, _search_value: &str) -> Result<vantage_expressions::AnyExpression> {
470 Err(error!(
471 "search_expression not supported through JsonAdapter"
472 ))
473 }
474
475 fn clone_box(&self) -> Box<dyn TableLike<Value = Value, Id = String>> {
476 Box::new(self.clone())
477 }
478
479 fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
480 self
481 }
482
483 fn as_any_ref(&self) -> &dyn std::any::Any {
484 self
485 }
486
487 fn set_pagination(&mut self, pagination: Option<Pagination>) {
488 self.inner.set_pagination(pagination);
489 }
490
491 fn get_pagination(&self) -> Option<&Pagination> {
492 self.inner.pagination()
493 }
494
495 async fn get_count(&self) -> Result<i64> {
496 self.inner.data_source().get_table_count(&self.inner).await
497 }
498}
499
500#[cfg(test)]
501mod tests {
502 use crate::mocks::mock_table_source::MockTableSource;
503
504 use super::*;
505
506 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
507 struct TestEntity {
508 id: i32,
509 name: String,
510 }
511
512 #[test]
513 fn test_anytable_creation_and_downcast() {
514 let ds = MockTableSource::new();
515 let table = Table::<MockTableSource, TestEntity>::new("test", ds);
516 let any = AnyTable::new(table.clone());
517
518 assert_eq!(
519 any.datasource_name(),
520 std::any::type_name::<MockTableSource>()
521 );
522 assert_eq!(any.entity_name(), std::any::type_name::<TestEntity>());
523
524 let recovered = any.downcast::<MockTableSource, TestEntity>().unwrap();
526 assert_eq!(recovered.table_name(), "test");
527 }
528
529 #[test]
530 fn test_anytable_downcast_wrong_entity() {
531 let ds = MockTableSource::new();
532 let table = Table::<MockTableSource, TestEntity>::new("test", ds);
533 let any = AnyTable::new(table);
534
535 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
537 struct DifferentEntity;
538
539 let result = any.downcast::<MockTableSource, DifferentEntity>();
542 assert!(result.is_err());
543 }
544
545 #[test]
546 fn test_anytable_is_type() {
547 let ds = MockTableSource::new();
548 let table = Table::<MockTableSource, TestEntity>::new("test", ds);
549 let any = AnyTable::new(table);
550
551 assert!(any.is_type::<MockTableSource, TestEntity>());
552 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
554 struct OtherEntity;
555
556 assert!(!any.is_type::<MockTableSource, OtherEntity>());
557 }
558
559 #[test]
560 fn test_anytable_debug() {
561 let ds = MockTableSource::new();
562 let table = Table::<MockTableSource, TestEntity>::new("test", ds);
563 let any = AnyTable::new(table);
564
565 let debug_str = format!("{:?}", any);
566 assert!(debug_str.contains("AnyTable"));
567 assert!(debug_str.contains("datasource"));
568 assert!(debug_str.contains("entity"));
569 }
570}