Skip to content

Package: EntityCache

EntityCache

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