Skip to content

Package: ObjectOntologyMapperImpl

ObjectOntologyMapperImpl

nameinstructionbranchcomplexitylinemethod
ObjectOntologyMapperImpl(UnitOfWorkImpl, Connection)
M: 0 C: 88
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 17
100%
M: 0 C: 1
100%
checkForUnpersistedChanges()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
containsEntity(Class, URI, Descriptor)
M: 12 C: 43
78%
M: 3 C: 3
50%
M: 3 C: 1
25%
M: 0 C: 10
100%
M: 0 C: 1
100%
generateIdentifier(EntityType)
M: 6 C: 7
54%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 2 C: 1
33%
M: 0 C: 1
100%
getConfiguration()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getEntityFromCacheOrOntology(Class, URI, Descriptor)
M: 0 C: 50
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
getEntityType(Class)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getOriginalInstance(Object)
M: 4 C: 8
67%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 2
100%
M: 0 C: 1
100%
isManaged(Object)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
loadEntity(LoadingParameters)
M: 4 C: 10
71%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 3
100%
M: 0 C: 1
100%
loadEntityInternal(LoadingParameters)
M: 0 C: 31
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
loadFieldValue(Object, Field, Descriptor)
M: 18 C: 56
76%
M: 3 C: 5
63%
M: 3 C: 2
40%
M: 2 C: 15
88%
M: 0 C: 1
100%
loadReferencedList(ReferencedListDescriptor)
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
loadSimpleList(SimpleListDescriptor)
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
persistEntity(URI, Object, Descriptor)
M: 26 C: 50
66%
M: 3 C: 5
63%
M: 3 C: 2
40%
M: 2 C: 13
87%
M: 0 C: 1
100%
persistPendingReferences(Object, NamedResource)
M: 6 C: 88
94%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 2 C: 19
90%
M: 0 C: 1
100%
registerInstance(URI, Object, URI)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
registerPendingAssertion(NamedResource, Assertion, Object, URI)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
registerPendingListReference(Object, ListValueDescriptor, List)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
removeEntity(URI, Class, Descriptor)
M: 0 C: 34
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
removePendingAssertions(EntityType, Field, URI)
M: 0 C: 25
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: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
updateFieldValue(Object, Field, Descriptor)
M: 0 C: 35
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2016 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.oom;
16:
17: import cz.cvut.kbss.jopa.exceptions.StorageAccessException;
18: import cz.cvut.kbss.jopa.model.MetamodelImpl;
19: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
20: import cz.cvut.kbss.jopa.model.metamodel.Attribute;
21: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
22: import cz.cvut.kbss.jopa.model.metamodel.EntityTypeImpl;
23: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
24: import cz.cvut.kbss.jopa.oom.exceptions.EntityDeconstructionException;
25: import cz.cvut.kbss.jopa.oom.exceptions.EntityReconstructionException;
26: import cz.cvut.kbss.jopa.oom.exceptions.UnpersistedChangeException;
27: import cz.cvut.kbss.jopa.sessions.CacheManager;
28: import cz.cvut.kbss.jopa.sessions.LoadingParameters;
29: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
30: import cz.cvut.kbss.jopa.utils.Configuration;
31: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
32: import cz.cvut.kbss.ontodriver.Connection;
33: import cz.cvut.kbss.ontodriver.descriptor.*;
34: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
35: import cz.cvut.kbss.ontodriver.model.*;
36: import org.slf4j.Logger;
37: import org.slf4j.LoggerFactory;
38:
39: import java.lang.reflect.Field;
40: import java.net.URI;
41: import java.util.Collection;
42: import java.util.List;
43: import java.util.Objects;
44: import java.util.Set;
45:
46: public class ObjectOntologyMapperImpl implements ObjectOntologyMapper, EntityMappingHelper {
47:
48: private static final Logger LOG = LoggerFactory.getLogger(ObjectOntologyMapperImpl.class);
49:
50: private final UnitOfWorkImpl uow;
51: private final CacheManager cache;
52: private final Connection storageConnection;
53: private final MetamodelImpl metamodel;
54:
55: private final AxiomDescriptorFactory descriptorFactory;
56: private final EntityConstructor entityBuilder;
57: private final EntityDeconstructor entityBreaker;
58: private final InstanceRegistry instanceRegistry;
59: private final PendingReferenceRegistry pendingReferences;
60:
61: private final EntityInstanceLoader defaultInstanceLoader;
62: private final EntityInstanceLoader twoStepInstanceLoader;
63:
64: public ObjectOntologyMapperImpl(UnitOfWorkImpl uow, Connection connection) {
65: this.uow = Objects.requireNonNull(uow);
66: this.cache = uow.getLiveObjectCache();
67: this.storageConnection = Objects.requireNonNull(connection);
68: this.metamodel = uow.getMetamodel();
69: this.descriptorFactory = new AxiomDescriptorFactory(uow.getConfiguration());
70: this.instanceRegistry = new InstanceRegistry();
71: this.pendingReferences = new PendingReferenceRegistry();
72: this.entityBuilder = new EntityConstructor(this);
73: this.entityBreaker = new EntityDeconstructor(this);
74:
75: this.defaultInstanceLoader = DefaultInstanceLoader.builder().connection(storageConnection).metamodel(metamodel)
76: .descriptorFactory(descriptorFactory)
77: .entityBuilder(entityBuilder).cache(cache).build();
78: this.twoStepInstanceLoader = TwoStepInstanceLoader.builder().connection(storageConnection).metamodel(metamodel)
79: .descriptorFactory(descriptorFactory)
80: .entityBuilder(entityBuilder).cache(cache).build();
81: }
82:
83: @Override
84: public <T> boolean containsEntity(Class<T> cls, URI primaryKey, Descriptor descriptor) {
85:• assert cls != null;
86:• assert primaryKey != null;
87:• assert descriptor != null;
88:
89: final EntityType<T> et = getEntityType(cls);
90: final NamedResource classUri = NamedResource.create(et.getIRI().toURI());
91: final Axiom<NamedResource> ax = new AxiomImpl<>(NamedResource.create(primaryKey),
92: Assertion.createClassAssertion(false), new Value<>(classUri));
93: try {
94: return storageConnection.contains(ax, descriptor.getContext());
95: } catch (OntoDriverException e) {
96: throw new StorageAccessException(e);
97: }
98: }
99:
100: @Override
101: public <T> T loadEntity(LoadingParameters<T> loadingParameters) {
102:• assert loadingParameters != null;
103:
104: instanceRegistry.reset();
105: return loadEntityInternal(loadingParameters);
106: }
107:
108: private <T> T loadEntityInternal(LoadingParameters<T> loadingParameters) {
109: final EntityTypeImpl<T> et = getEntityType(loadingParameters.getEntityType());
110: final T result;
111:• if (et.hasSubtypes()) {
112: result = twoStepInstanceLoader.loadEntity(loadingParameters);
113: } else {
114: result = defaultInstanceLoader.loadEntity(loadingParameters);
115: }
116:• if (result != null) {
117: cache.add(loadingParameters.getIdentifier(), result, loadingParameters.getDescriptor());
118: }
119: return result;
120: }
121:
122: @Override
123: public <T> EntityTypeImpl<T> getEntityType(Class<T> cls) {
124: return metamodel.entity(cls);
125: }
126:
127: @Override
128: public <T> void loadFieldValue(T entity, Field field, Descriptor descriptor) {
129:• assert entity != null;
130:• assert field != null;
131:• assert descriptor != null;
132:
133: LOG.trace("Lazily loading value of field {} of entity {}.", field, entity);
134:
135: final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
136: final URI primaryKey = EntityPropertiesUtils.getIdentifier(entity, et);
137:
138: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForFieldLoading(primaryKey,
139: field, descriptor, et);
140: try {
141: final Collection<Axiom<?>> axioms = storageConnection.find(axiomDescriptor);
142:• if (axioms.isEmpty()) {
143: return;
144: }
145: entityBuilder.setFieldValue(entity, field, axioms, et, descriptor);
146: } catch (OntoDriverException e) {
147: throw new StorageAccessException(e);
148: } catch (IllegalArgumentException | IllegalAccessException e) {
149: throw new EntityReconstructionException(e);
150: }
151: }
152:
153: @Override
154: public <T> void persistEntity(URI primaryKey, T entity, Descriptor descriptor) {
155:• assert entity != null;
156:• assert descriptor != null;
157:
158: @SuppressWarnings("unchecked") final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
159: try {
160:• if (primaryKey == null) {
161: primaryKey = generateIdentifier(et);
162:• assert primaryKey != null;
163: EntityPropertiesUtils.setPrimaryKey(primaryKey, entity, et);
164: }
165: entityBreaker.setReferenceSavingResolver(new ReferenceSavingResolver(this));
166: final AxiomValueGatherer axiomBuilder = entityBreaker.mapEntityToAxioms(primaryKey, entity, et, descriptor);
167: axiomBuilder.persist(storageConnection);
168: persistPendingReferences(entity, axiomBuilder.getSubjectIdentifier());
169: } catch (IllegalArgumentException e) {
170: throw new EntityDeconstructionException("Unable to deconstruct entity " + entity, e);
171: }
172: }
173:
174: @Override
175: public URI generateIdentifier(EntityType<?> et) {
176: try {
177: return storageConnection.generateIdentifier(et.getIRI().toURI());
178: } catch (OntoDriverException e) {
179: throw new StorageAccessException(e);
180: }
181: }
182:
183: private <T> void persistPendingReferences(T instance, NamedResource identifier) {
184: try {
185: final Set<PendingAssertion> pas = pendingReferences.removeAndGetPendingAssertionsWith(instance);
186:• for (PendingAssertion pa : pas) {
187: final AxiomValueDescriptor desc = new AxiomValueDescriptor(pa.getOwner());
188: desc.addAssertionValue(pa.getAssertion(), new Value<>(identifier));
189: desc.setAssertionContext(pa.getAssertion(), pa.getContext());
190: storageConnection.persist(desc);
191: }
192: final Set<PendingReferenceRegistry.PendingListReference> pLists =
193: pendingReferences.removeAndGetPendingListReferencesWith(instance);
194: final EntityType<?> et = getEntityType(instance.getClass());
195:• for (PendingReferenceRegistry.PendingListReference list : pLists) {
196: final ListValueDescriptor desc = list.getDescriptor();
197: ListPropertyStrategy.addItemsToDescriptor(desc, list.getValues(), et);
198:• if (desc instanceof SimpleListValueDescriptor) {
199: // TODO This can be an update or a persist
200: storageConnection.lists().updateSimpleList((SimpleListValueDescriptor) desc);
201: } else {
202: storageConnection.lists().updateReferencedList((ReferencedListValueDescriptor) desc);
203: }
204: }
205: } catch (OntoDriverException e) {
206: throw new StorageAccessException(e);
207: }
208: }
209:
210: @Override
211: public <T> T getEntityFromCacheOrOntology(Class<T> cls, URI primaryKey, Descriptor descriptor) {
212: final T orig = uow.getManagedOriginal(cls, primaryKey, descriptor);
213:• if (orig != null) {
214: return orig;
215: }
216:• if (cache.contains(cls, primaryKey, descriptor)) {
217: return cache.get(cls, primaryKey, descriptor);
218:• } else if (instanceRegistry.containsInstance(primaryKey, descriptor.getContext())) {
219: // This prevents endless cycles in bidirectional relationships
220: return cls.cast(instanceRegistry.getInstance(primaryKey, descriptor.getContext()));
221: } else {
222: return loadEntityInternal(new LoadingParameters<>(cls, primaryKey, descriptor));
223: }
224: }
225:
226: @Override
227: public <T> T getOriginalInstance(T clone) {
228:• assert clone != null;
229: return (T) uow.getOriginal(clone);
230: }
231:
232: boolean isManaged(Object instance) {
233: return uow.isObjectManaged(instance);
234: }
235:
236: <T> void registerInstance(URI primaryKey, T instance, URI context) {
237: instanceRegistry.registerInstance(primaryKey, instance, context);
238: }
239:
240: @Override
241: public void checkForUnpersistedChanges() {
242:• if (pendingReferences.hasPendingResources()) {
243: throw new UnpersistedChangeException(
244: "The following instances were neither persisted nor marked as cascade for persist: "
245: + pendingReferences.getPendingResources());
246: }
247: }
248:
249: void registerPendingAssertion(NamedResource owner, Assertion assertion, Object object, URI context) {
250: pendingReferences.addPendingAssertion(owner, assertion, object, context);
251: }
252:
253: void registerPendingListReference(Object item, ListValueDescriptor listDescriptor, List<?> values) {
254: pendingReferences.addPendingListReference(item, listDescriptor, values);
255: }
256:
257: @Override
258: public <T> void removeEntity(URI primaryKey, Class<T> cls, Descriptor descriptor) {
259: final EntityType<T> et = getEntityType(cls);
260: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForEntityLoading(
261: new LoadingParameters<>(cls, primaryKey, descriptor, true), et);
262: try {
263: storageConnection.remove(axiomDescriptor);
264: pendingReferences.removePendingReferences(axiomDescriptor.getSubject());
265: } catch (OntoDriverException e) {
266: throw new StorageAccessException("Exception caught when removing entity.", e);
267: }
268: }
269:
270: @Override
271: public <T> void updateFieldValue(T entity, Field field, Descriptor descriptor) {
272: @SuppressWarnings("unchecked") final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
273: final URI pkUri = EntityPropertiesUtils.getIdentifier(entity, et);
274:
275: entityBreaker.setReferenceSavingResolver(new ReferenceSavingResolver(this));
276: // It is OK to do it like this, because if necessary, the mapping will re-register a pending assertion
277: removePendingAssertions(et, field, pkUri);
278: final AxiomValueGatherer axiomBuilder = entityBreaker.mapFieldToAxioms(pkUri, entity, field,
279: et, descriptor);
280: axiomBuilder.update(storageConnection);
281: }
282:
283: private <T> void removePendingAssertions(EntityType<T> et, Field field, URI identifier) {
284: final FieldSpecification<? super T, ?> fs = et.getFieldSpecification(field.getName());
285:• if (fs instanceof Attribute) {
286: final Attribute<?, ?> att = (Attribute<?, ?>) fs;
287: // We care only about object property assertions, others are never pending
288: final Assertion assertion = Assertion.createObjectPropertyAssertion(att.getIRI().toURI(), att.isInferred());
289: pendingReferences.removePendingReferences(NamedResource.create(identifier), assertion);
290: }
291: }
292:
293: @Override
294: public Collection<Axiom<NamedResource>> loadSimpleList(SimpleListDescriptor listDescriptor) {
295: try {
296: return storageConnection.lists().loadSimpleList(listDescriptor);
297: } catch (OntoDriverException e) {
298: throw new StorageAccessException(e);
299: }
300: }
301:
302: @Override
303: public Collection<Axiom<NamedResource>> loadReferencedList(ReferencedListDescriptor listDescriptor) {
304: try {
305: return storageConnection.lists().loadReferencedList(listDescriptor);
306: } catch (OntoDriverException e) {
307: throw new StorageAccessException(e);
308: }
309: }
310:
311: @Override
312: public Configuration getConfiguration() {
313: return uow.getConfiguration();
314: }
315: }