Skip to content

Package: EntityInstanceLoader

EntityInstanceLoader

nameinstructionbranchcomplexitylinemethod
EntityInstanceLoader(EntityInstanceLoader.EntityInstanceLoaderBuilder)
M: 20 C: 47
70%
M: 5 C: 5
50%
M: 5 C: 1
17%
M: 0 C: 13
100%
M: 0 C: 1
100%
getLoadStatDescriptor(Object, EntityType)
M: 0 C: 13
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
isCached(LoadingParameters, EntityType)
M: 0 C: 17
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$loadCached$0(Pair)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$loadCached$1(Pair)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$recursivelyProcessCachedEntityReferences$2(Object, EntityType, Consumer)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$recursivelyProcessCachedEntityReferences$3(Map, List, Object)
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$recursivelyProcessCachedEntityReferences$4(Object, Map, List, Attribute)
M: 0 C: 45
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
loadCached(EntityType, URI, Descriptor)
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
loadInstance(LoadingParameters, IdentifiableEntityType)
M: 6 C: 52
90%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 2 C: 10
83%
M: 0 C: 1
100%
recursivelyProcessCachedEntityReferences(Object, EntityType, Map, List)
M: 0 C: 27
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
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) 2024 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.oom;
19:
20: import cz.cvut.kbss.jopa.datatype.util.Pair;
21: import cz.cvut.kbss.jopa.exceptions.StorageAccessException;
22: import cz.cvut.kbss.jopa.model.MetamodelImpl;
23: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
24: import cz.cvut.kbss.jopa.model.metamodel.Attribute;
25: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
26: import cz.cvut.kbss.jopa.model.metamodel.IdentifiableEntityType;
27: import cz.cvut.kbss.jopa.model.metamodel.PluralAttribute;
28: import cz.cvut.kbss.jopa.oom.exception.EntityReconstructionException;
29: import cz.cvut.kbss.jopa.sessions.cache.CacheManager;
30: import cz.cvut.kbss.jopa.sessions.descriptor.LoadStateDescriptor;
31: import cz.cvut.kbss.jopa.sessions.descriptor.LoadStateDescriptorFactory;
32: import cz.cvut.kbss.jopa.sessions.util.LoadStateDescriptorRegistry;
33: import cz.cvut.kbss.jopa.sessions.util.LoadingParameters;
34: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
35: import cz.cvut.kbss.ontodriver.Connection;
36: import cz.cvut.kbss.ontodriver.descriptor.AxiomDescriptor;
37: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
38: import cz.cvut.kbss.ontodriver.model.Axiom;
39:
40: import java.net.URI;
41: import java.util.Collection;
42: import java.util.IdentityHashMap;
43: import java.util.List;
44: import java.util.Map;
45: import java.util.Objects;
46: import java.util.function.Consumer;
47:
48: /**
49: * Root of the entity loading strategies.
50: */
51: abstract class EntityInstanceLoader {
52:
53: final Connection storageConnection;
54: final MetamodelImpl metamodel;
55:
56: final CacheManager cache;
57: private final AxiomDescriptorFactory descriptorFactory;
58: final EntityConstructor entityBuilder;
59:
60: final LoadStateDescriptorRegistry loadStateRegistry;
61:
62: EntityInstanceLoader(EntityInstanceLoaderBuilder builder) {
63:• assert builder.storageConnection != null;
64:• assert builder.metamodel != null;
65:• assert builder.cache != null;
66:• assert builder.descriptorFactory != null;
67:• assert builder.entityBuilder != null;
68:
69: this.storageConnection = builder.storageConnection;
70: this.metamodel = builder.metamodel;
71: this.cache = builder.cache;
72: this.descriptorFactory = builder.descriptorFactory;
73: this.entityBuilder = builder.entityBuilder;
74: this.loadStateRegistry = builder.loadStateRegistry;
75: }
76:
77: /**
78: * Loads entity based on the specified loading parameters.
79: *
80: * @param loadingParameters Instance loading parameters
81: * @return The loaded instance (possibly {@code null})
82: */
83: abstract <T> T loadEntity(LoadingParameters<T> loadingParameters);
84:
85: <U extends T, T> U loadInstance(LoadingParameters<T> loadingParameters, IdentifiableEntityType<U> et) {
86: final URI identifier = loadingParameters.getIdentifier();
87: final Descriptor descriptor = loadingParameters.getDescriptor();
88:• if (isCached(loadingParameters, et)) {
89: return loadCached(et, identifier, descriptor);
90: }
91: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForEntityLoading(loadingParameters, et);
92: try {
93: final Collection<Axiom<?>> axioms = storageConnection.find(axiomDescriptor);
94:• return axioms.isEmpty() ? null : entityBuilder.reconstructEntity(
95: new EntityConstructor.EntityConstructionParameters<>(identifier, et, descriptor, loadingParameters.isForceEager()),
96: axioms);
97: } catch (OntoDriverException e) {
98: throw new StorageAccessException(e);
99: } catch (cz.cvut.kbss.jopa.exception.InstantiationException e) {
100: throw new EntityReconstructionException(e);
101: }
102: }
103:
104: <T> boolean isCached(LoadingParameters<T> loadingParameters, EntityType<? extends T> et) {
105:• return !loadingParameters.shouldBypassCache() &&
106:• cache.contains(et.getJavaType(), loadingParameters.getIdentifier(), loadingParameters.getDescriptor());
107: }
108:
109: <T> T loadCached(EntityType<T> et, URI identifier, Descriptor descriptor) {
110: final T cached = cache.get(et.getJavaType(), identifier, descriptor);
111: recursivelyProcessCachedEntityReferences(cached, et, new IdentityHashMap<>(), List.of(
112: pair -> loadStateRegistry.put(pair.first(), getLoadStatDescriptor(pair.first(), pair.second())),
113: pair -> entityBuilder.populateQueryAttributes(pair.first(), (EntityType<Object>) pair.second())
114: ));
115: return cached;
116: }
117:
118: private LoadStateDescriptor<?> getLoadStatDescriptor(Object instance, EntityType<?> et) {
119: final LoadStateDescriptor<?> cached = cache.getLoadStateDescriptor(instance);
120:• if (cached != null) {
121: return cached;
122: }
123: return LoadStateDescriptorFactory.createAllUnknown(instance, (EntityType<Object>) et);
124: }
125:
126: private void recursivelyProcessCachedEntityReferences(Object instance, EntityType<?> et,
127: Map<Object, Object> visited,
128: List<Consumer<Pair<Object, EntityType<?>>>> handlers) {
129:• if (visited.containsKey(instance)) {
130: return;
131: }
132: visited.put(instance, null);
133: handlers.forEach(h -> h.accept(new Pair<>(instance, et)));
134: et.getAttributes().stream().filter(Attribute::isAssociation).forEach(att -> {
135:• final Class<?> cls = att.isCollection() ? ((PluralAttribute) att).getElementType()
136: .getJavaType() : att.getJavaType();
137:• if (!metamodel.isEntityType(cls)) {
138: return;
139: }
140: final Object value = EntityPropertiesUtils.getAttributeValue(att, instance);
141:• if (value != null) {
142: // Resolve the value class instead of using the attribute type, as it may be a subclass at runtime
143:• if (att.isCollection()) {
144: ((Collection<?>) value).forEach(el -> recursivelyProcessCachedEntityReferences(el, metamodel.entity(el.getClass()), visited, handlers));
145: } else {
146: recursivelyProcessCachedEntityReferences(value, metamodel.entity(value.getClass()), visited, handlers);
147: }
148: }
149: });
150: }
151:
152: abstract static class EntityInstanceLoaderBuilder {
153: private Connection storageConnection;
154: private MetamodelImpl metamodel;
155: private CacheManager cache;
156:
157: private AxiomDescriptorFactory descriptorFactory;
158: private EntityConstructor entityBuilder;
159:
160: private LoadStateDescriptorRegistry loadStateRegistry;
161:
162: EntityInstanceLoaderBuilder connection(Connection connection) {
163: this.storageConnection = Objects.requireNonNull(connection);
164: return this;
165: }
166:
167: EntityInstanceLoaderBuilder metamodel(MetamodelImpl metamodel) {
168: this.metamodel = metamodel;
169: return this;
170: }
171:
172: EntityInstanceLoaderBuilder descriptorFactory(AxiomDescriptorFactory factory) {
173: this.descriptorFactory = factory;
174: return this;
175: }
176:
177: EntityInstanceLoaderBuilder entityBuilder(EntityConstructor builder) {
178: this.entityBuilder = builder;
179: return this;
180: }
181:
182: EntityInstanceLoaderBuilder cache(CacheManager cache) {
183: this.cache = cache;
184: return this;
185: }
186:
187: EntityInstanceLoaderBuilder loadStateRegistry(LoadStateDescriptorRegistry loadStateRegistry) {
188: this.loadStateRegistry = loadStateRegistry;
189: return this;
190: }
191:
192: abstract EntityInstanceLoader build();
193: }
194: }