Skip to content

Package: UnitOfWorkImpl

UnitOfWorkImpl

nameinstructionbranchcomplexitylinemethod
UnitOfWorkImpl(AbstractSession)
M: 0 C: 85
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 19
100%
M: 0 C: 1
100%
acquireConnection()
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
acquireUnitOfWork()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
attributeChanged(Object, Field)
M: 0 C: 46
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
calculateChanges()
M: 0 C: 16
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
calculateDeletedObjects(UnitOfWorkChangeSet)
M: 5 C: 30
86%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 7
88%
M: 0 C: 1
100%
calculateNewObjects(UnitOfWorkChangeSet)
M: 5 C: 50
91%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 1 C: 11
92%
M: 0 C: 1
100%
checkForCollections(Object)
M: 0 C: 25
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
clear()
M: 0 C: 31
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 11
100%
M: 0 C: 1
100%
cloneLoadedFieldValue(Object, Field, Descriptor, Object)
M: 0 C: 36
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
commit()
M: 0 C: 20
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
commitToOntology()
M: 0 C: 22
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
commitUnitOfWork()
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
contains(Object)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
containsOriginal(Object)
M: 0 C: 11
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 1
100%
M: 0 C: 1
100%
createChangeRecord(Object, Field, Descriptor)
M: 0 C: 23
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
createIndirectCollection(Object, Object, Field)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
createMap()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
createNativeQuery(String)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
createNativeQuery(String, Class)
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%
createQuery(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
createQuery(String, Class)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
deregisterEntityFromPersistenceContext(Object, UnitOfWork)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getCloneForOriginal(Object)
M: 2 C: 20
91%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 4
80%
M: 0 C: 1
100%
getConfiguration()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getContexts()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getDeletedObjects()
M: 0 C: 10
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getDescriptor(Object)
M: 4 C: 8
67%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 2
100%
M: 0 C: 1
100%
getFieldDescriptor(Object, Field, Descriptor)
M: 0 C: 15
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getIdentifier(Object)
M: 4 C: 8
67%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 2
100%
M: 0 C: 1
100%
getLiveObjectCache()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getManagedOriginal(Class, Object, Descriptor)
M: 2 C: 31
94%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 1 C: 7
88%
M: 0 C: 1
100%
getMetamodel()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getNewObjectsCloneToOriginal()
M: 0 C: 10
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getNewObjectsOriginalToClone()
M: 0 C: 10
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getObjectFromCache(Class, Object, URI)
M: 8 C: 13
62%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 0 C: 3
100%
M: 0 C: 1
100%
getOriginal(Object)
M: 0 C: 18
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
getState(Object)
M: 0 C: 28
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
getState(Object, Descriptor)
M: 0 C: 38
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
getUowChangeSet()
M: 0 C: 9
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
hasChanges()
M: 0 C: 13
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
hasDeleted()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
hasNew()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
individualAlreadyManaged(Object)
M: 0 C: 14
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isActive()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isConsistent(URI)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isInCommit()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isInRepository(Descriptor, Object)
M: 8 C: 12
60%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 0 C: 3
100%
M: 0 C: 1
100%
isInTransaction()
M: 0 C: 12
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 1
100%
M: 0 C: 1
100%
isIndividualManaged(Object, Object)
M: 0 C: 19
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
isObjectManaged(Object)
M: 0 C: 19
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
isObjectNew(Object)
M: 0 C: 11
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isSameType(Object, Object)
M: 4 C: 25
86%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 0 C: 3
100%
M: 0 C: 1
100%
isTypeManaged(Class)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$validateIntegrityConstraints$0(IntegrityConstraintsValidator, ObjectChangeSet)
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%
loadEntityField(Object, Field)
M: 0 C: 73
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 16
100%
M: 0 C: 1
100%
mergeChangesIntoParent()
M: 0 C: 9
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 3
100%
M: 0 C: 1
100%
mergeDetached(Object, Descriptor)
M: 0 C: 47
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
mergeDetachedInternal(Object, Descriptor)
M: 20 C: 105
84%
M: 2 C: 8
80%
M: 2 C: 4
67%
M: 5 C: 22
81%
M: 0 C: 1
100%
postCommit()
M: 0 C: 63
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 20
100%
M: 0 C: 1
100%
putObjectIntoCache(Object, Object, URI)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
readObject(Class, Object, Descriptor)
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
readObjectInternal(Class, Object, Descriptor)
M: 12 C: 93
89%
M: 5 C: 17
77%
M: 5 C: 7
58%
M: 0 C: 21
100%
M: 0 C: 1
100%
registerChangeRecord(Object, Object, Descriptor, ChangeRecord)
M: 0 C: 20
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
registerClone(Object, Object, Descriptor)
M: 0 C: 32
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
registerEntityWithOntologyContext(Descriptor, Object)
M: 8 C: 18
69%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 0 C: 5
100%
M: 0 C: 1
100%
registerEntityWithPersistenceContext(Object, UnitOfWorkImpl)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
registerExistingObject(Object, Descriptor)
M: 6 C: 27
82%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 1 C: 7
88%
M: 0 C: 1
100%
registerNewObject(Object, Descriptor)
M: 0 C: 15
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
registerNewObjectInternal(Object, Descriptor)
M: 4 C: 76
95%
M: 2 C: 8
80%
M: 2 C: 4
67%
M: 0 C: 18
100%
M: 0 C: 1
100%
release()
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
removeIndirectCollections(Object)
M: 0 C: 39
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
removeObject(Object)
M: 2 C: 58
97%
M: 2 C: 8
80%
M: 2 C: 4
67%
M: 2 C: 13
87%
M: 0 C: 1
100%
removeObjectFromCache(Object, URI)
M: 0 C: 17
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
revertObject(Object)
M: 20 C: 58
74%
M: 3 C: 5
63%
M: 3 C: 2
40%
M: 3 C: 12
80%
M: 0 C: 1
100%
rollback()
M: 0 C: 17
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
setEntityManager(AbstractEntityManager)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setHasChanges()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setIndirectCollectionIfPresent(Object, Field)
M: 0 C: 35
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
setShouldClearAfterCommit(boolean)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setUseBackupOntologyForQueryProcessing()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setUseTransactionalOntologyForQueryProcessing()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
shouldReleaseAfterCommit()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
storageCommit()
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
unregisterEntityFromOntologyContext(Object)
M: 16 C: 20
56%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 1 C: 6
86%
M: 0 C: 1
100%
unregisterObject(Object)
M: 6 C: 38
86%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 2 C: 11
85%
M: 0 C: 1
100%
unwrap(Class)
M: 0 C: 14
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
useBackupOntologyForQueryProcessing()
M: 0 C: 7
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
useTransactionalOntologyForQueryProcessing()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
validateIntegrityConstraints()
M: 0 C: 37
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
writeUncommittedChanges()
M: 7 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%

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.sessions;
14:
15: import cz.cvut.kbss.jopa.adapters.IndirectCollection;
16: import cz.cvut.kbss.jopa.exceptions.OWLEntityExistsException;
17: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
18: import cz.cvut.kbss.jopa.model.AbstractEntityManager;
19: import cz.cvut.kbss.jopa.model.EntityManagerImpl.State;
20: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
21: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
22: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
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.query.sparql.SparqlQueryFactory;
27: import cz.cvut.kbss.jopa.sessions.change.ChangeManagerImpl;
28: import cz.cvut.kbss.jopa.sessions.change.ChangeRecordImpl;
29: import cz.cvut.kbss.jopa.sessions.change.ChangeSetFactory;
30: import cz.cvut.kbss.jopa.sessions.validator.IntegrityConstraintsValidator;
31: import cz.cvut.kbss.jopa.utils.*;
32:
33: import java.lang.reflect.Field;
34: import java.net.URI;
35: import java.util.*;
36: import java.util.Map.Entry;
37:
38: public class UnitOfWorkImpl extends AbstractSession implements UnitOfWork, QueryFactory, ConfigurationHolder, Wrapper {
39:
40: private final Map<Object, Object> cloneMapping;
41: private final Map<Object, Object> cloneToOriginals;
42: private final Map<Object, Object> keysToClones = new HashMap<>();
43: private Map<Object, Object> deletedObjects;
44: private Map<Object, Object> newObjectsCloneToOriginal;
45: private Map<Object, Object> newObjectsOriginalToClone;
46: private final Map<Object, Object> newObjectsKeyToClone = new HashMap<>();
47: private RepositoryMap repoMap;
48:
49: private boolean hasChanges;
50: private boolean hasNew;
51: private boolean hasDeleted;
52: private boolean shouldReleaseAfterCommit;
53: private boolean shouldClearCacheAfterCommit;
54: private boolean useTransactionalOntology;
55:
56: private boolean isActive;
57: private boolean inCommit;
58:
59: private UnitOfWorkChangeSet uowChangeSet;
60:
61: private AbstractSession parent;
62: private AbstractEntityManager entityManager;
63: private final ConnectionWrapper storage;
64:
65: private final MergeManager mergeManager;
66: private final CloneBuilder cloneBuilder;
67: private final ChangeManager changeManager;
68: private final QueryFactory queryFactory;
69: private final CollectionFactory collectionFactory;
70: /**
71: * This is a shortcut for the second level cache.
72: */
73: private final CacheManager cacheManager;
74:
75: public UnitOfWorkImpl(AbstractSession parent) {
76: this.parent = Objects.requireNonNull(parent, ErrorUtils.constructNPXMessage("parent"));
77: this.cloneMapping = createMap();
78: this.cloneToOriginals = createMap();
79: this.repoMap = new RepositoryMap();
80: repoMap.initDescriptors();
81: this.cloneBuilder = new CloneBuilderImpl(this);
82: this.collectionFactory = new CollectionFactory(this);
83: this.cacheManager = parent.getLiveObjectCache();
84: this.storage = acquireConnection();
85: this.queryFactory = new SparqlQueryFactory(this, storage);
86: this.mergeManager = new MergeManagerImpl(this);
87: this.changeManager = new ChangeManagerImpl(this);
88: this.inCommit = false;
89: this.useTransactionalOntology = true;
90: this.isActive = true;
91: }
92:
93: /**
94: * This method returns null, since we don't support nested Units of Work yet.
95: */
96: @Override
97: public UnitOfWork acquireUnitOfWork() {
98: return null;
99: }
100:
101: @Override
102: protected ConnectionWrapper acquireConnection() {
103: final ConnectionWrapper conn = parent.acquireConnection();
104: conn.setUnitOfWork(this);
105: return conn;
106: }
107:
108: @Override
109: public <T> T readObject(Class<T> cls, Object primaryKey, Descriptor descriptor) {
110: Objects.requireNonNull(cls, ErrorUtils.constructNPXMessage("cls"));
111: Objects.requireNonNull(primaryKey, ErrorUtils.constructNPXMessage("primaryKey"));
112: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
113:
114: return readObjectInternal(cls, primaryKey, descriptor);
115: }
116:
117: private <T> T readObjectInternal(Class<T> cls, Object primaryKey, Descriptor descriptor) {
118:• assert cls != null;
119:• assert primaryKey != null;
120:• assert descriptor != null;
121: // First try to find the object among new uncommitted objects
122: Object result = newObjectsKeyToClone.get(primaryKey);
123:• if (result != null && (isInRepository(descriptor, result))) {
124: // The result can be returned, since it is already registered in
125: // this UOW
126: return cls.cast(result);
127: }
128: // Object is already managed
129: result = keysToClones.get(primaryKey);
130:• if (result != null) {
131:• if (!cls.isAssignableFrom(result.getClass())) {
132: throw individualAlreadyManaged(primaryKey);
133: }
134:• if (isInRepository(descriptor, result) && !getDeletedObjects().containsKey(result)) {
135: return cls.cast(result);
136: }
137: }
138: // Search the cache
139: result = getObjectFromCache(cls, primaryKey, descriptor.getContext());
140:• if (result == null) {
141: // The object is not in the session cache, so search the ontology
142: final URI pkUri = EntityPropertiesUtils.getValueAsURI(primaryKey);
143: result = storage.find(new LoadingParameters<>(cls, pkUri, descriptor));
144: }
145:• if (result == null) {
146: return null;
147: }
148: Object clone = registerExistingObject(result, descriptor);
149: checkForCollections(clone);
150: return cls.cast(clone);
151: }
152:
153: private OWLEntityExistsException individualAlreadyManaged(Object identifier) {
154: return new OWLEntityExistsException(
155: "An entity with URI " + identifier + " is already present in the current persistence context.");
156: }
157:
158: /**
159: * This method calculates the changes that were to the registered entities and adds these changes into the given
160: * change set for future commit to the ontology.
161: */
162: private void calculateChanges() {
163: final UnitOfWorkChangeSet changeSet = getUowChangeSet();
164:• if (hasNew()) {
165: calculateNewObjects(changeSet);
166: }
167:• if (hasDeleted()) {
168: calculateDeletedObjects(changeSet);
169: }
170: }
171:
172: /**
173: * Create object change sets for the new objects and adds them into our UnitOfWorkChangeSet.
174: *
175: * @param changeSet UnitOfWorkChangeSet
176: */
177: private void calculateNewObjects(UnitOfWorkChangeSet changeSet) {
178:• for (Object clone : getNewObjectsCloneToOriginal().keySet()) {
179: final Descriptor c = getDescriptor(clone);
180: Object original = getNewObjectsCloneToOriginal().get(clone);
181:• if (original == null) {
182: original = this.cloneBuilder.buildClone(clone, c);
183: }
184:• if (original == null) {
185: throw new OWLPersistenceException(
186: "Error while calculating changes for new objects. Original not found.");
187: }
188: getNewObjectsCloneToOriginal().put(clone, original);
189: getNewObjectsOriginalToClone().put(original, clone);
190: changeSet.addNewObjectChangeSet(ChangeSetFactory.createObjectChangeSet(original, clone,
191: c));
192: }
193: }
194:
195: private void calculateDeletedObjects(final UnitOfWorkChangeSet changeSet) {
196:• for (Object clone : getDeletedObjects().keySet()) {
197: Object original = cloneToOriginals.get(clone);
198:• if (original == null) {
199: throw new OWLPersistenceException("Cannot find an original for clone!");
200: }
201: Descriptor descriptor = getDescriptor(clone);
202: changeSet.addDeletedObjectChangeSet(ChangeSetFactory.createObjectChangeSet(original, clone,
203: descriptor));
204: }
205: }
206:
207: public void clear() {
208: cloneMapping.clear();
209: cloneToOriginals.clear();
210: keysToClones.clear();
211: this.deletedObjects = null;
212: this.newObjectsCloneToOriginal = null;
213: this.newObjectsOriginalToClone = null;
214: this.newObjectsKeyToClone.clear();
215: this.hasChanges = false;
216: this.hasDeleted = false;
217: this.hasNew = false;
218: }
219:
220: public boolean contains(Object entity) {
221: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
222:
223: return isObjectManaged(entity);
224: }
225:
226: public void commit() {
227: LOG.trace("UnitOfWork commit started.");
228:• if (!isActive()) {
229: throw new IllegalStateException("Cannot commit inactive Unit of Work!");
230: }
231: this.inCommit = true;
232: commitUnitOfWork();
233: LOG.trace("UnitOfWork commit finished.");
234: }
235:
236: public void rollback() {
237: LOG.trace("UnitOfWork rollback started.");
238:• if (!isActive()) {
239: throw new IllegalStateException("Cannot rollback inactive Unit of Work!");
240: }
241: storage.rollback();
242: clear();
243: }
244:
245: /**
246: * Commit this Unit of Work.
247: */
248: protected void commitUnitOfWork() {
249: commitToOntology();
250: mergeChangesIntoParent();
251: postCommit();
252: }
253:
254: /**
255: * Clean up after the commit.
256: */
257: private void postCommit() {
258: // Remove indirect collections from clones
259: cloneMapping.keySet().forEach(this::removeIndirectCollections);
260: getNewObjectsCloneToOriginal().clear();
261: getNewObjectsOriginalToClone().clear();
262: newObjectsKeyToClone.clear();
263: getDeletedObjects().clear();
264: cloneToOriginals.clear();
265: cloneMapping.clear();
266: keysToClones.clear();
267: this.hasChanges = false;
268: this.hasDeleted = false;
269: this.hasNew = false;
270: this.inCommit = false;
271: cloneBuilder.reset();
272: this.repoMap = new RepositoryMap();
273: repoMap.initDescriptors();
274: this.uowChangeSet = null;
275:• if (shouldClearCacheAfterCommit) {
276: cacheManager.evictAll();
277: this.shouldReleaseAfterCommit = true;
278: }
279: }
280:
281: /**
282: * If there are any changes, commit them to the ontology.
283: */
284: protected void commitToOntology() {
285:• boolean hasChanges = this.hasNew || this.hasChanges || this.hasDeleted;
286:• if (hasChanges) {
287: calculateChanges();
288: }
289: validateIntegrityConstraints();
290: storageCommit();
291: }
292:
293: private void validateIntegrityConstraints() {
294:• if (uowChangeSet == null) {
295: return;
296: }
297: final IntegrityConstraintsValidator validator = IntegrityConstraintsValidator.getValidator();
298:• for (ObjectChangeSet changeSet : uowChangeSet.getNewObjects()) {
299: validator.validate(changeSet.getCloneObject(),
300: getMetamodel().entity((Class<Object>) changeSet.getObjectClass()), false);
301: }
302: uowChangeSet.getExistingObjectsChanges().forEach(changeSet -> validator.validate(changeSet, getMetamodel()));
303: }
304:
305: private Map<Object, Object> createMap() {
306: return new IdentityHashMap<>();
307: }
308:
309: /**
310: * Gets current state of the specified entity. </p>
311: * <p>
312: * Note that since no repository is specified we can only determine if the entity is managed or removed. Therefore
313: * if the case is different this method returns State#NOT_MANAGED.
314: *
315: * @param entity The entity to check
316: * @return State of the entity
317: */
318: public State getState(Object entity) {
319: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
320:
321:• if (getDeletedObjects().containsKey(entity)) {
322: return State.REMOVED;
323:• } else if (getNewObjectsCloneToOriginal().containsKey(entity)) {
324: return State.MANAGED_NEW;
325:• } else if (cloneMapping.containsKey(entity)) {
326: return State.MANAGED;
327: } else {
328: return State.NOT_MANAGED;
329: }
330: }
331:
332: /**
333: * Checks the state of the specified entity with regards to the specified repository.
334: *
335: * @param entity Object
336: * @param descriptor Entity descriptor
337: * @return The state of the specified entity
338: */
339: public State getState(Object entity, Descriptor descriptor) {
340: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
341: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
342:
343:• if (getDeletedObjects().containsKey(entity)) {
344: return State.REMOVED;
345:• } else if (cloneMapping.containsKey(entity) && isInRepository(descriptor, entity)) {
346:• if (getNewObjectsCloneToOriginal().containsKey(entity)) {
347: return State.MANAGED_NEW;
348: }
349: return State.MANAGED;
350: } else {
351: return State.NOT_MANAGED;
352: }
353: }
354:
355: /**
356: * Tries to find the original object for the given clone. It searches the existing objects, new objects and deleted
357: * objects.
358: *
359: * @param clone Object
360: * @return The original object for the given clone
361: */
362: public Object getOriginal(Object clone) {
363:• if (clone == null) {
364: return null;
365: }
366: Object original = cloneToOriginals.get(clone);
367:• if (original == null) {
368: original = getNewObjectsCloneToOriginal().get(clone);
369: }
370: return original;
371: }
372:
373: /**
374: * Gets managed original with the specified identifier or {@code null} if there is none matching.
375: * <p>
376: * Descriptor is used to check repository context validity.
377: *
378: * @param cls Return type of the original
379: * @param identifier Instance identifier
380: * @param descriptor Repository descriptor
381: * @return Original object managed by this UoW or {@code null} if this UoW doesn't contain a matching instance
382: */
383: public <T> T getManagedOriginal(Class<T> cls, Object identifier, Descriptor descriptor) {
384:• if (!keysToClones.containsKey(identifier)) {
385: return null;
386: }
387: final Object clone = keysToClones.get(identifier);
388:• if (!cls.isAssignableFrom(clone.getClass())) {
389: return null;
390: }
391:• if (!isInRepository(descriptor, clone)) {
392: return null;
393: }
394: return cls.cast(cloneToOriginals.get(clone));
395: }
396:
397: /**
398: * Check if this UnitOfWork contains this original entity. This method is used by the CloneBuilder so it does not
399: * have to clone already managed referenced objects.
400: *
401: * @param entity The original entity.
402: * @return True if the original is managed in this UnitOfWork.
403: */
404: boolean containsOriginal(Object entity) {
405:• return entity != null && cloneToOriginals.containsValue(entity);
406: }
407:
408: /**
409: * Finds clone for the specified original. This method assumes that the original is managed in this persistence
410: * context (UnitOfWork). However, if not, this method just goes through all the managed objects and if it does not
411: * find match, returns null.
412: *
413: * @param original The original object whose clone we are looking for.
414: * @return The clone or null, if there is none.
415: */
416: Object getCloneForOriginal(Object original) {
417:• for (Entry<Object, Object> entry : cloneToOriginals.entrySet()) {
418: // We use IdentityMap, so we can use ==
419:• if (entry.getValue() == original) {
420: return entry.getKey();
421: }
422: }
423: return null;
424: }
425:
426: public boolean hasDeleted() {
427: return hasDeleted;
428: }
429:
430: public boolean hasChanges() {
431:• return hasChanges || hasDeleted || hasNew;
432: }
433:
434: public boolean hasNew() {
435: return hasNew;
436: }
437:
438: public void setHasChanges() {
439: this.hasChanges = true;
440: }
441:
442: public Map<Object, Object> getDeletedObjects() {
443:• if (deletedObjects == null) {
444: this.deletedObjects = createMap();
445: }
446: return deletedObjects;
447: }
448:
449: public Map<Object, Object> getNewObjectsCloneToOriginal() {
450:• if (newObjectsCloneToOriginal == null) {
451: this.newObjectsCloneToOriginal = createMap();
452: }
453: return newObjectsCloneToOriginal;
454: }
455:
456: public Map<Object, Object> getNewObjectsOriginalToClone() {
457:• if (newObjectsOriginalToClone == null) {
458: this.newObjectsOriginalToClone = createMap();
459: }
460: return newObjectsOriginalToClone;
461: }
462:
463: @Override
464: public CacheManager getLiveObjectCache() {
465: return parent.getLiveObjectCache();
466: }
467:
468: public UnitOfWorkChangeSet getUowChangeSet() {
469:• if (uowChangeSet == null) {
470: this.uowChangeSet = ChangeSetFactory.createUoWChangeSet();
471: }
472: return uowChangeSet;
473: }
474:
475: public boolean isActive() {
476: return this.isActive;
477: }
478:
479: /**
480: * Returns true if the given clone represents a newly created object. Otherwise returns false.
481: *
482: * @param clone Object
483: * @return boolean
484: */
485: public boolean isObjectNew(Object clone) {
486:• return clone != null && getNewObjectsCloneToOriginal().containsKey(clone);
487: }
488:
489: /**
490: * Returns true if the given object is already managed.
491: *
492: * @param entity Object
493: * @return boolean
494: */
495: public boolean isObjectManaged(Object entity) {
496: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
497:
498:• return (cloneMapping.containsKey(entity) && !getDeletedObjects().containsKey(entity));
499: }
500:
501: /**
502: * Persists changed value of the specified field.
503: *
504: * @param entity Entity with changes (the clone)
505: * @param f The field whose value has changed
506: * @throws IllegalStateException If this UoW is not in transaction
507: */
508: public void attributeChanged(Object entity, Field f) {
509:• if (!isInTransaction()) {
510: throw new IllegalStateException("This unit of work is not in a transaction.");
511: }
512: final Descriptor descriptor = getDescriptor(entity);
513:• if (descriptor == null) {
514: throw new OWLPersistenceException("Unable to find repository for entity " + entity
515: + ". Is it registered in this UoW?");
516: }
517: storage.merge(entity, f, descriptor);
518: createChangeRecord(entity, f, descriptor);
519: setHasChanges();
520: setIndirectCollectionIfPresent(entity, f);
521: }
522:
523: private void createChangeRecord(Object clone, Field field, Descriptor descriptor) {
524: final Object orig = getOriginal(clone);
525:• if (orig == null) {
526: return;
527: }
528: final ChangeRecord record = new ChangeRecordImpl(field.getName(),
529: EntityPropertiesUtils.getFieldValue(field, clone));
530: registerChangeRecord(clone, orig, descriptor, record);
531: }
532:
533: private void registerChangeRecord(Object clone, Object orig, Descriptor descriptor, ChangeRecord record) {
534: ObjectChangeSet chSet = getUowChangeSet().getExistingObjectChanges(orig);
535:• if (chSet == null) {
536: chSet = ChangeSetFactory.createObjectChangeSet(orig, clone, descriptor);
537: getUowChangeSet().addObjectChangeSet(chSet);
538: }
539: chSet.addChangeRecord(record);
540: }
541:
542: /**
543: * Merge the changes from this Unit of Work's change set into the server session.
544: */
545: public void mergeChangesIntoParent() {
546:• if (hasChanges()) {
547: mergeManager.mergeChangesFromChangeSet(getUowChangeSet());
548: }
549: }
550:
551: @Override
552: public <T> T mergeDetached(T entity, Descriptor descriptor) {
553: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
554: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
555:
556: final Object id = getIdentifier(entity);
557:• if (!storage.contains(id, entity.getClass(), descriptor)) {
558: registerNewObject(entity, descriptor);
559: return entity;
560: } else {
561:• if (isIndividualManaged(id, entity) && !isSameType(id, entity)) {
562: throw individualAlreadyManaged(id);
563: }
564: return mergeDetachedInternal(entity, descriptor);
565: }
566: }
567:
568: private boolean isSameType(Object id, Object entity) {
569: final Class<?> mergedType = entity.getClass();
570:• final Object managed = keysToClones.containsKey(id) ? keysToClones.get(id) : newObjectsKeyToClone.get(id);
571:• return managed != null && managed.getClass().isAssignableFrom(mergedType);
572: }
573:
574: private <T> T mergeDetachedInternal(T entity, Descriptor descriptor) {
575:• assert entity != null;
576: final Object iri = getIdentifier(entity);
577: final Class<T> entityCls = (Class<T>) entity.getClass();
578: // Search the cache
579: T original = getObjectFromCache(entityCls, iri, descriptor.getContext());
580:• if (original == null) {
581: // The object is not in the session cache, so search the ontology
582: final URI idUri = EntityPropertiesUtils.getValueAsURI(iri);
583: original = storage.find(new LoadingParameters<>(entityCls, idUri, descriptor, true));
584: }
585:• assert original != null;
586: registerClone(entity, original, descriptor);
587: try {
588: // Merge only the changed attributes
589: final ObjectChangeSet chSet = ChangeSetFactory.createObjectChangeSet(original, entity, descriptor);
590: changeManager.calculateChanges(chSet);
591: final EntityType<?> et = getMetamodel().entity(entityCls);
592:• for (ChangeRecord record : chSet.getChanges().values()) {
593: final Field field = et.getFieldSpecification(record.getAttributeName()).getJavaField();
594: storage.merge(entity, field, descriptor);
595: }
596: getUowChangeSet().addObjectChangeSet(chSet);
597: } catch (OWLEntityExistsException e) {
598: unregisterObject(entity);
599: throw e;
600: } catch (IllegalAccessException e) {
601: throw new OWLPersistenceException(e);
602: }
603:• if (cacheManager.contains(entityCls, iri, descriptor.getContext())) {
604: cacheManager.evict(entityCls, iri, descriptor.getContext());
605: }
606: setHasChanges();
607: return entity;
608: }
609:
610: /**
611: * {@inheritDoc}
612: */
613: @Override
614: void registerEntityWithPersistenceContext(Object entity, UnitOfWorkImpl uow) {
615: parent.registerEntityWithPersistenceContext(entity, uow);
616: }
617:
618: @Override
619: void deregisterEntityFromPersistenceContext(Object entity, UnitOfWork uow) {
620: parent.deregisterEntityFromPersistenceContext(entity, uow);
621: }
622:
623: @Override
624: public Object registerExistingObject(Object entity, Descriptor descriptor) {
625:• if (entity == null) {
626: return null;
627: }
628:• if (cloneToOriginals.containsValue(entity)) {
629: return getCloneForOriginal(entity);
630: }
631: Object clone = this.cloneBuilder.buildClone(entity, descriptor);
632:• assert clone != null;
633: registerClone(clone, entity, descriptor);
634: return clone;
635: }
636:
637: private void registerClone(Object clone, Object original, Descriptor descriptor) {
638: cloneMapping.put(clone, clone);
639: cloneToOriginals.put(clone, original);
640: final Object identifier = EntityPropertiesUtils.getPrimaryKey(clone, getMetamodel());
641: keysToClones.put(identifier, clone);
642: registerEntityWithPersistenceContext(clone, this);
643: registerEntityWithOntologyContext(descriptor, clone);
644: }
645:
646: /**
647: * Release this Unit of Work. Releasing an active Unit of Work with uncommitted changes causes all pending changes
648: * to be discarded.
649: */
650: public void release() {
651: clear();
652: storage.close();
653: this.isActive = false;
654: LOG.debug("UnitOfWork released.");
655: }
656:
657: @Override
658: public <T> void revertObject(T object) {
659: Objects.requireNonNull(object, ErrorUtils.constructNPXMessage("object"));
660:
661:• if (!isObjectManaged(object) && !getDeletedObjects().containsKey(object)) {
662: throw new IllegalArgumentException("The specified entity " + object
663: + " is not managed by this persistence context.");
664: }
665: final Descriptor descriptor = getDescriptor(object);
666:• if (descriptor == null) {
667: throw new IllegalArgumentException("Unable to find entity " + object
668: + " in this persistence context.");
669: }
670: // To revert the object's state, just swap original and clone for change
671: // calculation and merging so that the state of the original is merged
672: // into the state of the clone
673: final Object original = getOriginal(object);
674: final ObjectChangeSet chSet = ChangeSetFactory.createObjectChangeSet(object, original,
675: descriptor);
676: try {
677: final boolean anyChanges = changeManager.calculateChanges(chSet);
678:• if (anyChanges) {
679: mergeManager.mergeChangesOnObject(original, chSet);
680: }
681: } catch (IllegalAccessException | IllegalArgumentException e) {
682: throw new OWLPersistenceException(e);
683: }
684: }
685:
686: @Override
687: public void registerNewObject(Object entity, Descriptor descriptor) {
688: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
689: Objects.requireNonNull(descriptor, ErrorUtils.constructNPXMessage("descriptor"));
690:
691: registerNewObjectInternal(entity, descriptor);
692: }
693:
694: /**
695: * Registers the specified entity for persist in this Unit of Work.
696: *
697: * @param entity The entity to register
698: * @param descriptor Entity descriptor, specifying optionally contexts into which the entity will be persisted
699: */
700: private void registerNewObjectInternal(Object entity, Descriptor descriptor) {
701:• assert entity != null;
702: Object id = getIdentifier(entity);
703:• if (id == null) {
704: final EntityType<?> eType = getMetamodel().entity(entity.getClass());
705: EntityPropertiesUtils.verifyIdentifierIsGenerated(entity, eType);
706: }
707:• if (isIndividualManaged(id, entity) && !entity.getClass().isEnum()) {
708: throw individualAlreadyManaged(id);
709: }
710: storage.persist(id, entity, descriptor);
711:• if (id == null) {
712: // If the ID was null, extract it from the entity
713: // It is present now
714: id = getIdentifier(entity);
715: }
716: // Original is null until commit
717: cloneMapping.put(entity, entity);
718: getNewObjectsCloneToOriginal().put(entity, null);
719: registerEntityWithPersistenceContext(entity, this);
720: registerEntityWithOntologyContext(descriptor, entity);
721: newObjectsKeyToClone.put(id, entity);
722: checkForCollections(entity);
723: this.hasNew = true;
724: }
725:
726: private boolean isIndividualManaged(Object identifier, Object entity) {
727:• return keysToClones.containsKey(identifier) ||
728:• newObjectsKeyToClone.containsKey(identifier) && !cloneMapping.containsKey(entity);
729: }
730:
731: /**
732: * Remove the specified entity from the ontology.
733: *
734: * @param entity Managed entity to delete
735: */
736: public void removeObject(Object entity) {
737:• if (entity == null) {
738: return;
739: }
740:• if (!isObjectManaged(entity)) {
741: throw new IllegalArgumentException(
742: "Cannot remove entity which is not managed in the current persistence context.");
743: }
744:• if (getDeletedObjects().containsKey(entity)) {
745: return;
746: }
747: final Object primaryKey = getIdentifier(entity);
748: final Descriptor descriptor = getDescriptor(entity);
749:
750:• if (hasNew() && getNewObjectsCloneToOriginal().containsKey(entity)) {
751: unregisterObject(entity);
752: newObjectsKeyToClone.remove(primaryKey);
753: } else {
754: getDeletedObjects().put(entity, entity);
755: this.hasDeleted = true;
756: }
757: //                unregisterEntityFromOntologyContext(entity);
758: storage.remove(primaryKey, entity.getClass(), descriptor);
759: }
760:
761: /**
762: * Remove the registered object from this Unit of Work.
763: *
764: * @param object Clone of the original object
765: */
766: public void unregisterObject(Object object) {
767:• if (object == null) {
768: return;
769: }
770: cloneMapping.remove(object);
771: cloneToOriginals.remove(object);
772:
773: getDeletedObjects().remove(object);
774:• if (hasNew()) {
775: Object newOriginal = getNewObjectsCloneToOriginal().remove(object);
776:• if (newOriginal != null) {
777: getNewObjectsOriginalToClone().remove(newOriginal);
778: }
779: }
780: removeIndirectCollections(object);
781: deregisterEntityFromPersistenceContext(object, this);
782: unregisterEntityFromOntologyContext(object);
783: }
784:
785: public boolean shouldReleaseAfterCommit() {
786: return shouldReleaseAfterCommit;
787: }
788:
789: public void setShouldClearAfterCommit(boolean shouldClearCache) {
790: this.shouldClearCacheAfterCommit = shouldClearCache;
791: }
792:
793: public void setEntityManager(AbstractEntityManager entityManager) {
794: this.entityManager = entityManager;
795: }
796:
797: public void writeUncommittedChanges() {
798:• if (!hasChanges()) {
799: return;
800: }
801: commitUnitOfWork();
802: }
803:
804: @Override
805: public Metamodel getMetamodel() {
806: return parent.getMetamodel();
807: }
808:
809: @Override
810: public boolean isTypeManaged(Class<?> cls) {
811: return parent.isTypeManaged(cls);
812: }
813:
814: @Override
815: public boolean isInTransaction() {
816:• return entityManager != null && entityManager.getTransaction().isActive();
817: }
818:
819: /**
820: * Returns {@code true} if this UoW is currently committing changes.
821: */
822: public boolean isInCommit() {
823: return inCommit;
824: }
825:
826: @Override
827: public <T> void loadEntityField(T entity, Field field) {
828: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
829: Objects.requireNonNull(field, ErrorUtils.constructNPXMessage("field"));
830:
831:• if (EntityPropertiesUtils.getFieldValue(field, entity) != null) {
832: return;
833: }
834: final Descriptor entityDescriptor = getDescriptor(entity);
835:• if (entityDescriptor == null) {
836: throw new OWLPersistenceException(
837: "Unable to find repository identifier for entity " + entity
838: + ". Is it managed by this UoW?");
839: }
840: storage.loadFieldValue(entity, field, entityDescriptor);
841: final Object orig = EntityPropertiesUtils.getFieldValue(field, entity);
842: final Object entityOriginal = getOriginal(entity);
843:• if (entityOriginal != null) {
844: EntityPropertiesUtils.setFieldValue(field, entityOriginal, orig);
845: }
846: final Descriptor fieldDescriptor = getFieldDescriptor(entity, field, entityDescriptor);
847: final Object clone = cloneLoadedFieldValue(entity, field, fieldDescriptor, orig);
848: EntityPropertiesUtils.setFieldValue(field, entity, clone);
849: }
850:
851: private <T> Descriptor getFieldDescriptor(T entity, Field field, Descriptor entityDescriptor) {
852: final EntityType<?> et = getMetamodel().entity(entity.getClass());
853: final FieldSpecification<?, ?> fieldSpec = et
854: .getFieldSpecification(field.getName());
855: return entityDescriptor.getAttributeDescriptor(fieldSpec);
856: }
857:
858: private <T> Object cloneLoadedFieldValue(T entity, Field field, final Descriptor fieldDescriptor,
859: final Object fieldValueOrig) {
860: Object clone;
861:• if (fieldValueOrig == null) {
862: clone = null;
863: } else {
864:• if (isTypeManaged(field.getType())) {
865: clone = registerExistingObject(fieldValueOrig, fieldDescriptor);
866: final URI fieldContext = fieldDescriptor.getContext();
867: putObjectIntoCache(getIdentifier(clone), fieldValueOrig, fieldContext);
868: } else {
869: clone = cloneBuilder.buildClone(entity, field, fieldValueOrig, fieldDescriptor);
870: }
871: }
872: return clone;
873: }
874:
875: @Override
876: public void removeObjectFromCache(Object toRemove, URI context) {
877: Objects.requireNonNull(toRemove, ErrorUtils.constructNPXMessage("toRemove"));
878:
879: final Object primaryKey = getIdentifier(toRemove);
880: cacheManager.evict(toRemove.getClass(), primaryKey, context);
881: }
882:
883: @Override
884: public boolean isConsistent(URI context) {
885: return storage.isConsistent(context);
886: }
887:
888: @Override
889: public List<URI> getContexts() {
890: return storage.getContexts();
891: }
892:
893: @Override
894: public void setUseTransactionalOntologyForQueryProcessing() {
895: this.useTransactionalOntology = true;
896: }
897:
898: @Override
899: public boolean useTransactionalOntologyForQueryProcessing() {
900: return useTransactionalOntology;
901: }
902:
903: @Override
904: public void setUseBackupOntologyForQueryProcessing() {
905: this.useTransactionalOntology = false;
906: }
907:
908: @Override
909: public boolean useBackupOntologyForQueryProcessing() {
910:• return !useTransactionalOntology;
911: }
912:
913: @Override
914: public Query createNativeQuery(String sparql) {
915: return queryFactory.createNativeQuery(sparql);
916: }
917:
918: @Override
919: public <T> TypedQuery<T> createNativeQuery(String sparql, Class<T> resultClass) {
920: return queryFactory.createNativeQuery(sparql, resultClass);
921: }
922:
923: @Override
924: public Query createQuery(String query) {
925: return queryFactory.createQuery(query);
926: }
927:
928: @Override
929: public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
930: return queryFactory.createQuery(query, resultClass);
931: }
932:
933: /**
934: * Check if the specified entity contains a collection. If so, replace it with its indirect representation so that
935: * changes in that collection can be tracked.
936: *
937: * @param entity The entity to check
938: */
939: private void checkForCollections(Object entity) {
940: Field[] fields = entity.getClass().getDeclaredFields();
941:• for (Field f : fields) {
942: setIndirectCollectionIfPresent(entity, f);
943: }
944: }
945:
946: /**
947: * Create and set indirect collection on the specified entity field.</p>
948: * <p>
949: * If the specified field is of Collection type and it is not already an indirect collection, create new one and set
950: * it as the value of the specified field on the specified entity.
951: *
952: * @param entity The entity collection will be set on
953: * @param field The field to set
954: * @throws IllegalArgumentException Reflection
955: */
956: public void setIndirectCollectionIfPresent(Object entity, Field field) {
957: Objects.requireNonNull(entity, ErrorUtils.constructNPXMessage("entity"));
958: Objects.requireNonNull(field, ErrorUtils.constructNPXMessage("field"));
959:
960: Object value = EntityPropertiesUtils.getFieldValue(field, entity);
961:• if (value == null || value instanceof IndirectCollection) {
962: return;
963: }
964:• if (value instanceof Collection || value instanceof Map) {
965: EntityPropertiesUtils.setFieldValue(field, entity, createIndirectCollection(value, entity, field));
966: }
967: }
968:
969: /**
970: * Creates an indirect collection, which wraps the specified collection instance and propagates changes to the
971: * persistence context.
972: *
973: * @param collection Collection to be proxied
974: * @param owner Collection owner instance
975: * @param field Field filled with the collection
976: * @return Indirect collection
977: */
978: public IndirectCollection<?> createIndirectCollection(Object collection, Object owner, Field field) {
979: return collectionFactory.createIndirectCollection(collection, owner, field);
980: }
981:
982: /**
983: * Remove indirect collection implementations from the specified entity (if present).
984: *
985: * @param entity The entity to remove indirect collections from
986: */
987: private void removeIndirectCollections(Object entity) {
988: Field[] fields = entity.getClass().getDeclaredFields();
989:• for (Field f : fields) {
990: final Object ob = EntityPropertiesUtils.getFieldValue(f, entity);
991:• if (ob == null) {
992: continue;
993: }
994:• if (ob instanceof IndirectCollection) {
995: IndirectCollection<?> indCol = (IndirectCollection<?>) ob;
996: EntityPropertiesUtils.setFieldValue(f, entity, indCol.getReferencedCollection());
997: }
998: }
999: }
1000:
1001: /**
1002: * Get entity with the specified primary key from the cache. </p>
1003: * <p>
1004: * If the cache does not contain any object with the specified primary key and class, null is returned. This method
1005: * is just a delegate for the cache methods, it handles locks.
1006: *
1007: * @return Cached object or null
1008: */
1009: private <T> T getObjectFromCache(Class<T> cls, Object primaryKey, URI context) {
1010:• assert cls != null;
1011:• assert primaryKey != null;
1012: return cacheManager.get(cls, primaryKey, context);
1013: }
1014:
1015: public void putObjectIntoCache(Object primaryKey, Object entity, URI context) {
1016: cacheManager.add(primaryKey, entity, context);
1017: }
1018:
1019: private Object getIdentifier(Object entity) {
1020:• assert entity != null;
1021: return EntityPropertiesUtils.getPrimaryKey(entity, getMetamodel());
1022: }
1023:
1024: private void unregisterEntityFromOntologyContext(Object entity) {
1025:• assert entity != null;
1026:
1027: final Descriptor descriptor = repoMap.getEntityDescriptor(entity);
1028:• if (descriptor == null) {
1029: throw new OWLPersistenceException("Fatal error, unable to find descriptor for entity " + entity);
1030: }
1031:
1032: repoMap.remove(descriptor, entity);
1033: repoMap.removeEntityToRepository(entity);
1034: }
1035:
1036: private void registerEntityWithOntologyContext(Descriptor repository, Object entity) {
1037:• assert repository != null;
1038:• assert entity != null;
1039:
1040: repoMap.add(repository, entity, null);
1041: repoMap.addEntityToRepository(entity, repository);
1042: }
1043:
1044: private boolean isInRepository(Descriptor descriptor, Object entity) {
1045:• assert descriptor != null;
1046:• assert entity != null;
1047:
1048: return repoMap.contains(descriptor, entity);
1049: }
1050:
1051: private Descriptor getDescriptor(Object entity) {
1052:• assert entity != null;
1053:
1054: return repoMap.getEntityDescriptor(entity);
1055: }
1056:
1057: private void storageCommit() {
1058: try {
1059: storage.commit();
1060: } catch (OWLPersistenceException e) {
1061: entityManager.removeCurrentPersistenceContext();
1062: throw e;
1063: }
1064: }
1065:
1066: @Override
1067: public Configuration getConfiguration() {
1068: return entityManager.getConfiguration();
1069: }
1070:
1071: @Override
1072: public <T> T unwrap(Class<T> cls) {
1073:• if (cls.isAssignableFrom(getClass())) {
1074: return cls.cast(this);
1075: }
1076: return storage.unwrap(cls);
1077: }
1078: }