Skip to content

Commit 9fae6b9

Browse files
committed
update sort parameter
1 parent 23ce021 commit 9fae6b9

1 file changed

Lines changed: 173 additions & 6 deletions

File tree

src/main/java/it/aboutbits/springboot/toolbox/parameter/SortParameter.java

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,36 @@
99
import java.util.stream.Collectors;
1010
import java.util.stream.Stream;
1111

12+
/**
13+
* Represents sorting parameters for data retrieval and manipulation.
14+
* This class provides methods for creating, customizing, and applying sorting criteria
15+
* based on enum constants and associated sort properties. Sorting criteria can be defined
16+
* with various configurations, including direction and null-handling behavior.
17+
*/
1218
public record SortParameter<T extends Enum<?> & SortParameter.Definition>(List<SortField> sortFields) {
1319
private static final String DEFAULT_SORT_PROPERTY = "id";
14-
private static final Sort DEFAULT_SORT = Sort.by(
15-
Sort.Direction.ASC,
16-
DEFAULT_SORT_PROPERTY
17-
);
20+
private static final Sort.Direction DEFAULT_SORT_DIRETION = Sort.Direction.ASC;
1821

22+
/**
23+
* Creates a {@link SortParameter} that represents an unsorted state.
24+
*
25+
* @param <T> a type that extends both {@link Enum} and {@link Definition}.
26+
* @return an instance of {@link SortParameter} configured with no sorting fields.
27+
*/
1928
public static <T extends Enum<?> & Definition> SortParameter<T> unsorted() {
2029
return new SortParameter<>(Collections.emptyList());
2130
}
2231

32+
/**
33+
* Creates a {@link SortParameter} initialized with the provided sort definitions.
34+
* Each provided enum constant is converted into a {@link SortField} with ascending
35+
* order direction and default null-handling behavior. This method allows the
36+
* specification of multiple sorting criteria.
37+
*
38+
* @param <T> a type parameter representing an enum that implements the {@link Definition} interface.
39+
* @param sortDefinitions an array of enum constants defining the sort properties. Must not be null.
40+
* @return a {@link SortParameter} instance configured with the given sort definitions.
41+
*/
2342
@SafeVarargs
2443
public static <T extends Enum<?> & Definition> SortParameter<T> by(
2544
@NonNull T... sortDefinitions
@@ -36,6 +55,42 @@ public static <T extends Enum<?> & Definition> SortParameter<T> by(
3655
);
3756
}
3857

58+
/**
59+
* Creates a {@link SortParameter} initialized with a single sort definition.
60+
* This method allows specifying the property to sort by, the direction of sorting,
61+
* and uses the default null-handling behavior ({@link Sort.NullHandling#NATIVE}).
62+
*
63+
* @param <T> a type that extends both {@link Enum} and {@link Definition}.
64+
* @param sortDefinition an enum constant defining the property to sort by. Must not be null.
65+
* @param direction the direction of sorting, either {@link Sort.Direction#ASC} or {@link Sort.Direction#DESC}.
66+
* Must not be null.
67+
* @return an instance of {@link SortParameter} configured with the given sort definition and direction.
68+
*/
69+
public static <T extends Enum<?> & Definition> SortParameter<T> by(
70+
@NonNull T sortDefinition,
71+
@NonNull Sort.Direction direction
72+
) {
73+
return new SortParameter<>(
74+
List.of(new SortField(
75+
sortDefinition.name(),
76+
direction,
77+
Sort.NullHandling.NATIVE
78+
)
79+
)
80+
);
81+
}
82+
83+
/**
84+
* Creates a {@link SortParameter} instance configured with a single sort definition.
85+
* This method allows specifying the property to sort by, the direction of sorting,
86+
* and null-handling behavior.
87+
*
88+
* @param <T> the type parameter extending both {@link Enum} and {@link Definition}.
89+
* @param sortDefinition an enum constant defining the property to sort by. Must not be null.
90+
* @param direction the direction of sorting, either {@link Sort.Direction#ASC} or {@link Sort.Direction#DESC}. Must not be null.
91+
* @param nullHandling the strategy for handling null values during sorting, specified by {@link Sort.NullHandling}. Must not be null.
92+
* @return an instance of {@link SortParameter} configured with the given sort definition, direction, and null-handling behavior.
93+
*/
3994
public static <T extends Enum<?> & Definition> SortParameter<T> by(
4095
@NonNull T sortDefinition,
4196
@NonNull Sort.Direction direction,
@@ -51,10 +106,105 @@ public static <T extends Enum<?> & Definition> SortParameter<T> by(
51106
);
52107
}
53108

109+
/**
110+
* Adds additional sorting criteria to the existing {@link SortParameter}.
111+
* Each provided enum constant is converted into a {@link SortField} with ascending
112+
* order direction and default null-handling behavior.
113+
*
114+
* @param sortDefinitions an array of enum constants defining the additional sort properties. Must not be null.
115+
* @return the updated {@link SortParameter} instance containing the new sort definitions.
116+
*/
117+
@SafeVarargs
118+
public final SortParameter<T> and(
119+
@NonNull T... sortDefinitions
120+
) {
121+
sortFields.addAll(
122+
Stream.of(sortDefinitions)
123+
.map(sortDefinition -> new SortField(
124+
sortDefinition.name(),
125+
Sort.Direction.ASC,
126+
Sort.NullHandling.NATIVE
127+
)
128+
)
129+
.toList()
130+
);
131+
132+
return this;
133+
}
134+
135+
/**
136+
* Adds a sorting criterion to the current {@link SortParameter} instance.
137+
* The provided sort definition and direction are converted into a {@link SortField}
138+
* with default null-handling behavior and appended to the existing sort fields.
139+
*
140+
* @param sortDefinition the enum constant defining the property to sort by. Must not be null.
141+
* @param direction the direction of sorting, either {@link Sort.Direction#ASC} or {@link Sort.Direction#DESC}. Must not be null.
142+
* @return the updated {@link SortParameter} instance containing the new sorting criterion.
143+
*/
144+
public SortParameter<T> and(
145+
@NonNull T sortDefinition,
146+
@NonNull Sort.Direction direction
147+
) {
148+
sortFields.add(
149+
new SortField(
150+
sortDefinition.name(),
151+
direction,
152+
Sort.NullHandling.NATIVE
153+
)
154+
);
155+
156+
return this;
157+
}
158+
159+
/**
160+
* Adds a sorting criterion to the current {@link SortParameter} instance. The provided sort definition,
161+
* direction, and null-handling behavior are converted into a {@link SortField} and appended to the
162+
* existing sort fields.
163+
*
164+
* @param sortDefinition the enum constant defining the property to sort by. Must not be null.
165+
* @param direction the direction of sorting, either {@link Sort.Direction#ASC} or {@link Sort.Direction#DESC}. Must not be null.
166+
* @param nullHandling the strategy for handling null values during sorting, specified by {@link Sort.NullHandling}. Must not be null.
167+
* @return the updated {@link SortParameter} instance containing the new sorting criterion.
168+
*/
169+
public SortParameter<T> and(
170+
@NonNull T sortDefinition,
171+
@NonNull Sort.Direction direction,
172+
@NonNull Sort.NullHandling nullHandling
173+
) {
174+
sortFields.add(
175+
new SortField(
176+
sortDefinition.name(),
177+
direction,
178+
nullHandling
179+
)
180+
);
181+
182+
return this;
183+
}
184+
185+
/**
186+
* Returns the current {@link SortParameter} instance if it has defined sorting fields.
187+
* Otherwise, returns the provided fallback {@link SortParameter}.
188+
*
189+
* @param fallback the {@link SortParameter} to use as a fallback in case the current instance
190+
* has no defined sorting fields. Must not be null.
191+
* @return the current {@link SortParameter} if it has defined sorting fields,
192+
* or the provided fallback if it does not.
193+
*/
54194
public SortParameter<T> or(@NonNull SortParameter<T> fallback) {
55195
return sortFields == null || sortFields.isEmpty() ? fallback : this;
56196
}
57197

198+
/**
199+
* Builds a {@link Sort} object without applying any default sorting parameters. Converts the enum keys
200+
* of the provided map to their string names and generates the sort object.
201+
*
202+
* @param mapping a non-null map where the keys are enumeration values representing sort properties
203+
* and the values are their associated sort directions. The enumeration keys must
204+
* have a `name()` method for string conversion. Must not be null.
205+
* @return an instance of {@link Sort} created using the transformed key-value mapping,
206+
* excluding default sorting behavior.
207+
*/
58208
public Sort buildSortWithoutDefault(@NonNull Map<T, String> mapping) {
59209
var stringMapping = mapping.entrySet().stream()
60210
.collect(Collectors.toMap(
@@ -65,6 +215,16 @@ public Sort buildSortWithoutDefault(@NonNull Map<T, String> mapping) {
65215
return buildSort(stringMapping, false);
66216
}
67217

218+
/**
219+
* Builds a {@link Sort} object based on the provided mapping of enumeration values to string properties.
220+
* Converts enum keys to their respective string names and generates the sort object.
221+
* <p>
222+
* If a sort mapping for "id" is provided, it will be used as the default sort property. Unless specified, this sort will be applied last.
223+
*
224+
* @param mapping a non-null map where the keys represent enumeration values and the values represent sort property names.
225+
* The enumeration keys must implement the `name()` method to retrieve their string representation.
226+
* @return an instance of {@link Sort} created using the transformed key-value mapping with default sorting behavior.
227+
*/
68228
public Sort buildSort(@NonNull Map<T, String> mapping) {
69229
var stringMapping = mapping.entrySet().stream()
70230
.collect(Collectors.toMap(
@@ -79,7 +239,7 @@ public Sort buildSort(@NonNull Map<T, String> mapping) {
79239
@SuppressWarnings("java:S6204")
80240
private Sort buildSort(@NonNull Map<String, String> mapping, boolean withDefault) {
81241
if (sortFields == null || sortFields.isEmpty()) {
82-
return withDefault ? DEFAULT_SORT : Sort.unsorted();
242+
return withDefault ? getMappedDefaultSort(mapping) : Sort.unsorted();
83243
}
84244

85245
var additionalSort = Sort.by(
@@ -97,19 +257,26 @@ private Sort buildSort(@NonNull Map<String, String> mapping, boolean withDefault
97257
if (withDefault) {
98258
var includesDefault = additionalSort.getOrderFor(DEFAULT_SORT_PROPERTY) != null;
99259
if (!includesDefault) {
100-
return additionalSort.and(DEFAULT_SORT);
260+
return additionalSort.and(getMappedDefaultSort(mapping));
101261
}
102262
}
103263
return additionalSort;
104264
}
105265

266+
private static Sort getMappedDefaultSort(Map<String, String> mapping) {
267+
return Sort.by(DEFAULT_SORT_DIRETION, mapping.getOrDefault(DEFAULT_SORT_PROPERTY, DEFAULT_SORT_PROPERTY));
268+
}
269+
106270
public record SortField(
107271
@NonNull String property,
108272
@NonNull Sort.Direction direction,
109273
@NonNull Sort.NullHandling nullHandling
110274
) {
111275
}
112276

277+
/**
278+
* Interface to give enums the purpose of listing sortable keys.
279+
*/
113280
public interface Definition {
114281
}
115282
}

0 commit comments

Comments
 (0)