1 7 package org.jboss.cache.optimistic; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.AbstractNode; 12 import org.jboss.cache.CacheSPI; 13 import org.jboss.cache.Fqn; 14 import org.jboss.cache.GlobalTransaction; 15 import org.jboss.cache.Node; 16 import org.jboss.cache.NodeSPI; 17 import org.jboss.cache.VersionedNode; 18 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.HashSet ; 22 import java.util.Map ; 23 import java.util.Set ; 24 import java.util.concurrent.ConcurrentHashMap ; 25 26 32 public class WorkspaceNodeImpl extends AbstractNode implements WorkspaceNode 33 { 34 35 private static Log log = LogFactory.getLog(WorkspaceNodeImpl.class); 36 37 private NodeSPI node; 38 private TransactionWorkspace workspace; 39 private DataVersion version = DefaultDataVersion.ZERO; 40 private boolean dirty; 41 private boolean created; 42 private Map <Object , NodeSPI> optimisticChildNodeMap; 43 private Map <Object , Object > optimisticDataMap; 44 private boolean versioningImplicit; 45 46 49 public WorkspaceNodeImpl(NodeSPI node, TransactionWorkspace workspace) 50 { 51 if (!(node instanceof VersionedNode)) 52 { 53 throw new IllegalArgumentException ("node " + node + " not VersionedNode"); 54 } 55 this.node = node; 56 this.workspace = workspace; 57 optimisticDataMap = new HashMap <Object , Object >(node.getDataDirect()); 58 Map <Object , Node> childrenMap = node.getChildrenMapDirect(); 59 if (childrenMap == null) 60 { 61 optimisticChildNodeMap = new ConcurrentHashMap <Object , NodeSPI>(); 62 } 63 else 64 { 65 optimisticChildNodeMap = new ConcurrentHashMap (childrenMap); 66 } 67 this.version = node.getVersion(); 68 if (version == null) 69 { 70 throw new IllegalStateException ("VersionedNode version null"); 71 } 72 } 73 74 77 public boolean isDirty() 78 { 79 return dirty; 80 } 81 82 public Fqn getFqn() 83 { 84 return node.getFqn(); 85 } 86 87 public void put(Map <Object , Object > data) 88 { 89 realPut(data, false); 90 dirty = true; 91 } 92 93 public Object put(Object key, Object value) 94 { 95 dirty = true; 96 return optimisticDataMap.put(key, value); 97 98 } 99 100 public Object remove(Object key) 101 { 102 dirty = true; 103 return optimisticDataMap.remove(key); 104 105 } 106 107 public Object get(Object key) 108 { 109 return optimisticDataMap.get(key); 110 } 111 112 public Set <Object > getKeys() 113 { 114 return optimisticDataMap.keySet(); 115 } 116 117 public Set <Object > getChildrenNames() 119 { 120 return new HashSet <Object >(optimisticChildNodeMap.keySet()); 121 } 122 123 private void realPut(Map <Object , Object > data, boolean eraseData) 124 { 125 realPut(data, eraseData, true); 126 } 127 128 private void realPut(Map <Object , Object > data, boolean eraseData, boolean forceDirtyFlag) 129 { 130 if (forceDirtyFlag) dirty = true; 131 if (eraseData) 132 { 133 optimisticDataMap.clear(); 134 } 135 if (data != null) optimisticDataMap.putAll(data); 136 } 137 138 public Node getParent() 139 { 140 return node.getParent(); 141 } 142 143 public NodeSPI createChild(Object child_name, NodeSPI parent, CacheSPI cache, DataVersion version) 144 { 145 if (child_name == null) 146 { 147 return null; 148 } 149 150 NodeSPI child = optimisticChildNodeMap.get(child_name); 152 153 if (child == null) 155 { 156 Fqn childFqn = new Fqn(parent.getFqn(), child_name); 157 child = (NodeSPI) cache.getConfiguration().getRuntimeConfig().getNodeFactory().createNodeOfType(parent, child_name, parent, null); 158 optimisticChildNodeMap.put(child_name, child); 159 } 160 dirty = true; 161 return child; 162 } 163 164 public boolean isVersioningImplicit() 165 { 166 return versioningImplicit; 167 } 168 169 public void setVersioningImplicit(boolean b) 170 { 171 versioningImplicit = b; 172 } 173 174 public NodeSPI getChild(Object childName) 175 { 176 return optimisticChildNodeMap.get(childName); 178 } 179 180 public NodeSPI getNode() 181 { 182 return node; 183 } 184 185 public DataVersion getVersion() 186 { 187 return version; 188 } 189 190 public void setVersion(DataVersion version) 191 { 192 this.version = version; 193 } 194 195 public Map <Object , NodeSPI> getMergedChildren() 196 { 197 return optimisticChildNodeMap; 198 } 199 200 public Map <Object , Object > getMergedData() 201 { 202 return optimisticDataMap; 203 } 204 205 public TransactionWorkspace getTransactionWorkspace() 206 { 207 return workspace; 208 } 209 210 public boolean isCreated() 211 { 212 return created; 213 } 214 215 public void markAsCreated() 216 { 217 created = true; 218 dirty = true; 219 } 220 221 public Map <Object , Object > getData() 222 { 223 return Collections.unmodifiableMap(optimisticDataMap); 224 } 225 226 public String toString() 227 { 228 StringBuffer sb = new StringBuffer (); 229 if (deleted) sb.append("del "); 230 if (dirty) sb.append("dirty "); 231 if (created) sb.append("new "); 232 return getClass().getSimpleName() + " [ fqn=" + getFqn() + " " + sb + "ver=" + version + "]"; 233 } 234 235 public Node addChild(Fqn f) 236 { 237 CacheSPI cache = getCache(); 238 Node newNode = this; 239 GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction(); 240 241 if (f.size() == 1) 242 { 243 newNode = createChild(f.get(0), node, getCache(), version); 244 } 245 else 246 { 247 Node currentParent = this; 249 for (Object o : f.peekElements()) 250 { 251 if (currentParent instanceof WorkspaceNode) 252 { 253 newNode = ((WorkspaceNode) currentParent).getNode().getOrCreateChild(o, gtx); 254 } 255 else 256 { 257 if (currentParent instanceof WorkspaceNode) 258 { 259 newNode = ((WorkspaceNode) currentParent).getNode().getOrCreateChild(o, gtx); 260 } 261 else 262 { 263 newNode = ((NodeSPI) currentParent).getOrCreateChild(o, gtx); 264 } 265 } 266 currentParent = newNode; 267 } 268 } 269 return newNode; 270 } 271 272 public void clearData() 273 { 274 dirty = true; 275 optimisticDataMap.clear(); 276 } 277 278 public NodeSPI getChild(Fqn f) 279 { 280 if (f.size() > 1) 281 { 282 throw new UnsupportedOperationException ("Workspace node does not support fetching indirect children"); 283 } 284 return getChild(f.getLastElement()); 285 } 286 287 public Set <Node> getChildren() 288 { 289 throw new UnsupportedOperationException (); 290 } 291 292 public boolean hasChild(Fqn f) 293 { 294 throw new UnsupportedOperationException (); 295 } 296 297 public NodeSPI getNodeSPI() 298 { 299 throw new UnsupportedOperationException ("WorkspaceNode has no access to a NodeSPI"); 300 } 301 302 public void putIfAbsent(Object k, Object v) 303 { 304 throw new UnsupportedOperationException (); 305 } 306 307 public void putIfAbsent(Map <Object , Object > m) 308 { 309 throw new UnsupportedOperationException (); 310 } 311 312 public void removeChild(Fqn f) 313 { 314 if (f.size() > 1) throw new UnsupportedOperationException ("Workspace nodes can only remove direct children!"); 315 Object key = f.getLastElement(); 316 removeChild(key); 317 } 318 319 public void removeChild(Object childName) 320 { 321 if (optimisticChildNodeMap.containsKey(childName)) 322 { 323 dirty = true; 324 optimisticChildNodeMap.remove(childName); 325 } 326 } 327 328 protected CacheSPI getCache() 329 { 330 return node.getCache(); 331 } 332 } 333 | Popular Tags |