-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathLookupValuesProperty.java
141 lines (123 loc) · 5.23 KB
/
LookupValuesProperty.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* 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.codelists;
import sirius.db.mixing.AccessPath;
import sirius.db.mixing.BaseEntity;
import sirius.db.mixing.EntityDescriptor;
import sirius.db.mixing.Mapping;
import sirius.db.mixing.Mixing;
import sirius.db.mixing.Property;
import sirius.db.mixing.PropertyFactory;
import sirius.db.mixing.properties.StringListProperty;
import sirius.kernel.commons.Explain;
import sirius.kernel.commons.Value;
import sirius.kernel.di.std.Register;
import sirius.kernel.health.Exceptions;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* Provides the property used to handle {@link LookupValues lookup values} in database entities.
*/
public class LookupValuesProperty extends StringListProperty {
private LookupValues referenceValues;
/**
* Factory for generating properties based on their field type
*/
@Register
public static class Factory implements PropertyFactory {
@Override
public boolean accepts(EntityDescriptor descriptor, Field field) {
return LookupValues.class.equals(field.getType());
}
@Override
public void create(EntityDescriptor descriptor,
AccessPath accessPath,
Field field,
Consumer<Property> propertyConsumer) {
if (!Modifier.isFinal(field.getModifiers())) {
Mixing.LOG.WARN("Field %s in %s is not final! This will probably result in errors.",
field.getName(),
field.getDeclaringClass().getName());
}
propertyConsumer.accept(new LookupValuesProperty(descriptor, accessPath, field));
}
}
protected LookupValuesProperty(EntityDescriptor descriptor, AccessPath accessPath, Field field) {
super(descriptor, accessPath, field);
}
@Override
protected void link() {
referenceValues = getLookupValues(descriptor.getReferenceInstance());
}
public LookupValues getReferenceValues() {
return referenceValues;
}
/**
* Bypasses {@link StringListProperty#getValueFromField(java.lang.Object)} to access the actual LookupValues entity.
*
* @param entity the target object determined by the access path
* @return the corresponding {@link LookupValues} object determined by the access path
* @see Property#getValueFromField(java.lang.Object)
*/
protected LookupValues getLookupValues(Object entity) {
Object target = accessPath.apply(entity);
try {
return (LookupValues) field.get(target);
} catch (IllegalAccessException exception) {
throw Exceptions.handle()
.to(Mixing.LOG)
.error(exception)
.withSystemErrorMessage("Cannot read property '%s' (from '%s'): %s (%s)",
getName(),
getDefinition())
.handle();
}
}
@Override
public String getValueForUserMessage(Object entity) {
LookupValues lookupValues = getLookupValues(entity);
return lookupValues.data()
.stream()
.map(value -> lookupValues.getTable().resolveName(value).orElse(value))
.collect(Collectors.joining(", "));
}
@Override
@SuppressWarnings("java:S6204")
@Explain("We probably want a mutable list in the field as this is expected by a caller of the getter")
public void onBeforeSaveChecks(Object entity) {
if (((BaseEntity<?>) entity).isChanged(Mapping.named(getName()))) {
LookupValues lookupValues = getLookupValues(entity);
List<String> normalizedValues = lookupValues.data().stream().map(value -> {
Optional<String> normalizedValue = referenceValues.getTable().normalize(value);
if (normalizedValue.isPresent()) {
return normalizedValue.get();
} else if (referenceValues.getCustomValues() == LookupValue.CustomValues.REJECT) {
throw illegalFieldValue(Value.of(value));
} else {
return value;
}
}).collect(Collectors.toList());
lookupValues.setData(normalizedValues);
}
super.onBeforeSaveChecks(entity);
}
@Override
@SuppressWarnings({"unchecked", "java:S6204"})
@Explain("We probably want a mutable list in the field as this is expected by a caller of the getter")
protected Object transformValueFromImport(Value value) {
LookupTable table = referenceValues.getTable();
List<String> values = (List<String>) super.transformValueFromImport(value);
return values.stream()
.map(importValue -> table.normalizeInput(importValue).orElse(importValue))
.collect(Collectors.toList());
}
}