Skip to content

Package: EntityManagerImpl$4

EntityManagerImpl$4

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