This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push: new 3b0d1440b CAY-2833 Unify code related to the Cayenne model paths processing 3b0d1440b is described below commit 3b0d1440b375da35437c25b2a1cfa2b13aaaabb9 Author: Nikita Timofeev <stari...@gmail.com> AuthorDate: Tue Feb 27 15:49:29 2024 +0400 CAY-2833 Unify code related to the Cayenne model paths processing --- .../access/HierarchicalObjectResolverNode.java | 3 ++- .../access/JoinedIdParentAttachmentStrategy.java | 6 ++--- .../org/apache/cayenne/access/ObjectResolver.java | 26 +++++++++------------- .../org/apache/cayenne/access/ObjectStore.java | 9 ++++---- .../access/flush/ArcValuesCreationHandler.java | 12 +++------- .../cayenne/access/flush/operation/Values.java | 9 ++++---- .../apache/cayenne/reflect/ClassDescriptor.java | 3 ++- .../reflect/LazyClassDescriptorDecorator.java | 3 ++- .../cayenne/reflect/PersistentDescriptor.java | 7 +++--- .../reflect/PersistentDescriptorFactory.java | 19 ++++++---------- 10 files changed, 43 insertions(+), 54 deletions(-) diff --git a/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java b/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java index b3de306ed..acc6c1f76 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java @@ -22,6 +22,7 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.DataRow; import org.apache.cayenne.ObjectId; import org.apache.cayenne.Persistent; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.reflect.ClassDescriptor; import java.util.ArrayList; @@ -55,7 +56,7 @@ class HierarchicalObjectResolverNode extends PrefetchObjectResolver { // not using DataRow.createObjectId for performance reasons - // ObjectResolver // has all needed metadata already cached. - ObjectId anId = createObjectId(row, classDescriptor.getEntity(), null); + ObjectId anId = createObjectId(row, classDescriptor.getEntity(), CayennePath.EMPTY_PATH); Persistent object = objectFromDataRow(row, anId, classDescriptor); if (object == null) { 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 eb15da0f5..7c6ef7ef4 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/JoinedIdParentAttachmentStrategy.java @@ -24,6 +24,7 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.DataRow; import org.apache.cayenne.ObjectId; import org.apache.cayenne.Persistent; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.graph.GraphManager; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.reflect.ClassDescriptor; @@ -34,7 +35,7 @@ import org.apache.cayenne.reflect.ClassDescriptor; */ class JoinedIdParentAttachmentStrategy implements ParentAttachmentStrategy { - private final String relatedIdPrefix; + private final CayennePath relatedIdPrefix; private final Collection<ObjEntity> sourceEntities; private final PrefetchProcessorNode node; private final GraphManager graphManager; @@ -47,8 +48,7 @@ class JoinedIdParentAttachmentStrategy implements ParentAttachmentStrategy { relatedIdPrefix = node .getIncoming() .getRelationship() - .getReverseDbRelationshipPath() - + "."; + .getReverseDbRelationshipPath(); sourceEntities = parentDescriptor.getEntityInheritanceTree().allSubEntities(); diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ObjectResolver.java b/cayenne/src/main/java/org/apache/cayenne/access/ObjectResolver.java index 5bdd54774..2aa9f8466 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectResolver.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectResolver.java @@ -25,6 +25,7 @@ import org.apache.cayenne.ObjectContext; import org.apache.cayenne.ObjectId; import org.apache.cayenne.PersistenceState; import org.apache.cayenne.Persistent; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityResolver; @@ -129,7 +130,7 @@ class ObjectResolver { // not using DataRow.createObjectId for performance reasons - // ObjectResolver has all needed metadata already cached. - ObjectId anId = createObjectId(row, classDescriptor.getEntity(), null); + ObjectId anId = createObjectId(row, classDescriptor.getEntity(), CayennePath.EMPTY_PATH); return objectFromDataRow(row, anId, classDescriptor); } @@ -181,12 +182,11 @@ class ObjectResolver { return; } - for(Map.Entry<String, DbEntity> entry : classDescriptor.getAdditionalDbEntities().entrySet()) { + for(Map.Entry<CayennePath, DbEntity> entry : classDescriptor.getAdditionalDbEntities().entrySet()) { DbEntity dbEntity = entry.getValue(); - String path = entry.getKey(); - int lastDot = path.lastIndexOf('.'); - String prefix = lastDot == -1 ? path : path.substring(lastDot + 1); - ObjectId objectId = createObjectId(row, "db:" + dbEntity.getName(), dbEntity.getPrimaryKeys(), prefix + '.', false); + CayennePath path = entry.getKey(); + CayennePath prefix = path.length() == 1 ? path : path.tail(path.length() - 1); + ObjectId objectId = createObjectId(row, "db:" + dbEntity.getName(), dbEntity.getPrimaryKeys(), prefix, false); if(objectId != null) { context.getObjectStore().markFlattenedPath(object.getObjectId(), path, objectId); } @@ -209,24 +209,20 @@ class ObjectResolver { return context; } - ObjectId createObjectId(DataRow dataRow, ObjEntity objEntity, String namePrefix) { + ObjectId createObjectId(DataRow dataRow, ObjEntity objEntity, CayennePath namePrefix) { Collection<DbAttribute> pk = objEntity == this.descriptor.getEntity() ? this.primaryKey : objEntity.getDbEntity().getPrimaryKeys(); return createObjectId(dataRow, objEntity.getName(), pk, namePrefix, true); } - ObjectId createObjectId(DataRow dataRow, String name, Collection<DbAttribute> pk, String namePrefix, boolean strict) { - boolean prefix = namePrefix != null && !namePrefix.isEmpty(); - + ObjectId createObjectId(DataRow dataRow, String name, Collection<DbAttribute> pk, CayennePath namePrefix, boolean strict) { // ... handle special case - PK.size == 1 // use some not-so-significant optimizations... if (pk.size() == 1) { DbAttribute attribute = pk.iterator().next(); - - String key = (prefix) ? namePrefix + attribute.getName() : attribute.getName(); - + String key = namePrefix.dot(attribute.getName()).value(); Object val = dataRow.get(key); // this is possible when processing left outer joint prefetches @@ -245,9 +241,7 @@ class ObjectResolver { Map<String, Object> idMap = new HashMap<>(pk.size() * 2); for (final DbAttribute attribute : pk) { - - String key = (prefix) ? namePrefix + attribute.getName() : attribute.getName(); - + String key = namePrefix.dot(attribute.getName()).value(); Object val = dataRow.get(key); // this is possible when processing left outer joint prefetches 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 28c17d11b..9f886e163 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java @@ -28,6 +28,7 @@ import org.apache.cayenne.Persistent; import org.apache.cayenne.access.ObjectDiff.ArcOperation; import org.apache.cayenne.access.event.SnapshotEvent; import org.apache.cayenne.access.event.SnapshotEventListener; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.graph.ArcId; import org.apache.cayenne.graph.ChildDiffLoader; import org.apache.cayenne.graph.GraphChangeHandler; @@ -72,7 +73,7 @@ public class ObjectStore implements Serializable, SnapshotEventListener, GraphMa * Presence of path in this map is used to separate insert from update case of flattened records. * @since 4.1 */ - protected Map<Object, Map<String, ObjectId>> trackedFlattenedPaths; + protected Map<Object, Map<CayennePath, ObjectId>> trackedFlattenedPaths; // a sequential id used to tag GraphDiffs so that they can later be sorted in the // original creation order @@ -598,7 +599,7 @@ public class ObjectStore implements Serializable, SnapshotEventListener, GraphMa } if(trackedFlattenedPaths != null) { - Map<String, ObjectId> paths = trackedFlattenedPaths.remove(nodeId); + Map<CayennePath, ObjectId> paths = trackedFlattenedPaths.remove(nodeId); if(paths != null) { trackedFlattenedPaths.put(newId, paths); } @@ -989,7 +990,7 @@ public class ObjectStore implements Serializable, SnapshotEventListener, GraphMa /** * @since 4.2 */ - public ObjectId getFlattenedId(ObjectId objectId, String path) { + public ObjectId getFlattenedId(ObjectId objectId, CayennePath path) { if(trackedFlattenedPaths == null) { return null; } @@ -1014,7 +1015,7 @@ public class ObjectStore implements Serializable, SnapshotEventListener, GraphMa * Mark that flattened path for object has data row in DB. * @since 4.1 */ - public void markFlattenedPath(ObjectId objectId, String path, ObjectId id) { + public void markFlattenedPath(ObjectId objectId, CayennePath path, ObjectId id) { if(trackedFlattenedPaths == null) { trackedFlattenedPaths = new ConcurrentHashMap<>(); } diff --git a/cayenne/src/main/java/org/apache/cayenne/access/flush/ArcValuesCreationHandler.java b/cayenne/src/main/java/org/apache/cayenne/access/flush/ArcValuesCreationHandler.java index f42c120ac..545fd8e69 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/flush/ArcValuesCreationHandler.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/flush/ArcValuesCreationHandler.java @@ -101,26 +101,20 @@ class ArcValuesCreationHandler implements GraphChangeHandler { ObjectId processFlattenedPath(ObjectId id, ObjectId finalTargetId, DbEntity entity, CayennePath dbPath, boolean add) { Iterator<CayenneMapEntry> dbPathIterator = entity.resolvePathComponents(dbPath); - StringBuilder path = new StringBuilder(); + CayennePath flattenedPath = CayennePath.EMPTY_PATH; ObjectId srcId = id; ObjectId targetId = null; while(dbPathIterator.hasNext()) { CayenneMapEntry entry = dbPathIterator.next(); - if(path.length() > 0) { - path.append('.'); - } - - path.append(entry.getName()); + flattenedPath = flattenedPath.dot(entry.getName()); if(entry instanceof DbRelationship) { DbRelationship relationship = (DbRelationship)entry; // intermediate db entity to be inserted DbEntity target = relationship.getTargetEntity(); // if ID is present, just use it, otherwise create new - String flattenedPath = path.toString(); - - // if this is last segment and it's a relationship, use known target id from arc creation + // if this is last segment, and it's a relationship, use known target id from arc creation if(!dbPathIterator.hasNext()) { targetId = finalTargetId; } else { diff --git a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/Values.java b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/Values.java index f893b09ba..2d5591463 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/Values.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/Values.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import org.apache.cayenne.ObjectId; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbAttribute; /** @@ -43,7 +44,7 @@ public class Values { protected List<DbAttribute> updatedAttributes; // generated flattened Ids for this insert - protected Map<String, ObjectId> flattenedIds; + protected Map<CayennePath, ObjectId> flattenedIds; public Values(DbRowOp row, boolean includeId) { this.row = row; @@ -116,7 +117,7 @@ public class Values { } } - public void addFlattenedId(String path, ObjectId id) { + public void addFlattenedId(CayennePath path, ObjectId id) { if(flattenedIds == null) { flattenedIds = new HashMap<>(); } @@ -146,7 +147,7 @@ public class Values { return attributeSnapshot; } // FK should override attribute values - fkSnapshot.forEach(attributeSnapshot::put); + attributeSnapshot.putAll(fkSnapshot); return attributeSnapshot; } @@ -157,7 +158,7 @@ public class Values { return updatedAttributes; } - public Map<String, ObjectId> getFlattenedIds() { + public Map<CayennePath, ObjectId> getFlattenedIds() { if(flattenedIds == null) { return Collections.emptyMap(); } diff --git a/cayenne/src/main/java/org/apache/cayenne/reflect/ClassDescriptor.java b/cayenne/src/main/java/org/apache/cayenne/reflect/ClassDescriptor.java index 392e73923..763a80e18 100644 --- a/cayenne/src/main/java/org/apache/cayenne/reflect/ClassDescriptor.java +++ b/cayenne/src/main/java/org/apache/cayenne/reflect/ClassDescriptor.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.Map; import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityInheritanceTree; import org.apache.cayenne.map.ObjAttribute; @@ -61,7 +62,7 @@ public interface ClassDescriptor { * @since 4.1 * @return information about additional db entities */ - Map<String, DbEntity> getAdditionalDbEntities(); + Map<CayennePath, DbEntity> getAdditionalDbEntities(); /** * @since 3.0 diff --git a/cayenne/src/main/java/org/apache/cayenne/reflect/LazyClassDescriptorDecorator.java b/cayenne/src/main/java/org/apache/cayenne/reflect/LazyClassDescriptorDecorator.java index 9a7576e9a..826c371ac 100644 --- a/cayenne/src/main/java/org/apache/cayenne/reflect/LazyClassDescriptorDecorator.java +++ b/cayenne/src/main/java/org/apache/cayenne/reflect/LazyClassDescriptorDecorator.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Map; import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityInheritanceTree; import org.apache.cayenne.map.ObjAttribute; @@ -90,7 +91,7 @@ public class LazyClassDescriptorDecorator implements ClassDescriptor { } @Override - public Map<String, DbEntity> getAdditionalDbEntities() { + public Map<CayennePath, DbEntity> getAdditionalDbEntities() { checkDescriptorInitialized(); return descriptor.getAdditionalDbEntities(); } diff --git a/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptor.java b/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptor.java index 1cac8a14e..adbb72e6d 100644 --- a/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptor.java +++ b/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptor.java @@ -22,6 +22,7 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.PersistenceState; import org.apache.cayenne.Persistent; import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityInheritanceTree; import org.apache.cayenne.map.ObjAttribute; @@ -61,7 +62,7 @@ public class PersistentDescriptor implements ClassDescriptor { protected ObjEntity entity; protected Collection<DbEntity> rootDbEntities; - protected Map<String, DbEntity> additionalDbEntities; + protected Map<CayennePath, DbEntity> additionalDbEntities; protected EntityInheritanceTree entityInheritanceTree; @@ -127,7 +128,7 @@ public class PersistentDescriptor implements ClassDescriptor { * @param path path for entity * @param targetEntity additional entity */ - void addAdditionalDbEntity(String path, DbEntity targetEntity) { + void addAdditionalDbEntity(CayennePath path, DbEntity targetEntity) { if(additionalDbEntities == null) { additionalDbEntities = new HashMap<>(); } @@ -231,7 +232,7 @@ public class PersistentDescriptor implements ClassDescriptor { } @Override - public Map<String, DbEntity> getAdditionalDbEntities() { + public Map<CayennePath, DbEntity> getAdditionalDbEntities() { if(additionalDbEntities == null) { return Collections.emptyMap(); } diff --git a/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java b/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java index 103777c33..bd86793ab 100644 --- a/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java +++ b/cayenne/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java @@ -27,6 +27,7 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.exp.Expression; import org.apache.cayenne.exp.TraversalHandler; +import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.DbRelationship; @@ -303,16 +304,13 @@ public abstract class PersistentDescriptorFactory implements ClassDescriptorFact } Iterator<CayenneMapEntry> it = property.getAttribute().getDbPathIterator(); - StringBuilder sb = new StringBuilder(); + CayennePath path = CayennePath.EMPTY_PATH; while(it.hasNext()) { CayenneMapEntry next = it.next(); if(next instanceof DbRelationship) { DbRelationship rel = (DbRelationship)next; - if(sb.length() > 0) { - sb.append('.'); - } - sb.append(rel.getName()); - descriptor.addAdditionalDbEntity(sb.toString(), rel.getTargetEntity()); + path = path.dot(rel.getName()); + descriptor.addAdditionalDbEntity(path, rel.getTargetEntity()); } } return true; @@ -325,15 +323,12 @@ public abstract class PersistentDescriptorFactory implements ClassDescriptorFact } List<DbRelationship> dbRelationships = property.getRelationship().getDbRelationships(); - StringBuilder sb = new StringBuilder(); + CayennePath path = CayennePath.EMPTY_PATH; int count = dbRelationships.size(); for(int i=0; i<count-1; i++) { DbRelationship rel = dbRelationships.get(i); - if(sb.length() > 0) { - sb.append('.'); - } - sb.append(rel.getName()); - descriptor.addAdditionalDbEntity(sb.toString(), rel.getTargetEntity()); + path = path.dot(rel.getName()); + descriptor.addAdditionalDbEntity(path, rel.getTargetEntity()); } return true; }