-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathFieldLookupCache.java
139 lines (125 loc) · 4.99 KB
/
FieldLookupCache.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
/*
* 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.db.mixing;
import sirius.db.mixing.types.BaseEntityRef;
import sirius.kernel.cache.Cache;
import sirius.kernel.cache.CacheManager;
import sirius.kernel.commons.Strings;
import sirius.kernel.commons.Value;
import sirius.kernel.di.std.Part;
import sirius.kernel.di.std.Register;
import sirius.kernel.health.Exceptions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Provides a global cache for field values.
* <p>
* This can be used to quickly resolve IDs into names / label when rendering tables of items.
* Note that the cache isn't invalidated automatically but rather short lived.
*/
@Register(classes = FieldLookupCache.class)
public class FieldLookupCache {
private Cache<String, Value> cache = CacheManager.createLocalCache("mixing-field-lookup");
@Part
private Mixing mixing;
private <E extends BaseEntity<?>> Value load(Class<E> type, @Nullable Object id, Mapping field) throws Exception {
return mixing.getDescriptor(type).getMapper().fetchField(type, id, field);
}
/**
* Provides the value of the given entity and field.
* <p>
* Note that this gracefully handles both, empty IDs as well as IDs of nonexistent entities by simply returning
* an empty value.
*
* @param type the type of the entity to resolve
* @param id the id of the entity to resolve
* @param field the field to resolve
* @param <E> the generic type of the entitiy
* @return the value of the field or an empty value if either the field is empty or the given ID was <tt>null</tt>
*/
public <E extends BaseEntity<?>> Value lookup(Class<E> type, Object id, Mapping field) {
if (Strings.isEmpty(id)) {
return Value.EMPTY;
}
try {
String cacheKey = getCacheKey(type, id, field);
Value result = cache.get(cacheKey);
if (result == null) {
result = load(type, id, field);
cache.put(cacheKey, result);
}
return result;
} catch (Exception e) {
Exceptions.handle()
.to(Mixing.LOG)
.error(e)
.withSystemErrorMessage(
"An error occurred when performing a lookup on field %s for entity %s of type %s: %s (%s)",
field,
id,
type)
.handle();
return Value.EMPTY;
}
}
/**
* Provides the cache key of the given entity and field.
*
* @param type the type of the entity to resolve
* @param id the id of the entity to resolve
* @param field the field to resolve
* @param <E> the generic type of the entitiy
* @return the value of the cache key or an empty string if either the field is empty or the given ID was <tt>null</tt>
*/
@Nonnull
public <E extends BaseEntity<?>> String getCacheKey(Class<E> type, Object id, Mapping field) {
return Mixing.getUniqueName(type, id) + "-" + field;
}
/**
* Provides the value of the given entity and field.
*
* @param type the type of the entity to resolve
* @param id the id of the entity to resolve
* @param field the field to resolve
* @param <E> the generic type of the entitiy
* @return the value of the field or an empty value if either the field is empty or the given ID was <tt>null</tt>
*/
public <E extends BaseEntity<?>> Value lookup(Class<E> type, Object id, String field) {
return lookup(type, id, Mapping.named(field));
}
/**
* Provides the value of the field for the entity in the given reference.
*
* @param ref the reference which points to the entity to resolve
* @param field the field to resolve
* @param <E> the generic type of the entitiy
* @return the value of the field or an empty value if either the field is empty or if the given reference was empty
*/
public <E extends BaseEntity<?>> Value lookup(BaseEntityRef<?, E> ref, String field) {
return lookup(ref.getType(), ref.getId(), field);
}
/**
* Provides the value of the field for the entity in the given reference.
*
* @param ref the reference which points to the entity to resolve
* @param field the field to resolve
* @param <E> the generic type of the entitiy
* @return the value of the field or an empty value if either the field is empty or if the given reference was empty
*/
public <E extends BaseEntity<?>> Value lookup(BaseEntityRef<?, E> ref, Mapping field) {
return lookup(ref.getType(), ref.getId(), field);
}
/**
* Provides the value of cache.
*
* @return the value of cache
*/
private Cache<String, Value> getCache(){
return cache;
}
}