Skip to content

Package: EntityManagerImpl$6

EntityManagerImpl$6

nameinstructionbranchcomplexitylinemethod
runCascadedForEach(Object)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
{...}
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: case NOT_MANAGED:
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: open = false;
320: }
321:
322: @Override
323: public boolean isOpen() {
324: return open;
325: }
326:
327: @Override
328: public EntityTransaction getTransaction() {
329: return transaction.getTransaction();
330: }
331:
332: @Override
333: public EntityManagerFactoryImpl getEntityManagerFactory() {
334: return emf;
335: }
336:
337: @Override
338: public Metamodel getMetamodel() {
339: return emf.getMetamodel();
340: }
341:
342: @Override
343: public boolean isLoaded(final Object object, final String attributeName) {
344: // TODO
345: return false;
346: }
347:
348: @Override
349: public Query createQuery(String qlString) {
350: return getCurrentPersistenceContext().createQuery(qlString);
351: }
352:
353: @Override
354: public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
355: return getCurrentPersistenceContext().createQuery(query, resultClass);
356: }
357:
358: @Override
359: public Query createNativeQuery(String sparql) {
360: return getCurrentPersistenceContext().createNativeQuery(sparql);
361: }
362:
363: @Override
364: public <T> TypedQuery<T> createNativeQuery(String sparql, Class<T> resultClass) {
365: return getCurrentPersistenceContext().createNativeQuery(sparql, resultClass);
366: }
367:
368: @Override
369: public Query createNamedQuery(String name) {
370: return getCurrentPersistenceContext().createNamedQuery(name);
371: }
372:
373: @Override
374: public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
375: return getCurrentPersistenceContext().createNamedQuery(name, resultClass);
376: }
377:
378: @Override
379: public boolean isConsistent(URI context) {
380: return getCurrentPersistenceContext().isConsistent(context);
381: }
382:
383: @Override
384: public List<URI> getContexts() {
385: return getCurrentPersistenceContext().getContexts();
386: }
387:
388: @Override
389: public void setUseTransactionalOntologyForQueryProcessing() {
390: getCurrentPersistenceContext().setUseTransactionalOntologyForQueryProcessing();
391: }
392:
393: @Override
394: public boolean useTransactionalOntologyForQueryProcessing() {
395: return getCurrentPersistenceContext().useTransactionalOntologyForQueryProcessing();
396: }
397:
398: @Override
399: public void setUseBackupOntologyForQueryProcessing() {
400: getCurrentPersistenceContext().setUseBackupOntologyForQueryProcessing();
401: }
402:
403: @Override
404: public boolean useBackupOntologyForQueryProcessing() {
405: return getCurrentPersistenceContext().useBackupOntologyForQueryProcessing();
406: }
407:
408: @Override
409: public <T> T unwrap(Class<T> cls) {
410: if (cls.isAssignableFrom(this.getClass())) {
411: return cls.cast(this);
412: }
413: return getCurrentPersistenceContext().unwrap(cls);
414: }
415:
416: @Override
417: public Object getDelegate() {
418: return unwrap(EntityManagerImpl.class);
419: }
420:
421: private void ensureOpen() {
422: if (!isOpen()) {
423: throw new OWLPersistenceException("The entity manager is closed !");
424: }
425: }
426:
427: private State getState(Object entity) {
428: return getCurrentPersistenceContext().getState(entity);
429: }
430:
431: private State getState(Object entity, Descriptor descriptor) {
432: return getCurrentPersistenceContext().getState(entity, descriptor);
433: }
434:
435: @Override
436: protected void finalize() throws Throwable {
437: if (isOpen()) {
438: close();
439: }
440: super.finalize();
441: }
442:
443: @Override
444: public UnitOfWorkImpl getCurrentPersistenceContext() {
445: if (this.persistenceContext == null) {
446: this.persistenceContext = (UnitOfWorkImpl) this.serverSession.acquireUnitOfWork();
447: persistenceContext.setEntityManager(this);
448: }
449: return this.persistenceContext;
450: }
451:
452: /**
453: * Called from EntityTransaction in case of a rollback. Releasing the UoW is up to the EntityTransaction.
454: */
455: @Override
456: public void removeCurrentPersistenceContext() {
457: if (persistenceContext != null && persistenceContext.isActive()) {
458: persistenceContext.release();
459: }
460: this.persistenceContext = null;
461: }
462:
463: @Override
464: public void transactionStarted(EntityTransaction t) {
465: this.serverSession.transactionStarted(t, this);
466: }
467:
468: @Override
469: public void transactionFinished(EntityTransaction t) {
470: this.serverSession.transactionFinished(t);
471: }
472:
473: /**
474: * Since we support only EntityTransactions, we set the TransactionWrapper to EntityTransactionWrapper. In the
475: * future, if JTA transactions are supported, JTATransactionWrapper should be set instead of the
476: * EntityTransactionWrapper.
477: */
478: private void setTransactionWrapper() {
479: this.transaction = new EntityTransactionWrapper(this);
480: }
481:
482: @Override
483: public Configuration getConfiguration() {
484: return configuration;
485: }
486: }