1use std::hash::Hash;
12use std::marker::PhantomData;
13
14use solverforge_core::score::Score;
15
16use super::collection_extract::{CollectionExtract, FlattenExtract};
17use super::existence_stream::{ExistenceMode, ExistsConstraintStream};
18use super::filter::UniFilter;
19use super::joiner::EqualJoiner;
20use super::relational::operator::{CollectionNode, FlattenNode, ParentFlatten};
21use super::relational::view_plan::{ChildKey, EntityKey, ViewEqualPlan};
22use super::uni_stream::UniConstraintStream;
23
24pub struct FlattenedCollectionTarget<S, P, B, EP, FP, Flatten, Sc>
25where
26 Sc: Score,
27{
28 pub(crate) right_stream: UniConstraintStream<S, P, EP, FP, Sc>,
29 pub(crate) flatten: Flatten,
30 pub(crate) _phantom: PhantomData<(fn() -> B, fn() -> Sc)>,
31}
32
33pub trait ExistenceTarget<S, A, EA, FA, Sc: Score>
34where
35 EA: CollectionExtract<S, Item = A>,
36 FA: UniFilter<S, A>,
37{
38 type Output;
39
40 fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output;
41}
42
43impl<S, A, B, EA, FA, EB, FB, K, KA, KB, Mode, Sc> ExistenceTarget<S, A, EA, FA, Sc>
49 for (
50 UniConstraintStream<S, B, EB, FB, Sc>,
51 EqualJoiner<KA, KB, K, Mode>,
52 )
53where
54 S: Send + Sync + 'static,
55 A: Clone + Send + Sync + 'static,
56 B: Clone + Send + Sync + 'static,
57 EA: CollectionExtract<S, Item = A> + Send + Sync + 'static,
58 FA: UniFilter<S, A> + Send + Sync + 'static,
59 EB: CollectionExtract<S, Item = B> + Send + Sync + 'static,
60 FB: UniFilter<S, B> + Send + Sync + 'static,
61 K: Eq + Hash + Clone + Send + Sync + 'static,
62 KA: Fn(&A) -> K + Send + Sync + 'static,
63 KB: Fn(&B) -> K + Send + Sync + 'static,
64 Sc: Score + 'static,
65{
66 type Output = ExistsConstraintStream<
67 S,
68 A,
69 CollectionNode<S, UniConstraintStream<S, A, EA, FA, Sc>>,
70 CollectionNode<S, UniConstraintStream<S, B, EB, FB, Sc>>,
71 ViewEqualPlan<K, EntityKey<KA>, EntityKey<KB>>,
72 Sc,
73 >;
74
75 fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output {
76 let (right_stream, joiner) = self;
77 let (key_a, key_b) = joiner.into_keys();
78 let left_stream = UniConstraintStream::from_parts(extractor_a, filter_a);
79 let left = CollectionNode::new(left_stream, 0);
80 let right = CollectionNode::new(right_stream, 1);
81 let condition = ViewEqualPlan::new(EntityKey::new(key_a), EntityKey::new(key_b));
82 ExistsConstraintStream::new(mode, left, right, condition)
83 }
84}
85
86impl<S, A, P, B, EA, FA, EP, FP, K, KA, KB, Mode, Flatten, Sc> ExistenceTarget<S, A, EA, FA, Sc>
92 for (
93 FlattenedCollectionTarget<S, P, B, EP, FP, Flatten, Sc>,
94 EqualJoiner<KA, KB, K, Mode>,
95 )
96where
97 S: Send + Sync + 'static,
98 A: Clone + Send + Sync + 'static,
99 P: Clone + Send + Sync + 'static,
100 B: Clone + Send + Sync + 'static,
101 EA: CollectionExtract<S, Item = A> + Send + Sync + 'static,
102 FA: UniFilter<S, A> + Send + Sync + 'static,
103 EP: CollectionExtract<S, Item = P> + Send + Sync + 'static,
104 FP: UniFilter<S, P> + Send + Sync + 'static,
105 K: Eq + Hash + Clone + Send + Sync + 'static,
106 KA: Fn(&A) -> K + Send + Sync + 'static,
107 KB: Fn(&B) -> K + Send + Sync + 'static,
108 Flatten: FlattenExtract<P, Item = B> + Send + Sync + 'static,
109 Sc: Score + 'static,
110{
111 type Output = ExistsConstraintStream<
112 S,
113 A,
114 CollectionNode<S, UniConstraintStream<S, A, EA, FA, Sc>>,
115 FlattenNode<
116 CollectionNode<S, UniConstraintStream<S, P, EP, FP, Sc>>,
117 ParentFlatten<Flatten>,
118 >,
119 ViewEqualPlan<K, EntityKey<KA>, ChildKey<KB>>,
120 Sc,
121 >;
122
123 fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output {
124 let (target, joiner) = self;
125 let FlattenedCollectionTarget {
126 right_stream,
127 flatten,
128 ..
129 } = target;
130 let (key_a, key_b) = joiner.into_keys();
131 let left_stream = UniConstraintStream::from_parts(extractor_a, filter_a);
132 let left = CollectionNode::new(left_stream, 0);
133 let parents = CollectionNode::new(right_stream, 1);
134 let right = FlattenNode::new(parents, ParentFlatten::new(flatten));
135 let condition = ViewEqualPlan::new(EntityKey::new(key_a), ChildKey::new(key_b));
136 ExistsConstraintStream::new(mode, left, right, condition)
137 }
138}