Author: aadamchik
Date: Sat Jan 21 21:15:43 2012
New Revision: 1234419
URL: http://svn.apache.org/viewvc?rev=1234419&view=rev
Log:
CAY-1616 Remove internal dependencies on deprecated ObjectContext.localObject
splitting merge method into an action class: ShallowMergeOperation
it is possible as now it no longer depends on the context implementation
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java?rev=1234419&r1=1234418&r2=1234419&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
Sat Jan 21 21:15:43 2012
@@ -37,19 +37,21 @@ import org.apache.cayenne.reflect.ToMany
import org.apache.cayenne.reflect.ToOneProperty;
/**
- * An operation that performs object graph deep merge, terminating merge at
unresolved
- * nodes.
+ * An operation that merges changes from an object graph, whose objects are
registered in
+ * some ObjectContext, to peer objects in an ObjectConext that is a child of
that context.
+ * The merge terminates at hollow nodes in the parent context to avoid
tripping over
+ * unresolved relationships.
*
* @since 1.2
*/
public class DeepMergeOperation {
- protected ObjectContext context;
- protected Map<ObjectId, Persistent> seen;
+ private Map<ObjectId, Persistent> seen;
+ private ShallowMergeOperation shallowMergeOperation;
public DeepMergeOperation(ObjectContext context) {
- this.context = context;
this.seen = new HashMap<ObjectId, Persistent>();
+ this.shallowMergeOperation = new ShallowMergeOperation(context);
}
public void reset() {
@@ -75,7 +77,7 @@ public class DeepMergeOperation {
return seenTarget;
}
- final Persistent target = context.localObject(id, source);
+ final Persistent target = shallowMergeOperation.merge(source);
seen.put(id, target);
descriptor = descriptor.getSubclassDescriptor(source.getClass());
@@ -101,17 +103,17 @@ public class DeepMergeOperation {
public boolean visitToMany(ToManyProperty property) {
if (!property.isFault(source)) {
Object value = property.readProperty(source);
- Object targetValue;
-
+ Object targetValue;
+
if (property instanceof ToManyMapProperty) {
Map<?, ?> map = (Map) value;
Map targetMap = new HashMap();
-
+
for (Entry entry : map.entrySet()) {
Object destinationSource = entry.getValue();
- Object destinationTarget = destinationSource !=
null
- ? merge(destinationSource,
property.getTargetDescriptor())
- : null;
+ Object destinationTarget = destinationSource !=
null ? merge(
+ destinationSource,
+ property.getTargetDescriptor()) : null;
targetMap.put(entry.getKey(), destinationTarget);
}
@@ -122,9 +124,9 @@ public class DeepMergeOperation {
Collection targetCollection = new
ArrayList(collection.size());
for (Object destinationSource : collection) {
- Object destinationTarget = destinationSource !=
null
- ? merge(destinationSource,
property.getTargetDescriptor())
- : null;
+ Object destinationTarget = destinationSource !=
null ? merge(
+ destinationSource,
+ property.getTargetDescriptor()) : null;
targetCollection.add(destinationTarget);
}
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java?rev=1234419&r1=1234418&r2=1234419&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
Sat Jan 21 21:15:43 2012
@@ -48,7 +48,7 @@ import org.apache.cayenne.reflect.ClassD
* <p>
* <i>Intended for internal use only.</i>
* </p>
- *
+ *
* @since 1.2
*/
public abstract class ObjectContextQueryAction {
@@ -120,6 +120,7 @@ public abstract class ObjectContextQuery
// rewrite response to contain objects from the query context
GenericResponse childResponse = new GenericResponse();
+ ShallowMergeOperation merger = null;
for (response.reset(); response.next();) {
if (response.isList()) {
@@ -130,6 +131,10 @@ public abstract class ObjectContextQuery
}
else {
+ if (merger == null) {
+ merger = new ShallowMergeOperation(targetContext);
+ }
+
// TODO: Andrus 1/31/2006 - IncrementalFaultList is
not properly
// transferred between contexts....
@@ -137,8 +142,7 @@ public abstract class ObjectContextQuery
Iterator it = objects.iterator();
while (it.hasNext()) {
Persistent object = (Persistent) it.next();
- childObjects.add(targetContext.localObject(object
- .getObjectId(), object));
+ childObjects.add(merger.merge(object));
}
childResponse.addResultList(childObjects);
@@ -245,17 +249,17 @@ public abstract class ObjectContextQuery
}
/**
- * Workaround for CAY-1183. If a Relationship query is
being sent from
- * child context, we assure that local object is not
NEW and relationship - unresolved
- * (this way exception will occur). This helps when
faulting objects that
- * were committed to parent context (this), but not to
database.
- *
- * Checking type of context's channel is the only way
to ensure that we are
- * on the top level of context hierarchy (there might
be more than one-level-deep
+ * Workaround for CAY-1183. If a Relationship query is
being sent
+ * from child context, we assure that local object is
not NEW and
+ * relationship - unresolved (this way exception will
occur). This
+ * helps when faulting objects that were committed to
parent
+ * context (this), but not to database. Checking type
of context's
+ * channel is the only way to ensure that we are on
the top level
+ * of context hierarchy (there might be more than
one-level-deep
* nested contexts).
*/
if (((Persistent) object).getPersistenceState() ==
PersistenceState.NEW
- && !(actingContext.getChannel() instanceof
BaseContext)) {
+ && !(actingContext.getChannel() instanceof
BaseContext)) {
this.response = new ListResponse();
return DONE;
}
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java?rev=1234419&view=auto
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
(added)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ShallowMergeOperation.java
Sat Jan 21 21:15:43 2012
@@ -0,0 +1,95 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.util;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.PersistenceState;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.graph.GraphManager;
+import org.apache.cayenne.reflect.ClassDescriptor;
+
+/**
+ * An operation that merges changes from a single object registered in some
ObjectContext,
+ * to a peer object in an ObjectConext that is a child of that context.
+ *
+ * @since 3.1
+ */
+public class ShallowMergeOperation {
+
+ private final ObjectContext context;
+
+ public ShallowMergeOperation(ObjectContext context) {
+ this.context = context;
+ }
+
+ public Persistent merge(Persistent peerInParentContext) {
+
+ if (peerInParentContext == null) {
+ throw new IllegalArgumentException("Null peerInParentContext");
+ }
+
+ // handling of HOLLOW peer state is here for completeness... Wonder if
we ever
+ // have a case where it is applicable.
+ int peerState = peerInParentContext.getPersistenceState();
+
+ ObjectId id = peerInParentContext.getObjectId();
+
+ ClassDescriptor descriptor =
context.getEntityResolver().getClassDescriptor(
+ id.getEntityName());
+
+ GraphManager graphManager = context.getGraphManager();
+
+ // have to synchronize almost the entire method to prevent multiple
threads from
+ // messing up dataobjects per CAY-845.
+ synchronized (graphManager) {
+ Persistent object = (Persistent) graphManager.getNode(id);
+
+ // merge into an existing object
+ if (object == null) {
+ object = (Persistent) descriptor.createObject();
+ object.setObjectContext(context);
+ object.setObjectId(id);
+
+ if (peerState == PersistenceState.HOLLOW) {
+ object.setPersistenceState(PersistenceState.HOLLOW);
+ }
+ else {
+ object.setPersistenceState(PersistenceState.COMMITTED);
+ }
+
+ graphManager.registerNode(id, object);
+ }
+
+ // TODO: Andrus, 1/24/2006 implement smart merge for modified
objects...
+ if (peerState != PersistenceState.HOLLOW
+ && object.getPersistenceState() !=
PersistenceState.MODIFIED
+ && object.getPersistenceState() !=
PersistenceState.DELETED) {
+
+ descriptor.shallowMerge(peerInParentContext, object);
+
+ if (object.getPersistenceState() == PersistenceState.HOLLOW) {
+ object.setPersistenceState(PersistenceState.COMMITTED);
+ }
+ }
+
+ return object;
+ }
+ }
+}