@@ -48,9 +48,34 @@ public static <T> DataSourceResult toDataSourceResult(List<T> data, DataSourceRe
4848 // Get total count after filtering (before paging)
4949 long total = filteredData .size ();
5050
51- // Apply sorting
51+ // Apply sorting - need to combine group sorting with regular sorting
52+ List <SortDescriptor > sortDescriptors = new ArrayList <>();
53+
54+ // First, add sorts from group descriptors (groups take precedence)
55+ if (request .getGroup () != null && !request .getGroup ().isEmpty ()) {
56+ for (GroupDescriptor group : request .getGroup ()) {
57+ SortDescriptor sort = new SortDescriptor ();
58+ sort .setField (group .getField ());
59+ // Use group's dir if specified, otherwise default to ascending
60+ sort .setDir (group .getDir () != null && !group .getDir ().isEmpty () ? group .getDir () : "asc" );
61+ sortDescriptors .add (sort );
62+ }
63+ }
64+
65+ // Then add regular sort descriptors (if they don't conflict with group sorting)
5266 if (request .getSort () != null && !request .getSort ().isEmpty ()) {
53- filteredData = applySort (filteredData , request .getSort ());
67+ for (SortDescriptor sort : request .getSort ()) {
68+ boolean alreadySorted = sortDescriptors .stream ()
69+ .anyMatch (s -> s .getField ().equals (sort .getField ()));
70+ if (!alreadySorted ) {
71+ sortDescriptors .add (sort );
72+ }
73+ }
74+ }
75+
76+ // Apply the combined sorting
77+ if (!sortDescriptors .isEmpty ()) {
78+ filteredData = applySort (filteredData , sortDescriptors );
5479 }
5580
5681 // Apply grouping (grouping should NOT be affected by paging unless groupPaging is enabled)
@@ -471,14 +496,16 @@ private static <T> List<GroupResult> applyGrouping(List<T> data, List<GroupDescr
471496 }
472497
473498 GroupDescriptor currentGroup = groupDescriptors .get (level );
499+
500+ // Use LinkedHashMap to preserve insertion order (data is already sorted)
474501 Map <Object , List <T >> grouped = data .stream ()
475502 .collect (Collectors .groupingBy (item -> {
476503 try {
477504 return getFieldValue (item , currentGroup .getField ());
478505 } catch (Exception e ) {
479506 return null ;
480507 }
481- }));
508+ }, LinkedHashMap :: new , Collectors . toList () ));
482509
483510 List <GroupResult > results = new ArrayList <>();
484511 boolean hasMoreGroups = level + 1 < groupDescriptors .size ();
@@ -489,22 +516,21 @@ private static <T> List<GroupResult> applyGrouping(List<T> data, List<GroupDescr
489516 groupResult .setValue (entry .getKey ());
490517
491518 if (hasMoreGroups ) {
492- // Recursively group
519+ // Recursively group nested levels
493520 List <GroupResult > subGroups = applyGrouping (entry .getValue (), groupDescriptors , level + 1 );
494521 groupResult .setItems (subGroups );
495522 groupResult .setHasSubgroups (true );
496- // Count total items in all subgroups
497523 int totalItems = subGroups .stream ()
498524 .mapToInt (g -> g .getItemCount () != null ? g .getItemCount () : 0 )
499525 .sum ();
500526 groupResult .setItemCount (totalItems );
501527 } else {
528+ // Leaf level - store the actual items
502529 groupResult .setItems (entry .getValue ());
503530 groupResult .setHasSubgroups (false );
504531 groupResult .setItemCount (entry .getValue ().size ());
505532 }
506533
507- // Calculate aggregates for this group
508534 if (currentGroup .getAggregates () != null && !currentGroup .getAggregates ().isEmpty ()) {
509535 List <AggregateDescriptor > aggregateDescriptors = currentGroup .getAggregates ().stream ()
510536 .map (af -> {
0 commit comments