You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/09/12 20:30:59 UTC
(cayenne) 01/02: CAY-3025 ObjectContext to require/return Persistent for all object ops
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit a72e595dfe2f892837988eb5e01b5bbb87ccc6fd
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat Sep 12 16:02:06 2026 -0400
CAY-3025 ObjectContext to require/return Persistent for all object ops
---
.../cayenne/DataChannelSyncCallbackAction.java | 10 +--
.../java/org/apache/cayenne/ObjectContext.java | 26 ++++----
.../org/apache/cayenne/ObjectContextStateLog.java | 26 ++++----
.../org/apache/cayenne/access/DataContext.java | 74 ++++++++++------------
.../cayenne/access/DataContextMergeHandler.java | 4 +-
.../access/JoinedIdParentAttachmentStrategy.java | 6 +-
.../org/apache/cayenne/access/ObjectStore.java | 25 ++++----
.../cayenne/access/ObjectStoreGraphDiff.java | 2 +-
.../cayenne/access/flush/DbRowOpFactory.java | 2 +-
.../flush/operation/GraphBasedDbRowOpSorter.java | 2 +-
.../cayenne/ashwood/AshwoodEntitySorter.java | 2 +-
.../org/apache/cayenne/graph/ChildDiffLoader.java | 2 +-
.../org/apache/cayenne/graph/GraphManager.java | 13 ++--
.../apache/cayenne/util/ShallowMergeOperation.java | 2 +-
.../apache/cayenne/ContextStateRecorderTest.java | 3 +-
.../access/DataContextInvalidateObjectsIT.java | 6 +-
.../cayenne/dba/ConcurrentPkGeneratorIT.java | 6 +-
17 files changed, 106 insertions(+), 105 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java b/cayenne/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
index 2120123e2..3315e2469 100644
--- a/cayenne/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
@@ -42,7 +42,7 @@ public abstract class DataChannelSyncCallbackAction implements GraphChangeHandle
public static DataChannelSyncCallbackAction getCallbackAction(
LifecycleCallbackRegistry callbackRegistry,
- GraphManager graphManager,
+ GraphManager<Persistent> graphManager,
GraphDiff changes,
int syncType) {
@@ -62,10 +62,10 @@ public abstract class DataChannelSyncCallbackAction implements GraphChangeHandle
Collection<Object> persisted;
Collection<Object> removed;
private Map<Object, Op> seenIds;
- private GraphManager graphManager;
+ private GraphManager<Persistent> graphManager;
DataChannelSyncCallbackAction(LifecycleCallbackRegistry callbackRegistry,
- GraphManager graphManager, GraphDiff changes) {
+ GraphManager<Persistent> graphManager, GraphDiff changes) {
this.callbackRegistry = callbackRegistry;
this.graphManager = graphManager;
@@ -172,7 +172,7 @@ public abstract class DataChannelSyncCallbackAction implements GraphChangeHandle
static class FlushCallbackAction extends DataChannelSyncCallbackAction {
FlushCallbackAction(LifecycleCallbackRegistry callbackRegistry,
- GraphManager graphManager, GraphDiff changes) {
+ GraphManager<Persistent> graphManager, GraphDiff changes) {
super(callbackRegistry, graphManager, changes);
}
@@ -202,7 +202,7 @@ public abstract class DataChannelSyncCallbackAction implements GraphChangeHandle
static class RollbackCallbackAction extends DataChannelSyncCallbackAction {
RollbackCallbackAction(LifecycleCallbackRegistry callbackRegistry,
- GraphManager graphManager, GraphDiff changes) {
+ GraphManager<Persistent> graphManager, GraphDiff changes) {
super(callbackRegistry, graphManager, changes);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/ObjectContext.java b/cayenne/src/main/java/org/apache/cayenne/ObjectContext.java
index 814f93952..cb8634f13 100644
--- a/cayenne/src/main/java/org/apache/cayenne/ObjectContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/ObjectContext.java
@@ -53,24 +53,24 @@ public interface ObjectContext {
* Returns a collection of objects that are registered with this
* ObjectContext and have a state PersistenceState.NEW
*/
- Collection<?> newObjects();
+ Collection<Persistent> newObjects();
/**
* Returns a collection of objects that are registered with this
* ObjectContext and have a state PersistenceState.DELETED
*/
- Collection<?> deletedObjects();
+ Collection<Persistent> deletedObjects();
/**
* Returns a collection of objects that are registered with this
* ObjectContext and have a state PersistenceState.MODIFIED
*/
- Collection<?> modifiedObjects();
+ Collection<Persistent> modifiedObjects();
/**
* Returns a collection of MODIFIED, DELETED or NEW objects.
*/
- Collection<?> uncommittedObjects();
+ Collection<Persistent> uncommittedObjects();
/**
* Returns a local copy of 'objectFromAnotherContext' object. "Local" means
@@ -185,7 +185,7 @@ public interface ObjectContext {
* Creates a new persistent object of a given class scheduled to be inserted
* to the database on next commit.
*/
- <T> T newObject(Class<T> persistentClass);
+ <T extends Persistent> T newObject(Class<T> persistentClass);
/**
* Registers a transient object with the context. The difference with
@@ -197,7 +197,7 @@ public interface ObjectContext {
* new object that needs to be made persistent.
* @since 3.0
*/
- void registerNewObject(Object object);
+ void registerNewObject(Persistent object);
/**
* Schedules deletion of a persistent object.
@@ -206,7 +206,7 @@ public interface ObjectContext {
* if a {@link org.apache.cayenne.map.DeleteRule#DENY} delete
* rule is applicable for object deletion.
*/
- default void deleteObject(Object object) throws DeleteDenyException {
+ default void deleteObject(Persistent object) throws DeleteDenyException {
deleteObjects(object);
}
@@ -217,10 +217,10 @@ public interface ObjectContext {
* if a {@link org.apache.cayenne.map.DeleteRule#DENY} delete
* rule is applicable for object deletion.
*/
- default void deleteObjects(Collection<?> objects) throws DeleteDenyException {
+ default void deleteObjects(Collection<? extends Persistent> objects) throws DeleteDenyException {
// toArray() copies, which also guards against ConcurrentModificationException when delete rules modify the
// source collection (e.g. a to-many list) mid-iteration
- deleteObjects(objects.toArray());
+ deleteObjects(objects.toArray(new Persistent[0]));
}
/**
@@ -231,7 +231,7 @@ public interface ObjectContext {
* rule is applicable for object deletion.
* @since 3.1
*/
- <T> void deleteObjects(T... objects) throws DeleteDenyException;
+ <T extends Persistent> void deleteObjects(T... objects) throws DeleteDenyException;
/**
* A callback method that child Persistent objects are expected to call
@@ -365,7 +365,7 @@ public interface ObjectContext {
* Returns GraphManager that manages object graph associated with this
* context.
*/
- GraphManager getGraphManager();
+ GraphManager<Persistent> getGraphManager();
/**
* Returns <code>true</code> if there are any modified, deleted or new
@@ -382,7 +382,7 @@ public interface ObjectContext {
* and change object's state to HOLLOW. On the next access to this object,
* the object will be refetched.
*/
- void invalidateObjects(Collection<?> objects);
+ void invalidateObjects(Collection<? extends Persistent> objects);
/**
* Invalidates one or more persistent objects. Same as
@@ -392,7 +392,7 @@ public interface ObjectContext {
*
* @since 3.1
*/
- <T> void invalidateObjects(T... objects);
+ <T extends Persistent> void invalidateObjects(T... objects);
/**
* Returns a user-defined property previously set via 'setUserProperty'.
diff --git a/cayenne/src/main/java/org/apache/cayenne/ObjectContextStateLog.java b/cayenne/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
index 4a501c657..83d2d1599 100644
--- a/cayenne/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
+++ b/cayenne/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
@@ -38,9 +38,9 @@ import java.util.Set;
class ObjectContextStateLog implements GraphChangeHandler {
Set<Object> dirtyIds;
- GraphManager graphManager;
+ GraphManager<Persistent> graphManager;
- ObjectContextStateLog(GraphManager graphManager) {
+ ObjectContextStateLog(GraphManager<Persistent> graphManager) {
this.dirtyIds = new HashSet<>();
this.graphManager = graphManager;
}
@@ -59,14 +59,14 @@ class ObjectContextStateLog implements GraphChangeHandler {
List<Object> deletedIds = new ArrayList<>();
for (Object id : dirtyIds) {
- Object node = graphManager.getNode(id);
- if (node instanceof Persistent persistentNode) {
- switch (persistentNode.getPersistenceState()) {
+ Persistent node = graphManager.getNode(id);
+ if (node != null) {
+ switch (node.getPersistenceState()) {
case PersistenceState.MODIFIED, PersistenceState.NEW ->
- persistentNode.setPersistenceState(PersistenceState.COMMITTED);
+ node.setPersistenceState(PersistenceState.COMMITTED);
case PersistenceState.DELETED -> {
deletedIds.add(id);
- persistentNode.setPersistenceState(PersistenceState.TRANSIENT);
+ node.setPersistenceState(PersistenceState.TRANSIENT);
}
}
}
@@ -84,13 +84,13 @@ class ObjectContextStateLog implements GraphChangeHandler {
void graphReverted() {
for (Object id : dirtyIds) {
- Object node = graphManager.getNode(id);
- if (node instanceof Persistent persistentNode) {
- switch (persistentNode.getPersistenceState()) {
+ Persistent node = graphManager.getNode(id);
+ if (node != null) {
+ switch (node.getPersistenceState()) {
case PersistenceState.MODIFIED, PersistenceState.DELETED ->
- persistentNode.setPersistenceState(PersistenceState.COMMITTED);
+ node.setPersistenceState(PersistenceState.COMMITTED);
case PersistenceState.NEW ->
- persistentNode.setPersistenceState(PersistenceState.TRANSIENT);
+ node.setPersistenceState(PersistenceState.TRANSIENT);
}
}
}
@@ -127,7 +127,7 @@ class ObjectContextStateLog implements GraphChangeHandler {
int size = dirtyIds.size();
Collection<Object> objects = new ArrayList<>(size > 50 ? size / 2 : size);
for (Object id : dirtyIds) {
- Persistent o = (Persistent) graphManager.getNode(id);
+ Persistent o = graphManager.getNode(id);
if (o.getPersistenceState() == state) {
objects.add(o);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java
index bdb48a8ed..6f4c5932c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java
@@ -253,7 +253,7 @@ public class DataContext implements ObjectContext {
* have a state PersistenceState.NEW
*/
@Override
- public Collection<?> newObjects() {
+ public Collection<Persistent> newObjects() {
return getObjectStore().objectsInState(PersistenceState.NEW);
}
@@ -262,7 +262,7 @@ public class DataContext implements ObjectContext {
* have a state {@link PersistenceState#DELETED}
*/
@Override
- public Collection<?> deletedObjects() {
+ public Collection<Persistent> deletedObjects() {
return getObjectStore().objectsInState(PersistenceState.DELETED);
}
@@ -270,15 +270,15 @@ public class DataContext implements ObjectContext {
* @since 3.1
*/
@Override
- public <T> void deleteObjects(T... objects) throws DeleteDenyException {
+ public <T extends Persistent> void deleteObjects(T... objects) throws DeleteDenyException {
if (objects == null || objects.length == 0) {
return;
}
DataContextDeleteAction action = new DataContextDeleteAction(this);
- for (Object object : objects) {
- action.performDelete((Persistent) object);
+ for (Persistent object : objects) {
+ action.performDelete(object);
}
}
@@ -287,7 +287,7 @@ public class DataContext implements ObjectContext {
* have a state {@link PersistenceState#MODIFIED}
*/
@Override
- public Collection<?> modifiedObjects() {
+ public Collection<Persistent> modifiedObjects() {
return getObjectStore().objectsInState(PersistenceState.MODIFIED);
}
@@ -297,18 +297,18 @@ public class DataContext implements ObjectContext {
* @since 1.2
*/
@Override
- public Collection<?> uncommittedObjects() {
+ public Collection<Persistent> uncommittedObjects() {
int len = getObjectStore().registeredObjectsCount();
if (len == 0) {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
// guess target collection size
- Collection<Object> objects = new ArrayList<>(len > 100 ? len / 2 : len);
- Iterator<?> it = getObjectStore().getObjectIterator();
+ Collection<Persistent> objects = new ArrayList<>(len > 100 ? len / 2 : len);
+ Iterator<Persistent> it = getObjectStore().getObjectIterator();
while (it.hasNext()) {
- Persistent object = (Persistent) it.next();
+ Persistent object = it.next();
int state = object.getPersistenceState();
if (state == PersistenceState.MODIFIED || state == PersistenceState.NEW
|| state == PersistenceState.DELETED) {
@@ -366,8 +366,8 @@ public class DataContext implements ObjectContext {
}
for (ObjectId candidateId : inheritanceTree.polymorphicIds(id)) {
- if (getGraphManager().getNode(candidateId) instanceof Persistent object
- && object.getPersistenceState() != PersistenceState.HOLLOW) {
+ Persistent object = getGraphManager().getNode(candidateId);
+ if (object != null && object.getPersistenceState() != PersistenceState.HOLLOW) {
return object;
}
}
@@ -531,7 +531,7 @@ public class DataContext implements ObjectContext {
* @since 1.2
*/
@Override
- public <T> T newObject(Class<T> persistentClass) {
+ public <T extends Persistent> T newObject(Class<T> persistentClass) {
if (persistentClass == null) {
throw new NullPointerException("Null 'persistentClass'");
}
@@ -541,7 +541,6 @@ public class DataContext implements ObjectContext {
throw new IllegalArgumentException("Class is not mapped with Cayenne: " + persistentClass.getName());
}
-
return (T) newObject(entity.getName());
}
@@ -584,36 +583,32 @@ public class DataContext implements ObjectContext {
* Registers a transient object with the context, recursively registering
* all transient persistent objects attached to this object via
* relationships.
- * <p>
- * <i>Note that since 3.0 this method takes Object as an argument instead of a {@link Persistent}.</i>
*
* @param object new object that needs to be made persistent.
*/
@Override
- public void registerNewObject(Object object) {
+ public void registerNewObject(Persistent object) {
if (object == null) {
throw new NullPointerException("Can't register null object.");
}
- ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object);
+ ObjEntity entity = getEntityResolver().getObjEntity(object);
if (entity == null) {
throw new IllegalArgumentException("Can't find ObjEntity for Persistent class: "
+ object.getClass().getName() + ", class is likely not mapped.");
}
- Persistent persistent = (Persistent) object;
-
// sanity check - maybe already registered
- if (persistent.getObjectId() != null) {
- if (persistent.getObjectContext() == this) {
+ if (object.getObjectId() != null) {
+ if (object.getObjectContext() == this) {
// already registered, just ignore
return;
- } else if (persistent.getObjectContext() != null) {
+ } else if (object.getObjectContext() != null) {
throw new IllegalStateException("Persistent is already registered with another DataContext. "
+ "Try using 'localObjects()' instead.");
}
} else {
- persistent.setObjectId(ObjectId.of(entity.getName()));
+ object.setObjectId(ObjectId.of(entity.getName()));
}
ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
@@ -629,27 +624,27 @@ public class DataContext implements ObjectContext {
descriptor.visitProperties(new PropertyVisitor() {
public boolean visitToMany(ToManyProperty property) {
- property.injectValueHolder(persistent);
+ property.injectValueHolder(object);
- Object value = property.readProperty(persistent);
+ Object value = property.readProperty(object);
Collection<?> collection = value instanceof Map<?, ?> map ? map.values() : (Collection<?>) value;
for (Object target : collection) {
if (target instanceof Persistent targetDO) {
registerNewObject(targetDO);
- getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
+ getObjectStore().arcCreated(object.getObjectId(), targetDO.getObjectId(), new ArcId(property));
}
}
return true;
}
public boolean visitToOne(ToOneProperty property) {
- Object target = property.readPropertyDirectly(persistent);
+ Object target = property.readPropertyDirectly(object);
if (target instanceof Persistent targetDO) {
// make sure it is registered
registerNewObject(targetDO);
- getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
+ getObjectStore().arcCreated(object.getObjectId(), targetDO.getObjectId(), new ArcId(property));
}
return true;
}
@@ -664,16 +659,14 @@ public class DataContext implements ObjectContext {
* If ObjEntity qualifier is set, asks it to inject initial value to an object.
* Also performs all Persistent initialization operations
*/
- private void injectInitialValue(Object obj) {
+ private void injectInitialValue(Persistent object) {
// must follow this exact order of property initialization per CAY-653,
// i.e. have the id and the context in place BEFORE setPersistence is called
- Persistent object = (Persistent) obj;
-
object.setObjectContext(this);
object.setPersistenceState(PersistenceState.NEW);
- GraphManager graphManager = getGraphManager();
+ GraphManager<Persistent> graphManager = getGraphManager();
synchronized (graphManager) {
graphManager.registerNode(object.getObjectId(), object);
graphManager.nodeCreated(object.getObjectId());
@@ -703,7 +696,7 @@ public class DataContext implements ObjectContext {
*
* @see #invalidateObjects(Collection)
*/
- public void unregisterObjects(Collection<?> objects) {
+ public void unregisterObjects(Collection<? extends Persistent> objects) {
getObjectStore().objectsUnregistered(objects);
}
@@ -712,14 +705,14 @@ public class DataContext implements ObjectContext {
*/
@SafeVarargs
@Override
- public final <T> void invalidateObjects(T... objects) {
+ public final <T extends Persistent> void invalidateObjects(T... objects) {
if (objects != null && objects.length > 0) {
invalidateObjects(Arrays.asList(objects));
}
}
@Override
- public void invalidateObjects(Collection<?> objects) {
+ public void invalidateObjects(Collection<? extends Persistent> objects) {
// don't allow null collections as a matter of coding discipline
if (objects == null) {
@@ -727,7 +720,6 @@ public class DataContext implements ObjectContext {
}
List<ObjectId> ids = objects.stream()
- .map(Persistent.class::cast)
// NEW objects have nothing to refetch, and their temporary ids are unknown to the parent channel
.filter(p -> p.getPersistenceState() != PersistenceState.NEW)
.map(Persistent::getObjectId)
@@ -757,7 +749,7 @@ public class DataContext implements ObjectContext {
@SuppressWarnings("unchecked")
private List<Persistent> resolveRelationshipInSelf(ObjectId sourceId, String relationshipName, boolean resolveToMany) {
- Persistent source = (Persistent) getGraphManager().getNode(sourceId);
+ Persistent source = getGraphManager().getNode(sourceId);
if (source == null) {
return null;
}
@@ -1137,7 +1129,7 @@ public class DataContext implements ObjectContext {
* @since 1.2
*/
@Override
- public GraphManager getGraphManager() {
+ public GraphManager<Persistent> getGraphManager() {
return objectStore;
}
@@ -1158,7 +1150,7 @@ public class DataContext implements ObjectContext {
// messing up Persistent objects per CAY-845. Originally only parts of "else" were synchronized,
// but we had to expand the lock scope to ensure consistent behavior.
synchronized (getGraphManager()) {
- Persistent cachedObject = (Persistent) getGraphManager().getNode(id);
+ Persistent cachedObject = getGraphManager().getNode(id);
// return an existing object
if (cachedObject != null) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java b/cayenne/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
index 5f48c0a72..d9a4f4c61 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
@@ -157,7 +157,7 @@ class DataContextMergeHandler implements GraphChangeHandler, DataChannelListener
Object oldValue,
Object newValue) {
- Persistent object = (Persistent) context.getGraphManager().getNode(nodeId);
+ Persistent object = context.getGraphManager().getNode(nodeId);
if (object != null && object.getPersistenceState() != PersistenceState.HOLLOW) {
// do not override local changes....
@@ -181,7 +181,7 @@ class DataContextMergeHandler implements GraphChangeHandler, DataChannelListener
// works the same for add and remove as long as we don't get too smart per TODO below.
private void arcChanged(Object nodeId, Object arcId) {
- final Persistent source = (Persistent) context.getGraphManager().getNode(nodeId);
+ final Persistent source = context.getGraphManager().getNode(nodeId);
if (source != null && source.getPersistenceState() != PersistenceState.HOLLOW) {
final int state = source.getPersistenceState();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java b/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java
index 7c6ef7ef4..ab0a747d8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java
@@ -38,9 +38,9 @@ class JoinedIdParentAttachmentStrategy implements ParentAttachmentStrategy {
private final CayennePath relatedIdPrefix;
private final Collection<ObjEntity> sourceEntities;
private final PrefetchProcessorNode node;
- private final GraphManager graphManager;
+ private final GraphManager<Persistent> graphManager;
- JoinedIdParentAttachmentStrategy(GraphManager graphManager, PrefetchProcessorNode node) {
+ JoinedIdParentAttachmentStrategy(GraphManager<Persistent> graphManager, PrefetchProcessorNode node) {
ClassDescriptor parentDescriptor = ((PrefetchProcessorNode) node.getParent())
.getResolver()
.getDescriptor();
@@ -70,7 +70,7 @@ class JoinedIdParentAttachmentStrategy implements ParentAttachmentStrategy {
, row, entity.getName(), relatedIdPrefix);
}
- parentObject = (Persistent) graphManager.getNode(id);
+ parentObject = graphManager.getNode(id);
if (parentObject != null) {
break;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
index 329caa64b..4619e6d74 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
@@ -68,7 +68,7 @@ import java.util.concurrent.ConcurrentHashMap;
*
* @since 1.0
*/
-public class ObjectStore implements SnapshotEventListener, GraphManager {
+public class ObjectStore implements SnapshotEventListener, GraphManager<Persistent> {
protected final DataContext context;
protected final DataRowStore dataRowCache;
@@ -250,16 +250,14 @@ public class ObjectStore implements SnapshotEventListener, GraphManager {
*/
// this method is exactly the same as "objectsInvalidated", only additionally it
// throws out registered objects
- public synchronized void objectsUnregistered(Collection objects) {
+ public synchronized void objectsUnregistered(Collection<? extends Persistent> objects) {
if (objects.isEmpty()) {
return;
}
Collection<ObjectId> ids = new ArrayList<>(objects.size());
- for (Object object1 : objects) {
- Persistent object = (Persistent) object1;
-
+ for (Persistent object : objects) {
ObjectId id = object.getObjectId();
// remove object but not snapshot
@@ -467,10 +465,11 @@ public class ObjectStore implements SnapshotEventListener, GraphManager {
return null;
}
- GraphManager parentGraph = parent.getGraphManager();
+ GraphManager<Persistent> parentGraph = parent.getGraphManager();
EntityInheritanceTree inheritanceTree = parent.getEntityResolver().getInheritanceTree(oid.getEntityName());
for (ObjectId candidateId : inheritanceTree.polymorphicIds(oid)) {
- if (parentGraph.getNode(candidateId) instanceof Persistent parentObject) {
+ Persistent parentObject = parentGraph.getNode(candidateId);
+ if (parentObject != null) {
return parent.currentSnapshot(parentObject);
}
}
@@ -784,7 +783,7 @@ public class ObjectStore implements SnapshotEventListener, GraphManager {
* @since 1.2
*/
@Override
- public synchronized Object getNode(Object nodeId) {
+ public synchronized Persistent getNode(Object nodeId) {
return objectMap.get(nodeId);
}
@@ -795,7 +794,7 @@ public class ObjectStore implements SnapshotEventListener, GraphManager {
* @since 1.2
*/
@Override
- public synchronized Collection<Object> registeredNodes() {
+ public synchronized Collection<Persistent> registeredNodes() {
return new ArrayList<>(objectMap.values());
}
@@ -803,16 +802,16 @@ public class ObjectStore implements SnapshotEventListener, GraphManager {
* @since 1.2
*/
@Override
- public synchronized void registerNode(Object nodeId, Object nodeObject) {
- objectMap.put(nodeId, (Persistent) nodeObject);
+ public synchronized void registerNode(Object nodeId, Persistent nodeObject) {
+ objectMap.put(nodeId, nodeObject);
}
/**
* @since 1.2
*/
@Override
- public synchronized Object unregisterNode(Object nodeId) {
- Object object = getNode(nodeId);
+ public synchronized Persistent unregisterNode(Object nodeId) {
+ Persistent object = objectMap.get(nodeId);
if (object != null) {
objectsUnregistered(Collections.singleton(object));
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
index 90842fbb9..10abbd967 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
@@ -183,7 +183,7 @@ public class ObjectStoreGraphDiff implements GraphDiff {
ObjectId id = (ObjectId) entry.getKey();
- Persistent object = (Persistent) objectStore.getNode(id);
+ Persistent object = objectStore.getNode(id);
// address manual id override.
ObjectId objectId = object.getObjectId();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
index fd418f8f6..ba33fb885 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
@@ -74,7 +74,7 @@ class DbRowOpFactory {
ObjectId id = (ObjectId) diff.getNodeId();
this.diff = diff;
this.descriptor = resolver.getClassDescriptor(id.getEntityName());
- this.object = (Persistent) store.getNode(id);
+ this.object = store.getNode(id);
this.dbRows.clear();
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/GraphBasedDbRowOpSorter.java b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/GraphBasedDbRowOpSorter.java
index d6307d0ee..3332cf36d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/GraphBasedDbRowOpSorter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/GraphBasedDbRowOpSorter.java
@@ -290,7 +290,7 @@ public class GraphBasedDbRowOpSorter implements DbRowOpSorter {
});
// check and merge flattened IDs snapshots
- GraphManager graphManager = object.getObjectContext().getGraphManager();
+ GraphManager<Persistent> graphManager = object.getObjectContext().getGraphManager();
if(graphManager instanceof ObjectStore store) {
store.getFlattenedIds(object.getObjectId()).forEach(flattenedId -> {
// map values of flattened ids from target to source
diff --git a/cayenne/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java b/cayenne/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
index 02087b966..8c88363e6 100644
--- a/cayenne/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
@@ -292,7 +292,7 @@ public class AshwoodEntitySorter implements EntitySorter {
// not using 'localObject', looking up in context instead, as within the sorter
// we only care about objects participating in transaction, so no need to create hollow objects
- return (id != null) ? (Persistent) context.getGraphManager().getNode(id) : null;
+ return (id != null) ? context.getGraphManager().getNode(id) : null;
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java b/cayenne/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
index 7e24264a4..f892f0d4b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
@@ -243,7 +243,7 @@ public class ChildDiffLoader implements GraphChangeHandler {
// return it;
// if not - fetch.
- Persistent object = (Persistent) context.getGraphManager().getNode(nodeId);
+ Persistent object = context.getGraphManager().getNode(nodeId);
if (object != null) {
return object;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/graph/GraphManager.java b/cayenne/src/main/java/org/apache/cayenne/graph/GraphManager.java
index c6f695fba..6f669f159 100644
--- a/cayenne/src/main/java/org/apache/cayenne/graph/GraphManager.java
+++ b/cayenne/src/main/java/org/apache/cayenne/graph/GraphManager.java
@@ -25,29 +25,30 @@ import java.util.Collection;
* Represents a generic "managed" graph with nodes mapped by their ids. Inherited
* GraphChangeHandler methods are intended as callbacks for graph node objects to notify
* graph of their changes.
- *
+ *
+ * @param <T> the type of graph nodes
* @since 1.2
*/
-public interface GraphManager extends GraphChangeHandler {
+public interface GraphManager<T> extends GraphChangeHandler {
/**
* Returns a graph node given an id.
*/
- Object getNode(Object nodeId);
+ T getNode(Object nodeId);
/**
* "Registers" a graph node, usually storing the node in some internal map using its
* id as a key.
*/
- void registerNode(Object nodeId, Object nodeObject);
+ void registerNode(Object nodeId, T nodeObject);
/**
* "Unregisters" a graph node, forgetting any information associated with nodeId.
*/
- Object unregisterNode(Object nodeId);
+ T unregisterNode(Object nodeId);
/**
* Returns all graph nodes registered with GraphManager.
*/
- Collection<Object> registeredNodes();
+ Collection<T> registeredNodes();
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java b/cayenne/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
index 8388117b0..6780ca156 100644
--- a/cayenne/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
+++ b/cayenne/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
@@ -54,7 +54,7 @@ public class ShallowMergeOperation {
ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(
id.getEntityName());
- GraphManager graphManager = context.getGraphManager();
+ GraphManager<Persistent> graphManager = context.getGraphManager();
// have to synchronize almost the entire method to prevent multiple threads from
// messing up Persistent objects per CAY-845.
diff --git a/cayenne/src/test/java/org/apache/cayenne/ContextStateRecorderTest.java b/cayenne/src/test/java/org/apache/cayenne/ContextStateRecorderTest.java
index 8b5ac5134..86a2200c1 100644
--- a/cayenne/src/test/java/org/apache/cayenne/ContextStateRecorderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/ContextStateRecorderTest.java
@@ -32,9 +32,10 @@ import org.junit.jupiter.api.Test;
public class ContextStateRecorderTest {
private ObjectContextStateLog recorder;
- private GraphManager mockGraphManager;
+ private GraphManager<Persistent> mockGraphManager;
@BeforeEach
+ @SuppressWarnings("unchecked")
public void before() {
this.mockGraphManager = mock(GraphManager.class);
this.recorder = new ObjectContextStateLog(mockGraphManager);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataContextInvalidateObjectsIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataContextInvalidateObjectsIT.java
index d5eb4e015..4c7307a20 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextInvalidateObjectsIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextInvalidateObjectsIT.java
@@ -18,11 +18,13 @@
****************************************************************/
package org.apache.cayenne.access;
+import java.util.ArrayList;
import java.util.List;
import org.apache.cayenne.Cayenne;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.PersistenceState;
+import org.apache.cayenne.Persistent;
import org.apache.cayenne.query.ObjectSelect;
import org.apache.cayenne.query.QueryCacheStrategy;
import org.apache.cayenne.query.SortOrder;
@@ -398,7 +400,9 @@ public class DataContextInvalidateObjectsIT {
.getSharedSnapshotCache()
.getCachedSnapshot(p2.getObjectId()));
- context.invalidateObjects(context.getObjectStore().registeredNodes());
+ List<Persistent> registered = new ArrayList<>();
+ context.getObjectStore().getObjectIterator().forEachRemaining(registered::add);
+ context.invalidateObjects(registered);
assertNull(context
.getChannel().getDataDomain()
diff --git a/cayenne/src/test/java/org/apache/cayenne/dba/ConcurrentPkGeneratorIT.java b/cayenne/src/test/java/org/apache/cayenne/dba/ConcurrentPkGeneratorIT.java
index a23f04a91..7a99fe2ad 100644
--- a/cayenne/src/test/java/org/apache/cayenne/dba/ConcurrentPkGeneratorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/dba/ConcurrentPkGeneratorIT.java
@@ -20,6 +20,7 @@
package org.apache.cayenne.dba;
import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.Persistent;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
@@ -99,7 +100,10 @@ public class ConcurrentPkGeneratorIT {
ObjectContext context1 = runtime.newContext();
EntityResolver entityResolver = context1.getEntityResolver();
for (ObjEntity entity : dataMap.getObjEntities()) {
- context1.newObject(entityResolver.getObjectFactory().getJavaClass(entity.getJavaClassName()));
+ Class<? extends Persistent> type = entityResolver.getObjectFactory()
+ .getJavaClass(entity.getJavaClassName())
+ .asSubclass(Persistent.class);
+ context1.newObject(type);
}
context1.commitChanges();
} catch (Exception e) {