Skip to contentMethod: loadSimpleList(SimpleListDescriptor)
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.descriptors.Descriptor;
19: import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor;
20: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
21: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
22: import cz.cvut.kbss.jopa.oom.exceptions.EntityDeconstructionException;
23: import cz.cvut.kbss.jopa.oom.exceptions.EntityReconstructionException;
24: import cz.cvut.kbss.jopa.oom.exceptions.UnpersistedChangeException;
25: import cz.cvut.kbss.jopa.sessions.LoadingParameters;
26: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
27: import cz.cvut.kbss.jopa.utils.Configuration;
28: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
29: import cz.cvut.kbss.ontodriver.Connection;
30: import cz.cvut.kbss.ontodriver.descriptor.AxiomDescriptor;
31: import cz.cvut.kbss.ontodriver.descriptor.ReferencedListDescriptor;
32: import cz.cvut.kbss.ontodriver.descriptor.SimpleListDescriptor;
33: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
34: import cz.cvut.kbss.ontodriver.model.*;
35: import org.slf4j.Logger;
36: import org.slf4j.LoggerFactory;
37:
38: import java.lang.reflect.Field;
39: import java.net.URI;
40: import java.util.Collection;
41: import java.util.Map;
42: import java.util.Map.Entry;
43: import java.util.Objects;
44:
45: public class ObjectOntologyMapperImpl implements ObjectOntologyMapper, EntityMappingHelper {
46:
47: private static final Logger LOG = LoggerFactory.getLogger(ObjectOntologyMapperImpl.class);
48:
49: private final UnitOfWorkImpl uow;
50: private final Connection storageConnection;
51: private final Metamodel metamodel;
52:
53: private final AxiomDescriptorFactory descriptorFactory;
54: private final EntityConstructor entityBuilder;
55: private final EntityDeconstructor entityBreaker;
56: private final InstanceRegistry instanceRegistry;
57: private final PendingChangeRegistry pendingPersists;
58:
59: public ObjectOntologyMapperImpl(UnitOfWorkImpl uow, Connection connection) {
60: this.uow = Objects.requireNonNull(uow);
61: this.storageConnection = Objects.requireNonNull(connection);
62: this.metamodel = uow.getMetamodel();
63: this.descriptorFactory = new AxiomDescriptorFactory();
64: this.instanceRegistry = new InstanceRegistry();
65: this.pendingPersists = new PendingChangeRegistry();
66: this.entityBuilder = new EntityConstructor(this);
67: this.entityBreaker = new EntityDeconstructor(this);
68: }
69:
70: @Override
71: public <T> boolean containsEntity(Class<T> cls, URI primaryKey, Descriptor descriptor) {
72: assert cls != null;
73: assert primaryKey != null;
74: assert descriptor != null;
75:
76: final EntityType<T> et = getEntityType(cls);
77: final NamedResource classUri = NamedResource.create(et.getIRI().toURI());
78: final Axiom<NamedResource> ax = new AxiomImpl<>(NamedResource.create(primaryKey),
79: Assertion.createClassAssertion(false), new Value<>(classUri));
80: try {
81: return storageConnection.contains(ax, descriptor.getContext());
82: } catch (OntoDriverException e) {
83: throw new StorageAccessException(e);
84: }
85: }
86:
87: @Override
88: public <T> T loadEntity(LoadingParameters<T> loadingParameters) {
89: assert loadingParameters != null;
90:
91: instanceRegistry.reset();
92: return loadEntityInternal(loadingParameters);
93: }
94:
95: private <T> T loadEntityInternal(LoadingParameters<T> loadingParameters) {
96: final EntityType<T> et = getEntityType(loadingParameters.getEntityType());
97: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForEntityLoading(loadingParameters, et);
98: try {
99: final Collection<Axiom<?>> axioms = storageConnection.find(axiomDescriptor);
100: if (axioms.isEmpty()) {
101: return null;
102: }
103: return entityBuilder
104: .reconstructEntity(loadingParameters.getIdentifier(), et, loadingParameters.getDescriptor(),
105: axioms);
106: } catch (OntoDriverException e) {
107: throw new StorageAccessException(e);
108: } catch (InstantiationException | IllegalAccessException e) {
109: throw new EntityReconstructionException(e);
110: }
111: }
112:
113: @Override
114: public <T> EntityType<T> getEntityType(Class<T> cls) {
115: return metamodel.entity(cls);
116: }
117:
118: @Override
119: public <T> void loadFieldValue(T entity, Field field, Descriptor descriptor) {
120: assert entity != null;
121: assert field != null;
122: assert descriptor != null;
123:
124: LOG.trace("Lazily loading value of field {} of entity ", field, entity);
125:
126: final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
127: final URI primaryKey = EntityPropertiesUtils.getPrimaryKey(entity, et);
128:
129: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForFieldLoading(primaryKey,
130: field, descriptor, et);
131: try {
132: final Collection<Axiom<?>> axioms = storageConnection.find(axiomDescriptor);
133: if (axioms.isEmpty()) {
134: return;
135: }
136: entityBuilder.setFieldValue(entity, field, axioms, et, descriptor);
137: } catch (OntoDriverException e) {
138: throw new StorageAccessException(e);
139: } catch (IllegalArgumentException | IllegalAccessException e) {
140: throw new EntityReconstructionException(e);
141: }
142: }
143:
144: @Override
145: public <T> void persistEntity(URI primaryKey, T entity, Descriptor descriptor) {
146: assert entity != null;
147: assert descriptor != null;
148:
149: @SuppressWarnings("unchecked")
150: final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
151: try {
152: if (primaryKey == null) {
153: primaryKey = generateIdentifier(et);
154: assert primaryKey != null;
155: EntityPropertiesUtils.setPrimaryKey(primaryKey, entity, et);
156: }
157: entityBreaker.setCascadeResolver(new PersistCascadeResolver(this));
158: final AxiomValueGatherer axiomBuilder = entityBreaker.mapEntityToAxioms(primaryKey,
159: entity, et, descriptor);
160: axiomBuilder.persist(storageConnection);
161: pendingPersists.removeInstance(primaryKey, descriptor.getContext());
162: } catch (IllegalArgumentException e) {
163: throw new EntityDeconstructionException("Unable to deconstruct entity " + entity, e);
164: }
165: }
166:
167: @Override
168: public URI generateIdentifier(EntityType<?> et) {
169: try {
170: return storageConnection.generateIdentifier(et.getIRI().toURI());
171: } catch (OntoDriverException e) {
172: throw new StorageAccessException(e);
173: }
174: }
175:
176: @Override
177: public <T> T getEntityFromCacheOrOntology(Class<T> cls, URI primaryKey, Descriptor descriptor) {
178: final T orig = uow.getManagedOriginal(cls, primaryKey, descriptor);
179: if (orig != null) {
180: return orig;
181: }
182: if (uow.getLiveObjectCache().contains(cls, primaryKey, descriptor.getContext())) {
183: return uow.getLiveObjectCache().get(cls, primaryKey, descriptor.getContext());
184: } else if (instanceRegistry.containsInstance(primaryKey, descriptor.getContext())) {
185: // This prevents endless cycles in bidirectional relationships
186: return cls.cast(instanceRegistry.getInstance(primaryKey, descriptor.getContext()));
187: } else {
188: return loadEntityInternal(new LoadingParameters<>(cls, primaryKey, descriptor));
189: }
190: }
191:
192: @Override
193: public <T> T getOriginalInstance(T clone) {
194: assert clone != null;
195: return (T) uow.getOriginal(clone);
196: }
197:
198: <T> void registerInstance(URI primaryKey, T instance, URI context) {
199: instanceRegistry.registerInstance(primaryKey, instance, context);
200: }
201:
202: @Override
203: public void checkForUnpersistedChanges() {
204: try {
205: final Map<URI, Map<URI, Object>> persists = pendingPersists.getInstances();
206: if (!persists.isEmpty()) {
207: for (URI ctx : persists.keySet()) {
208: for (Entry<URI, Object> e : persists.get(ctx).entrySet()) {
209: verifyInstanceExistInOntology(ctx, e.getKey(), e.getValue());
210: }
211: }
212: }
213: } catch (OntoDriverException e) {
214: throw new StorageAccessException(e);
215: }
216: }
217:
218: private void verifyInstanceExistInOntology(URI ctx, URI primaryKey, Object instance)
219: throws OntoDriverException {
220: boolean exists = containsEntity(instance.getClass(), primaryKey, new EntityDescriptor(ctx));
221: if (!exists) {
222: throw new UnpersistedChangeException(
223: "Encountered an instance that was neither persisted nor marked as cascade for persist. The instance: "
224: + instance);
225: }
226: }
227:
228: <T> void registerPendingPersist(URI primaryKey, T entity, URI context) {
229: pendingPersists.registerInstance(primaryKey, entity, context);
230: }
231:
232: @Override
233: public <T> void removeEntity(URI primaryKey, Class<T> cls, Descriptor descriptor) {
234: final EntityType<T> et = getEntityType(cls);
235: final AxiomDescriptor axiomDescriptor = descriptorFactory.createForEntityLoading(
236: new LoadingParameters<>(cls, primaryKey, descriptor, true), et);
237: try {
238: storageConnection.remove(axiomDescriptor);
239: } catch (OntoDriverException e) {
240: throw new StorageAccessException("Exception caught when removing entity.", e);
241: }
242: }
243:
244: @Override
245: public <T> void updateFieldValue(T entity, Field field, Descriptor descriptor) {
246: @SuppressWarnings("unchecked")
247: final EntityType<T> et = (EntityType<T>) getEntityType(entity.getClass());
248: final URI pkUri = EntityPropertiesUtils.getPrimaryKey(entity, et);
249:
250: entityBreaker.setCascadeResolver(new PersistCascadeResolver(this));
251: final AxiomValueGatherer axiomBuilder = entityBreaker.mapFieldToAxioms(pkUri, entity, field,
252: et, descriptor);
253: axiomBuilder.update(storageConnection);
254: }
255:
256: @Override
257: public Collection<Axiom<NamedResource>> loadSimpleList(SimpleListDescriptor listDescriptor) {
258: try {
259: return storageConnection.lists().loadSimpleList(listDescriptor);
260: } catch (OntoDriverException e) {
261: throw new StorageAccessException(e);
262: }
263: }
264:
265: @Override
266: public Collection<Axiom<NamedResource>> loadReferencedList(ReferencedListDescriptor listDescriptor) {
267: try {
268: return storageConnection.lists().loadReferencedList(listDescriptor);
269: } catch (OntoDriverException e) {
270: throw new StorageAccessException(e);
271: }
272: }
273:
274: @Override
275: public Configuration getConfiguration() {
276: return uow.getConfiguration();
277: }
278: }