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: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.model;
14:
15: import cz.cvut.kbss.jopa.exceptions.OWLEntityExistsException;
16: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
17: import cz.cvut.kbss.jopa.exceptions.TransactionRequiredException;
18: import cz.cvut.kbss.jopa.model.annotations.CascadeType;
19: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
20: import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor;
21: import cz.cvut.kbss.jopa.model.metamodel.Attribute;
22: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
23: import cz.cvut.kbss.jopa.model.query.Query;
24: import cz.cvut.kbss.jopa.model.query.TypedQuery;
25: import cz.cvut.kbss.jopa.sessions.ServerSession;
26: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
27: import cz.cvut.kbss.jopa.transactions.EntityTransaction;
28: import cz.cvut.kbss.jopa.transactions.EntityTransactionWrapper;
29: import cz.cvut.kbss.jopa.transactions.TransactionWrapper;
30: import cz.cvut.kbss.jopa.utils.CollectionFactory;
31: import cz.cvut.kbss.jopa.utils.Configuration;
32: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
33: import cz.cvut.kbss.jopa.utils.ErrorUtils;
34: import org.slf4j.Logger;
35: import org.slf4j.LoggerFactory;
36:
37: import java.net.URI;
38: import java.util.Collection;
39: import java.util.List;
40: import java.util.Objects;
41:
42: public class EntityManagerImpl extends AbstractEntityManager {
43:
44: private static final Logger LOG = LoggerFactory.getLogger(EntityManagerImpl.class);
45:
46: private EntityManagerFactoryImpl emf;
47:
48: private boolean open;
49:
50: private TransactionWrapper transaction;
51: private UnitOfWorkImpl persistenceContext;
52: private ServerSession serverSession;
53: private final Configuration configuration;
54:
55: public EntityManagerImpl(EntityManagerFactoryImpl emf, Configuration configuration,
56: ServerSession serverSession) {
57: this.emf = emf;
58: this.serverSession = serverSession;
59: this.configuration = configuration;
60:
61: this.setTransactionWrapper();
62:
63: this.open = true;
64: }
65:
66: public enum State {
67: MANAGED, MANAGED_NEW, NOT_MANAGED, REMOVED
68: }
69:
70: @Override
71: public void persist(final Object entity) {
72: final Descriptor d = new EntityDescriptor();
73: persist(entity, d);
74: }
75:
76: @Override
77: public void persist(final Object entity, final Descriptor descriptor) {
78: LOG.trace("Persisting {}", entity);
79: ensureOpen();
80: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
81: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
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: @Override
132: public <T> T merge(final T entity) {
133: final Descriptor d = new EntityDescriptor();
134: return merge(entity, d);
135: }
136:
137: @Override
138: public <T> T merge(final T entity, final Descriptor descriptor) {
139: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
140: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
141:
142: return mergeInternal(entity, descriptor);
143: }
144:
145: /**
146: * Merges state of the specified entity into the current persistence context. </p>
147: *
148: * @param entity Entity instance
149: * @param descriptor Contains information about contexts into which the entity and its field should be merged
150: * @return Managed instance of the merged entity
151: */
152: private <T> T mergeInternal(final T entity, final Descriptor descriptor) {
153: assert entity != null;
154: assert descriptor != null;
155: LOG.trace("Merging {}", entity);
156: ensureOpen();
157:
158: Class<T> clz = (Class<T>) entity.getClass();
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: public void remove(Object object) {
213: ensureOpen();
214:
215: switch (getState(object)) {
216: case MANAGED_NEW:
217: case MANAGED:
218: getCurrentPersistenceContext().removeObject(object);
219: // Intentional fall-through
220: case REMOVED:
221: new SimpleOneLevelCascadeExplorer() {
222: @Override
223: protected void runCascadedForEach(Object ox2) {
224: remove(ox2);
225: }
226: }.start(this, object, CascadeType.REMOVE);
227: break;
228: case NOT_MANAGED:
229: throw new IllegalArgumentException("Entity " + object
230: + " is not managed and cannot be removed.");
231: }
232: }
233:
234: @Override
235: public <T> T find(Class<T> cls, Object primaryKey) {
236: final EntityDescriptor d = new EntityDescriptor();
237: return find(cls, primaryKey, d);
238: }
239:
240: @Override
241: public <T> T find(Class<T> cls, Object primaryKey, Descriptor descriptor) {
242: Objects.requireNonNull(cls, ErrorUtils.constructNPXMessage("cls"));
243: Objects.requireNonNull(primaryKey, ErrorUtils.constructNPXMessage("primaryKey"));
244: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
245:
246: ensureOpen();
247: LOG.trace("Finding instance of {} with identifier {} in context ", cls, primaryKey, descriptor);
248: final URI uri = (primaryKey instanceof URI) ? (URI) primaryKey : URI.create(primaryKey.toString());
249:
250: return getCurrentPersistenceContext().readObject(cls, uri, descriptor);
251: }
252:
253: public void flush() {
254: ensureOpen();
255:
256: LOG.trace("Flushing changes...");
257: if (!getTransaction().isActive()) {
258: throw new TransactionRequiredException();
259: }
260: this.getCurrentPersistenceContext().writeUncommittedChanges();
261: }
262:
263: @Override
264: public void refresh(Object entity) {
265: ensureOpen();
266: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
267:
268: this.getCurrentPersistenceContext().revertObject(entity);
269: new SimpleOneLevelCascadeExplorer() {
270: @Override
271: protected void runCascadedForEach(Object ox2) {
272: refresh(ox2);
273: }
274: }.start(this, entity, CascadeType.REFRESH);
275: }
276:
277: public void clear() {
278: getCurrentPersistenceContext().clear();
279: }
280:
281: public void detach(Object entity) {
282: ensureOpen();
283:
284: switch (getState(entity)) {
285: case MANAGED_NEW:
286: case MANAGED:
287: getCurrentPersistenceContext().unregisterObject(entity);
288: new SimpleOneLevelCascadeExplorer() {
289: @Override
290: protected void runCascadedForEach(Object ox2) {
291: detach(ox2);
292: }
293: }.start(this, entity, CascadeType.DETACH);
294: break;
295: default:
296: break;
297: }
298: }
299:
300: public boolean contains(Object entity) {
301: ensureOpen();
302: return getCurrentPersistenceContext().contains(entity);
303: }
304:
305: public void close() {
306: ensureOpen();
307: removeCurrentPersistenceContext();
308: open = false;
309: }
310:
311: public boolean isOpen() {
312: return open;
313: }
314:
315: @Override
316: public EntityTransaction getTransaction() {
317: return transaction.getTransaction();
318: }
319:
320: public EntityManagerFactoryImpl getEntityManagerFactory() {
321: return emf;
322: }
323:
324: public Metamodel getMetamodel() {
325: return emf.getMetamodel();
326: }
327:
328: public boolean isLoaded(final Object object, final String attributeName) {
329: // TODO
330: return false;
331: }
332:
333: @Override
334: public Query createQuery(String qlString) {
335: return getCurrentPersistenceContext().createQuery(qlString);
336: }
337:
338: @Override
339: public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
340: return getCurrentPersistenceContext().createQuery(query, resultClass);
341: }
342:
343: @Override
344: public Query createNativeQuery(String sqlString) {
345: return getCurrentPersistenceContext().createNativeQuery(sqlString);
346: }
347:
348: @Override
349: public <T> TypedQuery<T> createNativeQuery(String sqlString, Class<T> resultClass) {
350: return getCurrentPersistenceContext().createNativeQuery(sqlString, resultClass);
351: }
352:
353: @Override
354: public boolean isConsistent(URI context) {
355: return getCurrentPersistenceContext().isConsistent(context);
356: }
357:
358: @Override
359: public List<URI> getContexts() {
360: return getCurrentPersistenceContext().getContexts();
361: }
362:
363: @Override
364: public void setUseTransactionalOntologyForQueryProcessing() {
365: getCurrentPersistenceContext().setUseTransactionalOntologyForQueryProcessing();
366: }
367:
368: @Override
369: public boolean useTransactionalOntologyForQueryProcessing() {
370: return getCurrentPersistenceContext().useTransactionalOntologyForQueryProcessing();
371: }
372:
373: @Override
374: public void setUseBackupOntologyForQueryProcessing() {
375: getCurrentPersistenceContext().setUseBackupOntologyForQueryProcessing();
376: }
377:
378: @Override
379: public boolean useBackupOntologyForQueryProcessing() {
380: return getCurrentPersistenceContext().useBackupOntologyForQueryProcessing();
381: }
382:
383: public <T> T unwrap(Class<T> cls) {
384: if (cls.equals(this.getClass())) {
385: return cls.cast(this);
386: }
387:
388: throw new OWLPersistenceException();
389: }
390:
391: public Object getDelegate() {
392: return unwrap(EntityManagerImpl.class);
393: }
394:
395: private void ensureOpen() {
396: if (!isOpen()) {
397: throw new OWLPersistenceException("The entity manager is closed !");
398: }
399: }
400:
401: private State getState(Object entity) {
402: return getCurrentPersistenceContext().getState(entity);
403: }
404:
405: private State getState(Object entity, Descriptor descriptor) {
406: return getCurrentPersistenceContext().getState(entity, descriptor);
407: }
408:
409: @Override
410: protected void finalize() throws Throwable {
411: if (isOpen()) {
412: close();
413: }
414: super.finalize();
415: }
416:
417: public UnitOfWorkImpl getCurrentPersistenceContext() {
418: if (this.persistenceContext == null) {
419: this.persistenceContext = (UnitOfWorkImpl) this.serverSession.acquireUnitOfWork();
420: persistenceContext.setEntityManager(this);
421: }
422: return this.persistenceContext;
423: }
424:
425: /**
426: * Called from EntityTransaction in case of a rollback. Releasing the UoW is up to the EntityTransaction.
427: */
428: public void removeCurrentPersistenceContext() {
429: if (persistenceContext != null && persistenceContext.isActive()) {
430: persistenceContext.release();
431: }
432: this.persistenceContext = null;
433: }
434:
435: public void transactionStarted(EntityTransaction t) {
436: this.serverSession.transactionStarted(t, this);
437: }
438:
439: public void transactionFinished(EntityTransaction t) {
440: this.serverSession.transactionFinished(t);
441: }
442:
443: /**
444: * Since we support only EntityTransactions, we set the TransactionWrapper to EntityTransactionWrapper. In the
445: * future, if JTA transactions are supported, JTATransactionWrapper should be set instead of the
446: * EntityTransactionWrapper.
447: */
448: private void setTransactionWrapper() {
449: this.transaction = new EntityTransactionWrapper(this);
450: }
451:
452: @Override
453: public Configuration getConfiguration() {
454: return configuration;
455: }
456: }