Skip to content

Package: EntityCache

EntityCache

nameinstructionbranchcomplexitylinemethod
EntityCache()
M: 0 C: 24
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
contains(Class, Object, Descriptor)
M: 16 C: 63
80%
M: 4 C: 12
75%
M: 4 C: 5
56%
M: 0 C: 15
100%
M: 0 C: 1
100%
evict(Class)
M: 23 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
evict(Class, Object, URI)
M: 8 C: 27
77%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 0 C: 7
100%
M: 0 C: 1
100%
evict(URI)
M: 3 C: 20
87%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 6
86%
M: 0 C: 1
100%
get(Class, Object, Descriptor)
M: 7 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getInternal(Class, Object, Descriptor, Consumer)
M: 8 C: 56
88%
M: 2 C: 10
83%
M: 2 C: 5
71%
M: 0 C: 12
100%
M: 0 C: 1
100%
getMapForId(URI, Object)
M: 4 C: 29
88%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 6
100%
M: 0 C: 1
100%
isCacheable(Descriptor)
M: 0 C: 9
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$evict$1(Map)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$evict$2(Class, Object, Map)
M: 16 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
lambda$get$0(URI)
M: 1 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
put(Object, Object, Descriptor)
M: 12 C: 85
88%
M: 3 C: 9
75%
M: 3 C: 4
57%
M: 0 C: 18
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2022 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.sessions.cache;
16:
17: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
18:
19: import java.net.URI;
20: import java.util.*;
21: import java.util.function.Consumer;
22:
23: class EntityCache {
24:
25: // TODO Think about locking on context level, so that the whole cache doesn't have to be locked when being accessed
26:
27: private static final String DEFAULT_CONTEXT_BASE = "http://defaultContext";
28:
29: final Map<URI, Map<Object, Map<Class<?>, Object>>> repoCache;
30: final Map<Object, Descriptor> descriptors;
31: final URI defaultContext;
32:
33: EntityCache() {
34: repoCache = new HashMap<>();
35: this.descriptors =
36: new IdentityHashMap<>(); // Need to use identity to cope with entities overriding equals/hashcode
37: this.defaultContext = URI.create(DEFAULT_CONTEXT_BASE + System.currentTimeMillis());
38: }
39:
40: void put(Object identifier, Object entity, Descriptor descriptor) {
41:• assert identifier != null;
42:• assert entity != null;
43:• assert isCacheable(descriptor);
44:
45: final Class<?> cls = entity.getClass();
46: final URI ctx = descriptor.getSingleContext().orElse(defaultContext);
47:
48: Map<Object, Map<Class<?>, Object>> ctxMap;
49:• if (!repoCache.containsKey(ctx)) {
50: ctxMap = new HashMap<>();
51: repoCache.put(ctx, ctxMap);
52: } else {
53: ctxMap = repoCache.get(ctx);
54: }
55: Map<Class<?>, Object> individualMap;
56:• if (!ctxMap.containsKey(identifier)) {
57: individualMap = new HashMap<>();
58: ctxMap.put(identifier, individualMap);
59: } else {
60: individualMap = ctxMap.get(identifier);
61: }
62:• if (individualMap.containsKey(cls)) {
63: descriptors.remove(individualMap.get(cls));
64: }
65: individualMap.put(cls, entity);
66: descriptors.put(entity, descriptor);
67: }
68:
69: boolean isCacheable(Descriptor descriptor) {
70:• return descriptor.getContexts().size() <= 1;
71: }
72:
73: <T> T get(Class<T> cls, Object identifier, Descriptor descriptor) {
74: return getInternal(cls, identifier, descriptor, u -> {});
75: }
76:
77: <T> T getInternal(Class<T> cls, Object identifier, Descriptor descriptor, Consumer<URI> contextHandler) {
78:• assert cls != null;
79:• assert identifier != null;
80:
81: final Set<URI> contexts =
82:• descriptor.getContexts().isEmpty() ? Collections.singleton(defaultContext) : descriptor.getContexts();
83:• for (URI ctx : contexts) {
84: final Map<Class<?>, Object> m = getMapForId(ctx, identifier);
85: final Object result = m.get(cls);
86:• if (result != null && descriptors.get(result).equals(descriptor)) {
87: contextHandler.accept(ctx);
88: return cls.cast(result);
89: }
90: }
91: return null;
92: }
93:
94: boolean contains(Class<?> cls, Object identifier, Descriptor descriptor) {
95:• assert cls != null;
96:• assert identifier != null;
97:• assert descriptor != null;
98:
99: final Set<URI> contexts =
100:• descriptor.getContexts().isEmpty() ? Collections.singleton(defaultContext) : descriptor.getContexts();
101:• for (URI ctx : contexts) {
102: final Map<Class<?>, Object> m = getMapForId(ctx, identifier);
103:• if (!m.containsKey(cls)) {
104: continue;
105: }
106: final Object result = m.get(cls);
107:• assert descriptors.containsKey(result);
108:
109:• if (descriptors.get(result).equals(descriptor)) {
110: return true;
111: }
112: }
113: return false;
114: }
115:
116: void evict(Class<?> cls, Object identifier, URI context) {
117:• assert cls != null;
118:• assert identifier != null;
119:
120: final Map<Class<?>, Object> m = getMapForId(context, identifier);
121:• if (m.containsKey(cls)) {
122: descriptors.remove(m.get(cls));
123: }
124: m.remove(cls);
125: }
126:
127: void evict(URI context) {
128:• if (context == null) {
129: context = defaultContext;
130: }
131:• if (!repoCache.containsKey(context)) {
132: return;
133: }
134: final Map<Object, Map<Class<?>, Object>> contextCache = repoCache.remove(context);
135: contextCache.values().forEach(instances -> instances.values().forEach(descriptors::remove));
136: }
137:
138: void evict(Class<?> cls) {
139:• for (Map.Entry<URI, Map<Object, Map<Class<?>, Object>>> e : repoCache.entrySet()) {
140: final Map<Object, Map<Class<?>, Object>> m = e.getValue();
141: m.forEach((key, value) -> {
142:• if (value.containsKey(cls)) {
143: descriptors.remove(value.get(cls));
144: value.remove(cls);
145: }
146: });
147: }
148: }
149:
150: private Map<Class<?>, Object> getMapForId(URI context, Object identifier) {
151:• assert identifier != null;
152:
153:• final URI ctx = context != null ? context : defaultContext;
154:
155:• if (!repoCache.containsKey(ctx)) {
156: return Collections.emptyMap();
157: }
158: final Map<Object, Map<Class<?>, Object>> ctxMap = repoCache.get(ctx);
159: return ctxMap.getOrDefault(identifier, Collections.emptyMap());
160: }
161: }