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