1 19 20 package org.apache.cayenne.util; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 28 import org.apache.cayenne.CayenneRuntimeException; 29 import org.apache.cayenne.ObjectContext; 30 import org.apache.cayenne.ObjectId; 31 import org.apache.cayenne.Persistent; 32 import org.apache.cayenne.reflect.AttributeProperty; 33 import org.apache.cayenne.reflect.ClassDescriptor; 34 import org.apache.cayenne.reflect.PropertyVisitor; 35 import org.apache.cayenne.reflect.ToManyProperty; 36 import org.apache.cayenne.reflect.ToOneProperty; 37 38 45 public class DeepMergeOperation { 46 47 protected ObjectContext context; 48 protected Map seen; 49 50 public DeepMergeOperation(ObjectContext context) { 51 this.context = context; 52 this.seen = new HashMap (); 53 } 54 55 public void reset() { 56 seen.clear(); 57 } 58 59 public Object merge(Object object, ClassDescriptor descriptor) { 60 if (!(object instanceof Persistent)) { 61 throw new CayenneRuntimeException("Expected Persistent, got: " + object); 62 } 63 64 final Persistent source = (Persistent) object; 65 ObjectId id = source.getObjectId(); 66 67 if (id == null) { 69 throw new CayenneRuntimeException("Server returned an object without an id: " 70 + source); 71 } 72 73 Object seenTarget = seen.get(id); 74 if (seenTarget != null) { 75 return seenTarget; 76 } 77 78 final Persistent target = context.localObject(id, source); 79 seen.put(id, target); 80 81 descriptor = descriptor.getSubclassDescriptor(source.getClass()); 82 descriptor.visitProperties(new PropertyVisitor() { 83 84 public boolean visitToOne(ToOneProperty property) { 85 86 if (!property.isFault(source)) { 87 Object destinationSource = property.readProperty(source); 88 89 Object destinationTarget = destinationSource != null ? merge( 90 destinationSource, 91 property.getTargetDescriptor()) : null; 92 93 Object oldTarget = property.isFault(target) ? null : property 94 .readProperty(target); 95 property.writePropertyDirectly(target, oldTarget, destinationTarget); 96 } 97 98 return true; 99 } 100 101 public boolean visitToMany(ToManyProperty property) { 102 if (!property.isFault(source)) { 103 Collection collection = (Collection ) property.readProperty(source); 104 105 Collection targetCollection = new ArrayList (collection.size()); 106 107 Iterator it = collection.iterator(); 108 while (it.hasNext()) { 109 Object destinationSource = it.next(); 110 Object destinationTarget = destinationSource != null ? merge( 111 destinationSource, 112 property.getTargetDescriptor()) : null; 113 114 targetCollection.add(destinationTarget); 115 } 116 117 property.writePropertyDirectly(target, null, targetCollection); 118 } 119 120 return true; 121 } 122 123 public boolean visitAttribute(AttributeProperty property) { 124 return true; 125 } 126 }); 127 128 return target; 129 } 130 } 131 | Popular Tags |