3939import cds .gen .adminservice .GenreHierarchy ;
4040import cds .gen .adminservice .GenreHierarchy_ ;
4141
42+ import static cds .gen .adminservice .AdminService_ .GENRE_HIERARCHY ;
43+
4244@ Component
4345@ Profile ("default" )
4446@ ServiceName (AdminService_ .CDS_NAME )
@@ -47,8 +49,8 @@ public class HierarchyHandler implements EventHandler {
4749 private final PersistenceService db ;
4850
4951 HierarchyHandler (PersistenceService db ) {
50- this .db = db ;
51- }
52+ this .db = db ;
53+ }
5254
5355 @ Before (event = CqnService .EVENT_READ , entity = GenreHierarchy_ .CDS_NAME )
5456 public void readGenreHierarchy (CdsReadEventContext event ) {
@@ -58,12 +60,12 @@ public void readGenreHierarchy(CdsReadEventContext event) {
5860 if (trafos .size () < 1 ) {
5961 return ;
6062 }
61-
63+
6264 if (getTopLevels (trafos ) instanceof CqnTopLevelsTransformation topLevels ) {
6365 result = topLevels (topLevels , CQL .TRUE );
6466 } else if (trafos .get (0 ) instanceof CqnDescendantsTransformation descendants ) {
6567 result = handleDescendants (descendants );
66- } else if (trafos .get (0 ) instanceof CqnAncestorsTransformation ancestors ) {
68+ } else if (trafos .get (0 ) instanceof CqnAncestorsTransformation ancestors ) {
6769 if (trafos .size () == 2 && trafos .get (1 ) instanceof CqnTopLevelsTransformation topLevels ) {
6870 result = handleAncestors (ancestors , topLevels );
6971 } else if (trafos .size () == 3 && trafos .get (2 ) instanceof CqnTopLevelsTransformation topLevels ) {
@@ -77,7 +79,8 @@ public void readGenreHierarchy(CdsReadEventContext event) {
7779 private CqnTopLevelsTransformation getTopLevels (List <CqnTransformation > trafos ) {
7880 if (trafos .get (0 ) instanceof CqnTopLevelsTransformation topLevels ) {
7981 return topLevels ;
80- } else if (trafos .size () == 2 && trafos .get (0 ) instanceof CqnOrderByTransformation && trafos .get (1 ) instanceof CqnTopLevelsTransformation topLevels ) {
82+ } else if (trafos .size () == 2 && trafos .get (0 ) instanceof CqnOrderByTransformation
83+ && trafos .get (1 ) instanceof CqnTopLevelsTransformation topLevels ) {
8184 return topLevels ;
8285 }
8386 return null ;
@@ -93,8 +96,9 @@ private void setResult(CdsReadEventContext event, List<GenreHierarchy> result) {
9396
9497 private void addDrillState (List <GenreHierarchy > ghs ) {
9598 List <Integer > ids = ghs .stream ().map (gh -> gh .getId ()).toList ();
96- Set <Integer > parents = ghs .stream ().map (gh -> gh .getParntId ()).filter (p -> p != null ).collect (Collectors .toSet ());
97- CqnSelect q = Select .from (AdminService_ .GENRE_HIERARCHY ).columns (gh -> gh .parnt_ID ().as ("id" ))
99+ Set <Integer > parents = ghs .stream ().map (gh -> gh .getParntId ()).filter (p -> p != null )
100+ .collect (Collectors .toSet ());
101+ CqnSelect q = Select .from (GENRE_HIERARCHY ).columns (gh -> gh .parnt_ID ().as ("id" ))
98102 .where (gh -> gh .parnt_ID ().in (ids ));
99103 Set <Object > nonLeafs = db
100104 .run (q )
@@ -111,42 +115,43 @@ private void addDrillState(List<GenreHierarchy> ghs) {
111115 } else {
112116 gh .setDrillState ("leaf" );
113117 }
114- }
118+ }
115119 }
116-
117- private List <GenreHierarchy > handleDescendants (CqnDescendantsTransformation descendants ) {
118- Map <Integer , GenreHierarchy > lookup = new HashMap <>();
119- CqnFilterTransformation filter = (CqnFilterTransformation ) descendants .transformations ().get (0 );
120- CqnSelect getRoot = Select .from (AdminService_ .GENRE_HIERARCHY ).where (filter .filter ());
121- GenreHierarchy root = db .run (getRoot ).single (GenreHierarchy .class );
122- lookup .put (root .getId (), root );
123120
124- CqnPredicate parentFilter = CQL .copy (filter .filter (), new Modifier () {
121+ private CqnPredicate descendantsFilter (CqnDescendantsTransformation descendants ) {
122+ CqnTransformation trafo = descendants .transformations ().get (0 );
123+ CqnPredicate start = ((CqnFilterTransformation ) trafo ).filter ();
124+ CqnPredicate result = CQL .FALSE ;
125+ if (descendants .keepStart ()) {
126+ result = CQL .or (result , start );
127+ }
128+ CqnPredicate children = CQL .copy (start , new Modifier () {
125129 @ Override
126130 public CqnValue ref (CqnElementRef ref ) {
127131 return CQL .get (GenreHierarchy .PARNT_ID );
128132 }
129133 });
134+ result = CQL .or (result , children );
130135
131- CqnSelect childrenCQN = Select .from (AdminService_ .GENRE_HIERARCHY ).where (parentFilter );
132- List <GenreHierarchy > children = db .run (childrenCQN ).listOf (GenreHierarchy .class );
133- children .forEach (gh -> lookup .put (gh .getId (), gh ));
134- children .forEach (gh -> gh .setParnt (lookup .get (gh .getParntId ())));
135-
136- return children .stream ().sorted (new Sorter ()).toList ();
136+ return result ;
137137 }
138138
139- private List < GenreHierarchy > handleAncestors (CqnAncestorsTransformation ancestors , CqnTopLevelsTransformation topLevels ) {
139+ private CqnPredicate ancestorsFilter (CqnAncestorsTransformation ancestors ) {
140140 CqnTransformation trafo = ancestors .transformations ().get (0 );
141- Select <GenreHierarchy_ > inner = Select .from (AdminService_ . GENRE_HIERARCHY ).columns (gh -> gh .ID ());
141+ Select <GenreHierarchy_ > inner = Select .from (GENRE_HIERARCHY ).columns (gh -> gh .ID ());
142142 if (trafo instanceof CqnFilterTransformation filter ) {
143143 inner .where (filter .filter ());
144144 } else if (trafo instanceof CqnSearchTransformation search ) {
145145 inner .search (search .search ());
146146 }
147- Select <GenreHierarchy_ > outer = Select .from (AdminService_ .GENRE_HIERARCHY ).columns (gh -> gh .ID ().as ("i0" ), gh -> gh .parnt ().ID ().as ("i1" ),
148- gh -> gh .parnt ().parnt ().ID ().as ("i2" ), gh -> gh .parnt ().parnt ().parnt ().ID ().as ("i3" ),
149- gh -> gh .parnt ().parnt ().parnt ().parnt ().ID ().as ("i4" )).where (gh -> gh .ID ().in (inner ));
147+
148+ Select <GenreHierarchy_ > outer = Select .from (GENRE_HIERARCHY )
149+ .columns (gh -> gh .ID ().as ("i0" ),
150+ gh -> gh .parnt ().ID ().as ("i1" ),
151+ gh -> gh .parnt ().parnt ().ID ().as ("i2" ),
152+ gh -> gh .parnt ().parnt ().parnt ().ID ().as ("i3" ),
153+ gh -> gh .parnt ().parnt ().parnt ().parnt ().ID ().as ("i4" ))
154+ .where (gh -> gh .ID ().in (inner ));
150155
151156 Set <Integer > ancestorIds = new HashSet <>();
152157 db .run (outer ).stream ().forEach (r -> {
@@ -157,7 +162,30 @@ private List<GenreHierarchy> handleAncestors(CqnAncestorsTransformation ancestor
157162 addIfNotNull (ancestorIds , r , "i4" );
158163 });
159164
160- CqnPredicate filter = CQL .get (GenreHierarchy_ .ID ).in (ancestorIds .stream ().toList ());
165+ return CQL .get (GenreHierarchy_ .ID ).in (ancestorIds .stream ().toList ());
166+ }
167+
168+ private List <GenreHierarchy > handleDescendants (CqnDescendantsTransformation descendants ) {
169+ CqnPredicate filter = descendantsFilter (descendants );
170+ CqnSelect childrenCQN = Select .from (GENRE_HIERARCHY ).where (filter );
171+ List <GenreHierarchy > nodes = db .run (childrenCQN ).listOf (GenreHierarchy .class );
172+
173+ connect (nodes );
174+
175+ return nodes .stream ().sorted (new Sorter ()).toList ();
176+ }
177+
178+ private static void connect (List <GenreHierarchy > nodes ) {
179+ Map <Integer , GenreHierarchy > lookup = new HashMap <>();
180+ nodes .forEach (gh -> lookup .put (gh .getId (), gh ));
181+ nodes .forEach (gh -> gh .setParnt (lookup .get (gh .getParntId ())));
182+ nodes .forEach (gh -> gh .setDistanceFromRoot (distanceFromRoot (gh )));
183+ }
184+
185+ private List <GenreHierarchy > handleAncestors (CqnAncestorsTransformation ancestors ,
186+ CqnTopLevelsTransformation topLevels ) {
187+ CqnPredicate filter = ancestorsFilter (ancestors );
188+
161189 return topLevels (topLevels , filter );
162190 }
163191
@@ -166,24 +194,26 @@ private void addIfNotNull(Set<Integer> ancestorIds, Row r, String key) {
166194 if (id != null ) {
167195 ancestorIds .add (id );
168196 }
169- }
197+ }
170198
171199 private List <GenreHierarchy > topLevels (CqnTopLevelsTransformation topLevels , CqnPredicate filter ) {
172- return topLevels .levels () < 0 || !(topLevels .expandLevels ().isEmpty ()) ? topLevelsAll (filter ) : topLevelsLimit (topLevels .levels (), filter );
200+ return topLevels .levels () < 0 || !(topLevels .expandLevels ().isEmpty ()) ? topLevelsAll (filter )
201+ : topLevelsLimit (topLevels .levels (), filter );
173202 }
174203
175204 private List <GenreHierarchy > topLevelsLimit (long limit , CqnPredicate filter ) {
176- Map <Integer , GenreHierarchy > lookup = new HashMap <>();
205+ Map <Integer , GenreHierarchy > lookup = new HashMap <>();
177206
178- CqnSelect getRoots = Select .from (AdminService_ . GENRE_HIERARCHY ).where (gh -> gh .parnt_ID ().isNull ().and (filter ));
207+ CqnSelect getRoots = Select .from (GENRE_HIERARCHY ).where (gh -> gh .parnt_ID ().isNull ().and (filter ));
179208 List <GenreHierarchy > roots = db .run (getRoots ).listOf (GenreHierarchy .class );
180209 roots .forEach (root -> {
181210 root .setDistanceFromRoot (0l );
182211 lookup .put (root .getId (), root );
183212 List <Integer > parents = List .of (root .getId ());
184213 for (long i = 1 ; i < limit ; i ++) {
185214 List <Integer > ps = parents ;
186- CqnSelect getChildren = Select .from (AdminService_ .GENRE_HIERARCHY ).where (gh -> gh .parnt_ID ().in (ps ).and (filter ));
215+ CqnSelect getChildren = Select .from (GENRE_HIERARCHY )
216+ .where (gh -> gh .parnt_ID ().in (ps ).and (filter ));
187217 List <GenreHierarchy > children = db .run (getChildren ).listOf (GenreHierarchy .class );
188218 if (children .isEmpty ()) {
189219 break ;
@@ -201,13 +231,10 @@ private List<GenreHierarchy> topLevelsLimit(long limit, CqnPredicate filter) {
201231 }
202232
203233 private List <GenreHierarchy > topLevelsAll (CqnPredicate filter ) {
204- Map <Integer , GenreHierarchy > lookup = new HashMap <>();
205-
206- CqnSelect allCqn = Select .from (AdminService_ .GENRE_HIERARCHY ).where (filter );
234+ CqnSelect allCqn = Select .from (GENRE_HIERARCHY ).where (filter );
207235 var all = db .run (allCqn ).listOf (GenreHierarchy .class );
208- all .forEach (gh -> lookup .put (gh .getId (), gh ));
209- all .forEach (gh -> gh .setParnt (lookup .get (gh .getParntId ())));
210- all .forEach (gh -> gh .setDistanceFromRoot (distanceFromRoot (gh )));
236+
237+ connect (all );
211238
212239 return all .stream ().sorted (new Sorter ()).toList ();
213240 }
@@ -241,14 +268,14 @@ public int compare(GenreHierarchy gh1, GenreHierarchy gh2) {
241268 return res ;
242269 }
243270
244- Deque <String > getPath (GenreHierarchy gh ){
271+ Deque <String > getPath (GenreHierarchy gh ) {
245272 Deque <String > path = new ArrayDeque <>();
246273 do {
247274 path .push (gh .getName ());
248275 gh = gh .getParnt ();
249- } while (gh != null );
276+ } while (gh != null );
250277
251278 return path ;
252- }
279+ }
253280 }
254281}
0 commit comments