1 19 20 package org.apache.cayenne; 21 22 import org.apache.cayenne.graph.GraphChangeHandler; 23 import org.apache.cayenne.graph.GraphDiff; 24 import org.apache.cayenne.graph.GraphEvent; 25 import org.apache.cayenne.reflect.ArcProperty; 26 import org.apache.cayenne.reflect.ClassDescriptor; 27 import org.apache.cayenne.reflect.Property; 28 import org.apache.cayenne.reflect.ToManyProperty; 29 import org.apache.cayenne.util.Util; 30 31 39 class CayenneContextMergeHandler implements GraphChangeHandler, DataChannelListener { 40 41 CayenneContext context; 42 boolean active; 43 44 CayenneContextMergeHandler(CayenneContext context) { 45 this.context = context; 46 this.active = true; 47 } 48 49 51 public void graphChanged(final GraphEvent e) { 52 if (shouldProcessEvent(e) && e.getDiff() != null) { 54 runWithEventsDisabled(new Runnable () { 55 56 public void run() { 57 e.getDiff().apply(CayenneContextMergeHandler.this); 58 59 } 60 }); 61 62 repostAfterMerge(e); 64 } 65 } 66 67 public void graphFlushed(final GraphEvent e) { 68 70 76 79 if (shouldProcessEvent(e)) { 80 81 runWithEventsDisabled(new Runnable () { 82 83 public void run() { 84 85 if (e.getDiff() != null) { 86 e.getDiff().apply(CayenneContextMergeHandler.this); 87 } 88 } 89 }); 90 91 repostAfterMerge(e); 93 } 94 } 95 96 public void graphRolledback(final GraphEvent e) { 97 98 } 102 103 105 void repostAfterMerge(GraphEvent originalEvent) { 106 if (context.isLifecycleEventsEnabled()) { 108 context.internalGraphManager().send( 109 originalEvent.getDiff(), 110 DataChannel.GRAPH_CHANGED_SUBJECT, 111 originalEvent.getSource()); 112 } 113 } 114 115 118 void merge(final GraphDiff diff) { 119 runWithEventsDisabled(new Runnable () { 120 121 public void run() { 122 diff.apply(CayenneContextMergeHandler.this); 123 } 124 }); 125 } 126 127 129 public void nodeIdChanged(Object nodeId, Object newId) { 130 Object node = context.internalGraphManager().getNode(nodeId); 133 134 if (node != null) { 135 context.internalGraphManager().deadIds().add(nodeId); 136 context.internalGraphManager().registerNode(newId, node); 137 138 if (node instanceof Persistent) { 139 ((Persistent) node).setObjectId((ObjectId) newId); 141 } 142 } 143 } 144 145 public void nodeCreated(Object nodeId) { 146 } 148 149 public void nodeRemoved(Object nodeId) { 150 context.getGraphManager().unregisterNode(nodeId); 151 } 152 153 public void nodePropertyChanged( 154 Object nodeId, 155 String property, 156 Object oldValue, 157 Object newValue) { 158 159 Object object = context.internalGraphManager().getNode(nodeId); 160 if (object != null) { 161 162 Property p = propertyForId(nodeId, property); 164 if (Util.nullSafeEquals(p.readPropertyDirectly(object), oldValue)) { 165 166 p.writePropertyDirectly(object, oldValue, newValue); 167 } 168 } 169 } 170 171 public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) { 172 175 Object source = context.internalGraphManager().getNode(nodeId); 176 if (source == null) { 177 return; 179 } 180 181 184 ArcProperty p = (ArcProperty) propertyForId(nodeId, arcId.toString()); 185 if (p.isFault(source)) { 186 return; 187 } 188 189 Object target = context.internalGraphManager().getNode(targetNodeId); 190 if (target == null) { 191 target = context.createFault((ObjectId) targetNodeId); 192 } 193 194 context.internalGraphAction().setArcChangeInProcess(true); 195 try { 196 if (p instanceof ToManyProperty) { 197 ((ToManyProperty) p).addTarget(source, target, false); 198 } 199 else { 200 p.writePropertyDirectly(source, null, target); 201 } 202 } 203 finally { 204 context.internalGraphAction().setArcChangeInProcess(false); 205 } 206 } 207 208 public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) { 209 210 213 Object source = context.internalGraphManager().getNode(nodeId); 214 if (source == null) { 215 return; 217 } 218 219 ArcProperty p = (ArcProperty) propertyForId(nodeId, arcId.toString()); 221 if (p.isFault(source)) { 222 return; 223 } 224 225 Object target = context.internalGraphManager().getNode(targetNodeId); 226 if (target == null) { 227 target = context.createFault((ObjectId) targetNodeId); 228 } 229 230 context.internalGraphAction().setArcChangeInProcess(true); 231 try { 232 if (p instanceof ToManyProperty) { 233 ((ToManyProperty) p).removeTarget(source, target, false); 234 } 235 else { 236 p.writePropertyDirectly(source, target, null); 237 } 238 } 239 finally { 240 context.internalGraphAction().setArcChangeInProcess(false); 241 } 242 } 243 244 private Property propertyForId(Object nodeId, String propertyName) { 245 ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor( 246 ((ObjectId) nodeId).getEntityName()); 247 return descriptor.getProperty(propertyName); 248 } 249 250 boolean shouldProcessEvent(GraphEvent e) { 253 return active 256 && e.getSource() == context.getChannel() 257 && e.getPostedBy() != context 258 && e.getPostedBy() != context.getChannel(); 259 } 260 261 264 private void runWithEventsDisabled(Runnable closure) { 265 266 synchronized (context.internalGraphManager()) { 267 boolean changeEventsEnabled = context.internalGraphManager().changeEventsEnabled; 268 context.internalGraphManager().changeEventsEnabled = false; 269 270 boolean lifecycleEventsEnabled = context.internalGraphManager().lifecycleEventsEnabled; 271 context.internalGraphManager().lifecycleEventsEnabled = false; 272 273 try { 274 closure.run(); 275 } 276 finally { 277 context.internalGraphManager().changeEventsEnabled = changeEventsEnabled; 278 context.internalGraphManager().lifecycleEventsEnabled = lifecycleEventsEnabled; 279 } 280 } 281 } 282 } 283 | Popular Tags |