Skip to content

Package: EntityManagerImpl$5

EntityManagerImpl$5

nameinstructionbranchcomplexitylinemethod
runCascadedForEach(Object)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
{...}
M: 0 C: 6
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) 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.model;
16:
17: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
18: import cz.cvut.kbss.jopa.exceptions.TransactionRequiredException;
19: import cz.cvut.kbss.jopa.model.annotations.CascadeType;
20: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
21: import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor;
22: import cz.cvut.kbss.jopa.model.metamodel.Attribute;
23: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
24: import cz.cvut.kbss.jopa.model.query.Query;
25: import cz.cvut.kbss.jopa.model.query.TypedQuery;
26: import cz.cvut.kbss.jopa.sessions.ServerSession;
27: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
28: import cz.cvut.kbss.jopa.transactions.EntityTransaction;
29: import cz.cvut.kbss.jopa.transactions.EntityTransactionWrapper;
30: import cz.cvut.kbss.jopa.transactions.TransactionWrapper;
31: import cz.cvut.kbss.jopa.utils.*;
32: import org.slf4j.Logger;
33: import org.slf4j.LoggerFactory;
34:
35: import java.net.URI;
36: import java.util.Collection;
37: import java.util.List;
38: import java.util.Objects;
39:
40: public class EntityManagerImpl extends AbstractEntityManager implements Wrapper {
41:
42: private static final Logger LOG = LoggerFactory.getLogger(EntityManagerImpl.class);
43:
44: private EntityManagerFactoryImpl emf;
45:
46: private boolean open;
47:
48: private TransactionWrapper transaction;
49: private UnitOfWorkImpl persistenceContext;
50: private ServerSession serverSession;
51: private final Configuration configuration;
52:
53: public EntityManagerImpl(EntityManagerFactoryImpl emf, Configuration configuration, ServerSession serverSession) {
54: this.emf = emf;
55: this.serverSession = serverSession;
56: this.configuration = configuration;
57:
58: this.setTransactionWrapper();
59:
60: this.open = true;
61: }
62:
63: public enum State {
64: MANAGED, MANAGED_NEW, NOT_MANAGED, REMOVED
65: }
66:
67: @Override
68: public void persist(final Object entity) {
69: final Descriptor d = new EntityDescriptor();
70: persist(entity, d);
71: }
72:
73: @Override
74: public void persist(final Object entity, final Descriptor descriptor) {
75: LOG.trace("Persisting {}", entity);
76: ensureOpen();
77: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
78: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
79: checkClassIsValidEntity(entity.getClass());
80:
81: switch (getState(entity, descriptor)) {
82: case NOT_MANAGED:
83: try {
84: getCurrentPersistenceContext().registerNewObject(entity, descriptor);
85: } catch (RuntimeException e) {
86: if (getTransaction().isActive()) {
87: getTransaction().setRollbackOnly();
88: }
89: throw e;
90: }
91: case MANAGED:
92: new OneLevelCascadeExplorer() {
93: @Override
94: protected void exploreCascaded(Attribute<?, ?> at, Object o) {
95: try {
96: Object ox = EntityPropertiesUtils.getAttributeValue(at, o);
97: LOG.trace("object={}, attribute={}, value={}", o, at.getName(), ox);
98: if (ox == null) {
99: return;
100: }
101: final Descriptor attDescriptor = descriptor.getAttributeDescriptor(at);
102: if (at.isCollection()) {
103: for (final Object ox2 : (Collection<?>) ox) {
104: persist(ox2, attDescriptor);
105: }
106: } else {
107: persist(ox, attDescriptor);
108: }
109: } catch (Exception e) {
110: if (getTransaction().isActive()) {
111: getTransaction().setRollbackOnly();
112: }
113: throw new OWLPersistenceException(
114: "A problem occurred when persisting attribute " + at.getName()
115: + " of with value " + o + " of object " + entity, e);
116: }
117: }
118: }.start(this, entity, CascadeType.PERSIST);
119: break;
120: case REMOVED:
121: getCurrentPersistenceContext().revertObject(entity);
122: break;
123: default:
124: break;
125: }
126: }
127:
128: private void checkClassIsValidEntity(Class<?> cls) {
129: getMetamodel().entity(cls);
130: }
131:
132: @Override
133: public <T> T merge(final T entity) {
134: final Descriptor d = new EntityDescriptor();
135: return merge(entity, d);
136: }
137:
138: @Override
139: public <T> T merge(final T entity, final Descriptor descriptor) {
140: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
141: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
142: checkClassIsValidEntity(entity.getClass());
143:
144: return mergeInternal(entity, descriptor);
145: }
146:
147: /**
148: * Merges state of the specified entity into the current persistence context. </p>
149: *
150: * @param entity Entity instance
151: * @param descriptor Contains information about contexts into which the entity and its field should be merged
152: * @return Managed instance of the merged entity
153: */
154: private <T> T mergeInternal(final T entity, final Descriptor descriptor) {
155: assert entity != null;
156: assert descriptor != null;
157: LOG.trace("Merging {}", entity);
158: ensureOpen();
159:
160: switch (getState(entity, descriptor)) {
161: case MANAGED_NEW:
162: case MANAGED:
163: new OneLevelCascadeExplorer() {
164: @Override
165: protected void exploreCascaded(Attribute<?, ?> at, Object o) {
166: mergeX(at, o, descriptor);
167: }
168: }.start(this, entity, CascadeType.MERGE);
169: return entity;
170: case NOT_MANAGED:
171: final T merged;
172: merged = getCurrentPersistenceContext().mergeDetached(entity, descriptor);
173:
174: new OneLevelCascadeExplorer() {
175: @Override
176: protected void exploreCascaded(Attribute<?, ?> at, Object o) {
177: final Descriptor attDescriptor = descriptor.getAttributeDescriptor(at);
178: mergeX(at, o, attDescriptor);
179: }
180:
181: @Override
182: protected void exploreNonCascaded(Attribute<?, ?> at, Object o) {
183: final Object attVal = EntityPropertiesUtils.getAttributeValue(at, o);
184: EntityPropertiesUtils.setFieldValue(at.getJavaField(), o, attVal);
185: }
186: }.start(this, merged, CascadeType.MERGE);
187: return merged;
188: case REMOVED:
189: default:
190: throw new IllegalArgumentException();
191: }
192: }
193:
194: private void mergeX(Attribute<?, ?> at, Object o, Descriptor descriptor) {
195: Object attVal = EntityPropertiesUtils.getAttributeValue(at, o);
196: if (attVal == null) {
197: return;
198: }
199: if (at.isCollection()) {
200: Collection c = (Collection) attVal;
201: Collection merged = CollectionFactory.createInstance(c);
202: for (final Object ox2 : c) {
203: merged.add(mergeInternal(ox2, descriptor));
204: }
205: attVal = getCurrentPersistenceContext().createIndirectCollection(merged, o, at.getJavaField());
206: } else {
207: attVal = mergeInternal(attVal, descriptor);
208: }
209: EntityPropertiesUtils.setFieldValue(at.getJavaField(), o, attVal);
210: }
211:
212: @Override
213: public void remove(Object object) {
214: ensureOpen();
215: Objects.requireNonNull(object);
216: checkClassIsValidEntity(object.getClass());
217:
218: switch (getState(object)) {
219: case MANAGED_NEW:
220: case MANAGED:
221: getCurrentPersistenceContext().removeObject(object);
222: // Intentional fall-through
223: case REMOVED:
224: new SimpleOneLevelCascadeExplorer() {
225: @Override
226: protected void runCascadedForEach(Object ox2) {
227: remove(ox2);
228: }
229: }.start(this, object, CascadeType.REMOVE);
230: break;
231: default:
232: throw new IllegalArgumentException("Entity " + object + " is not managed and cannot be removed.");
233: }
234: }
235:
236: @Override
237: public <T> T find(Class<T> cls, Object primaryKey) {
238: final EntityDescriptor d = new EntityDescriptor();
239: return find(cls, primaryKey, d);
240: }
241:
242: @Override
243: public <T> T find(Class<T> cls, Object primaryKey, Descriptor descriptor) {
244: Objects.requireNonNull(cls, ErrorUtils.constructNPXMessage("cls"));
245: Objects.requireNonNull(primaryKey, ErrorUtils.constructNPXMessage("primaryKey"));
246: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
247:
248: ensureOpen();
249: checkClassIsValidEntity(cls);
250: LOG.trace("Finding instance of {} with identifier {} in context ", cls, primaryKey, descriptor);
251: final URI uri = (primaryKey instanceof URI) ? (URI) primaryKey : URI.create(primaryKey.toString());
252:
253: return getCurrentPersistenceContext().readObject(cls, uri, descriptor);
254: }
255:
256: @Override
257: public void flush() {
258: ensureOpen();
259:
260: LOG.trace("Flushing changes...");
261: if (!getTransaction().isActive()) {
262: throw new TransactionRequiredException();
263: }
264: this.getCurrentPersistenceContext().writeUncommittedChanges();
265: }
266:
267: @Override
268: public void refresh(Object entity) {
269: ensureOpen();
270: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
271: checkClassIsValidEntity(entity.getClass());
272:
273: this.getCurrentPersistenceContext().revertObject(entity);
274: new SimpleOneLevelCascadeExplorer() {
275: @Override
276: protected void runCascadedForEach(Object ox2) {
277: refresh(ox2);
278: }
279: }.start(this, entity, CascadeType.REFRESH);
280: }
281:
282: @Override
283: public void clear() {
284: getCurrentPersistenceContext().clear();
285: }
286:
287: @Override
288: public void detach(Object entity) {
289: ensureOpen();
290:
291: switch (getState(entity)) {
292: case MANAGED_NEW:
293: case MANAGED:
294: getCurrentPersistenceContext().unregisterObject(entity);
295: new SimpleOneLevelCascadeExplorer() {
296: @Override
297: protected void runCascadedForEach(Object ox2) {
298: detach(ox2);
299: }
300: }.start(this, entity, CascadeType.DETACH);
301: break;
302: default:
303: break;
304: }
305: }
306:
307: @Override
308: public boolean contains(Object entity) {
309: ensureOpen();
310: Objects.requireNonNull(entity);
311: checkClassIsValidEntity(entity.getClass());
312: return getCurrentPersistenceContext().contains(entity);
313: }
314:
315: @Override
316: public void close() {
317: ensureOpen();
318: removeCurrentPersistenceContext();
319: emf.entityManagerClosed(this);
320: open = false;
321: }
322:
323: @Override
324: public boolean isOpen() {
325: return open;
326: }
327:
328: @Override
329: public EntityTransaction getTransaction() {
330: return transaction.getTransaction();
331: }
332:
333: @Override
334: public EntityManagerFactoryImpl getEntityManagerFactory() {
335: return emf;
336: }
337:
338: @Override
339: public Metamodel getMetamodel() {
340: return emf.getMetamodel();
341: }
342:
343: @Override
344: public boolean isLoaded(final Object object, final String attributeName) {
345: // TODO
346: return false;
347: }
348:
349: @Override
350: public Query createQuery(String qlString) {
351: return getCurrentPersistenceContext().createQuery(qlString);
352: }
353:
354: @Override
355: public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
356: return getCurrentPersistenceContext().createQuery(query, resultClass);
357: }
358:
359: @Override
360: public Query createNativeQuery(String sparql) {
361: return getCurrentPersistenceContext().createNativeQuery(sparql);
362: }
363:
364: @Override
365: public <T> TypedQuery<T> createNativeQuery(String sparql, Class<T> resultClass) {
366: return getCurrentPersistenceContext().createNativeQuery(sparql, resultClass);
367: }
368:
369: @Override
370: public Query createNamedQuery(String name) {
371: return getCurrentPersistenceContext().createNamedQuery(name);
372: }
373:
374: @Override
375: public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
376: return getCurrentPersistenceContext().createNamedQuery(name, resultClass);
377: }
378:
379: @Override
380: public boolean isConsistent(URI context) {
381: return getCurrentPersistenceContext().isConsistent(context);
382: }
383:
384: @Override
385: public List<URI> getContexts() {
386: return getCurrentPersistenceContext().getContexts();
387: }
388:
389: @Override
390: public void setUseTransactionalOntologyForQueryProcessing() {
391: getCurrentPersistenceContext().setUseTransactionalOntologyForQueryProcessing();
392: }
393:
394: @Override
395: public boolean useTransactionalOntologyForQueryProcessing() {
396: return getCurrentPersistenceContext().useTransactionalOntologyForQueryProcessing();
397: }
398:
399: @Override
400: public void setUseBackupOntologyForQueryProcessing() {
401: getCurrentPersistenceContext().setUseBackupOntologyForQueryProcessing();
402: }
403:
404: @Override
405: public boolean useBackupOntologyForQueryProcessing() {
406: return getCurrentPersistenceContext().useBackupOntologyForQueryProcessing();
407: }
408:
409: @Override
410: public <T> T unwrap(Class<T> cls) {
411: if (cls.isAssignableFrom(this.getClass())) {
412: return cls.cast(this);
413: }
414: return getCurrentPersistenceContext().unwrap(cls);
415: }
416:
417: @Override
418: public Object getDelegate() {
419: return unwrap(EntityManagerImpl.class);
420: }
421:
422: private void ensureOpen() {
423: if (!isOpen()) {
424: throw new OWLPersistenceException("The entity manager is closed !");
425: }
426: }
427:
428: private State getState(Object entity) {
429: return getCurrentPersistenceContext().getState(entity);
430: }
431:
432: private State getState(Object entity, Descriptor descriptor) {
433: return getCurrentPersistenceContext().getState(entity, descriptor);
434: }
435:
436: @Override
437: protected void finalize() throws Throwable {
438: if (isOpen()) {
439: close();
440: }
441: super.finalize();
442: }
443:
444: @Override
445: public UnitOfWorkImpl getCurrentPersistenceContext() {
446: if (this.persistenceContext == null) {
447: this.persistenceContext = (UnitOfWorkImpl) this.serverSession.acquireUnitOfWork();
448: persistenceContext.setEntityManager(this);
449: }
450: return this.persistenceContext;
451: }
452:
453: /**
454: * Called from EntityTransaction in case of a rollback. Releasing the UoW is up to the EntityTransaction.
455: */
456: @Override
457: public void removeCurrentPersistenceContext() {
458: if (persistenceContext != null && persistenceContext.isActive()) {
459: persistenceContext.release();
460: }
461: this.persistenceContext = null;
462: }
463:
464: @Override
465: public void transactionStarted(EntityTransaction t) {
466: this.serverSession.transactionStarted(t, this);
467: }
468:
469: @Override
470: public void transactionFinished(EntityTransaction t) {
471: this.serverSession.transactionFinished(t);
472: }
473:
474: /**
475: * Since we support only EntityTransactions, we set the TransactionWrapper to EntityTransactionWrapper.
476: * <p>
477: * In the future, if JTA transactions are supported, JTATransactionWrapper should be set instead of the
478: * EntityTransactionWrapper.
479: */
480: private void setTransactionWrapper() {
481: this.transaction = new EntityTransactionWrapper(this);
482: }
483:
484: @Override
485: public Configuration getConfiguration() {
486: return configuration;
487: }
488: }