-
Notifications
You must be signed in to change notification settings - Fork 7
/
SortField.java
114 lines (98 loc) · 3.82 KB
/
SortField.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - [email protected]
*/
package sirius.biz.mongo;
import sirius.biz.protocol.NoJournal;
import sirius.db.mixing.Composite;
import sirius.db.mixing.Mapping;
import sirius.db.mixing.annotations.BeforeSave;
import sirius.db.mixing.annotations.NullAllowed;
import sirius.db.mixing.annotations.Transient;
import sirius.db.mongo.MongoEntity;
import sirius.kernel.commons.Explain;
import sirius.kernel.commons.Monoflop;
import sirius.kernel.commons.StringCleanup;
import sirius.kernel.commons.Strings;
import sirius.kernel.nls.NLS;
import java.util.Comparator;
import java.util.stream.Collectors;
/**
* Provides a container composite to be used in MongoDB entities which can be used for sorting.
* <p>
* As MongoDB doesn't sort values properly (as we use it without collations), we use a normalized sort field here.
* This field is populated with all values which are marked with {@link SortValue}.
*/
public class SortField extends Composite {
/**
* Contains the effective field to sort by.
*/
public static final Mapping SORT_FIELD = Mapping.named("sortField");
@SuppressWarnings("java:S1700")
@Explain("We actually do want the same name here.")
@NoJournal
@NullAllowed
private String sortField;
@Transient
private final MongoEntity owner;
/**
* Creates a sort field for the given entity.
*
* @param owner the owning entity which contains the sort field
*/
public SortField(MongoEntity owner) {
this.owner = owner;
}
/**
* Normalizes the given text using {@link StringCleanup#reduceCharacters(String)}, lower-casing it after.
*
* @param text the text to normalize
* @return the normalized text in lower-case
*/
public static String normalizeText(String text) {
if (Strings.isEmpty(text)) {
return text;
}
return Strings.cleanup(text, StringCleanup::reduceCharacters, StringCleanup::lowercase);
}
@BeforeSave
protected void fillSortField() {
if (owner.is(CustomSortValues.class)) {
fillUsingCustomSortValues();
} else {
fillUsingAnnotations();
}
}
private void fillUsingAnnotations() {
String sortFieldContents = owner.getDescriptor()
.getProperties()
.stream()
.filter(property -> property.isAnnotationPresent(SortValue.class))
.sorted(Comparator.comparing(property -> property.getAnnotation(SortValue.class)
.map(SortValue::order)
.orElse(99)))
.map(property -> property.getValue(owner))
.map(NLS::toUserString)
.collect(Collectors.joining(" "));
this.sortField = Strings.cleanup(sortFieldContents, StringCleanup::reduceCharacters, StringCleanup::lowercase);
}
private void fillUsingCustomSortValues() {
StringBuilder sortFieldContents = new StringBuilder();
Monoflop monoflop = Monoflop.create();
owner.as(CustomSortValues.class).emitSortValues(value -> {
if (monoflop.successiveCall()) {
sortFieldContents.append(" ");
}
if (value != null) {
sortFieldContents.append(NLS.toUserString(value));
}
});
this.sortField = normalizeText(sortFieldContents.toString());
}
public String getSortField() {
return sortField;
}
}