1 /* 2 * ModeShape (http://www.modeshape.org) 3 * See the COPYRIGHT.txt file distributed with this work for information 4 * regarding copyright ownership. Some portions may be licensed 5 * to Red Hat, Inc. under one or more contributor license agreements. 6 * See the AUTHORS.txt file in the distribution for a full listing of 7 * individual contributors. 8 * 9 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape 10 * is licensed to you under the terms of the GNU Lesser General Public License as 11 * published by the Free Software Foundation; either version 2.1 of 12 * the License, or (at your option) any later version. 13 * 14 * ModeShape is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this software; if not, write to the Free 21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 23 */ 24 package org.modeshape.graph.request; 25 26 import java.util.Collection; 27 import java.util.HashMap; 28 import java.util.Iterator; 29 import java.util.LinkedList; 30 import java.util.List; 31 import java.util.Map; 32 import org.modeshape.common.util.CheckArg; 33 import org.modeshape.common.util.HashCode; 34 import org.modeshape.graph.GraphI18n; 35 import org.modeshape.graph.Location; 36 import org.modeshape.graph.connector.RepositoryConnection; 37 import org.modeshape.graph.property.Name; 38 import org.modeshape.graph.property.Path; 39 import org.modeshape.graph.property.Property; 40 41 /** 42 * Instruction to read the properties and children of the node at the specifed location. 43 */ 44 public class ReadNodeRequest extends CacheableRequest implements Iterable<Location> { 45 46 private static final long serialVersionUID = 1L; 47 48 private final Location at; 49 private final String workspaceName; 50 private final Map<Name, Property> properties = new HashMap<Name, Property>(); 51 private final List<Location> children = new LinkedList<Location>(); 52 private Location actualLocation; 53 54 /** 55 * Create a request to read the properties and number of children of a node at the supplied location. 56 * 57 * @param at the location of the node to be read 58 * @param workspaceName the name of the workspace containing the node 59 * @throws IllegalArgumentException if the location or workspace name is null 60 */ 61 public ReadNodeRequest( Location at, 62 String workspaceName ) { 63 CheckArg.isNotNull(at, "at"); 64 CheckArg.isNotNull(workspaceName, "workspaceName"); 65 this.workspaceName = workspaceName; 66 this.at = at; 67 } 68 69 /** 70 * {@inheritDoc} 71 * 72 * @see org.modeshape.graph.request.Request#isReadOnly() 73 */ 74 @Override 75 public boolean isReadOnly() { 76 return true; 77 } 78 79 /** 80 * Get the location defining the node that is to be read. 81 * 82 * @return the location of the node; never null 83 */ 84 public Location at() { 85 return at; 86 } 87 88 /** 89 * Get the name of the workspace in which the node exists. 90 * 91 * @return the name of the workspace; never null 92 */ 93 public String inWorkspace() { 94 return workspaceName; 95 } 96 97 /** 98 * Get the properties that were read from the {@link RepositoryConnection}. 99 * 100 * @return the properties, as a map of property name to property; never null 101 */ 102 public Map<Name, Property> getPropertiesByName() { 103 return properties; 104 } 105 106 /** 107 * Get the properties that were read from the {@link RepositoryConnection}. 108 * 109 * @return the collection of properties; never null 110 */ 111 public Collection<Property> getProperties() { 112 return properties.values(); 113 } 114 115 /** 116 * Add a property that was read from the {@link RepositoryConnection} 117 * 118 * @param property the property that was read 119 * @return the previous property that had the same name, or null if there was no previously-recorded property with the same 120 * name 121 * @throws IllegalArgumentException if the property is null 122 * @throws IllegalStateException if the request is frozen 123 */ 124 public Property addProperty( Property property ) { 125 checkNotFrozen(); 126 return this.properties.put(property.getName(), property); 127 } 128 129 /** 130 * Add a property that was read from the {@link RepositoryConnection} 131 * 132 * @param properties the properties that were read 133 * @throws IllegalArgumentException if the properties array is null 134 * @throws IllegalStateException if the request is frozen 135 */ 136 public void addProperties( Property... properties ) { 137 checkNotFrozen(); 138 CheckArg.isNotNull(properties, "properties"); 139 for (Property property : properties) { 140 this.properties.put(property.getName(), property); 141 } 142 } 143 144 /** 145 * Add a property that was read from the {@link RepositoryConnection} 146 * 147 * @param properties the properties that were read 148 * @throws IllegalArgumentException if the iterable reference is null 149 * @throws IllegalStateException if the request is frozen 150 */ 151 public void addProperties( Iterable<Property> properties ) { 152 checkNotFrozen(); 153 CheckArg.isNotNull(properties, "properties"); 154 for (Property property : properties) { 155 this.properties.put(property.getName(), property); 156 } 157 } 158 159 /** 160 * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is 161 * represented by a location. 162 * 163 * @return the children that were read; never null 164 */ 165 public List<Location> getChildren() { 166 return children; 167 } 168 169 /** 170 * {@inheritDoc} 171 * 172 * @see java.lang.Iterable#iterator() 173 */ 174 public Iterator<Location> iterator() { 175 return children.iterator(); 176 } 177 178 /** 179 * Add to the list of children that has been read the supplied children with the given path and identification properties. The 180 * children are added in order. 181 * 182 * @param children the locations of the children that were read 183 * @throws IllegalArgumentException if the parameter is null 184 * @throws IllegalStateException if the request is frozen 185 * @see #addChild(Location) 186 * @see #addChild(Path, Property) 187 * @see #addChild(Path, Property, Property...) 188 */ 189 public void addChildren( Iterable<Location> children ) { 190 checkNotFrozen(); 191 CheckArg.isNotNull(children, "children"); 192 for (Location child : children) { 193 if (child != null) this.children.add(child); 194 } 195 } 196 197 /** 198 * Add to the list of children that has been read the child with the given path and identification properties. The children 199 * should be added in order. 200 * 201 * @param child the location of the child that was read 202 * @throws IllegalArgumentException if the location is null 203 * @throws IllegalStateException if the request is frozen 204 * @see #addChild(Path, Property) 205 * @see #addChild(Path, Property, Property...) 206 */ 207 public void addChild( Location child ) { 208 checkNotFrozen(); 209 CheckArg.isNotNull(child, "child"); 210 this.children.add(child); 211 } 212 213 /** 214 * Add to the list of children that has been read the child with the given path and identification properties. The children 215 * should be added in order. 216 * 217 * @param pathToChild the path of the child that was just read 218 * @param firstIdProperty the first identification property of the child that was just read 219 * @param remainingIdProperties the remaining identification properties of the child that was just read 220 * @throws IllegalArgumentException if the path or identification properties are null 221 * @throws IllegalStateException if the request is frozen 222 * @see #addChild(Location) 223 * @see #addChild(Path, Property) 224 */ 225 public void addChild( Path pathToChild, 226 Property firstIdProperty, 227 Property... remainingIdProperties ) { 228 checkNotFrozen(); 229 Location child = Location.create(pathToChild, firstIdProperty, remainingIdProperties); 230 this.children.add(child); 231 } 232 233 /** 234 * Add to the list of children that has been read the child with the given path and identification property. The children 235 * should be added in order. 236 * 237 * @param pathToChild the path of the child that was just read 238 * @param idProperty the identification property of the child that was just read 239 * @throws IllegalArgumentException if the path or identification properties are null 240 * @throws IllegalStateException if the request is frozen 241 * @see #addChild(Location) 242 * @see #addChild(Path, Property, Property...) 243 */ 244 public void addChild( Path pathToChild, 245 Property idProperty ) { 246 checkNotFrozen(); 247 Location child = Location.create(pathToChild, idProperty); 248 this.children.add(child); 249 } 250 251 /** 252 * Sets the actual and complete location of the node whose children and properties have been read. This method must be called 253 * when processing the request, and the actual location must have a {@link Location#getPath() path}. 254 * 255 * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used 256 * @throws IllegalArgumentException if the actual location is null or does not have a path. 257 * @throws IllegalStateException if the request is frozen 258 */ 259 public void setActualLocationOfNode( Location actual ) { 260 checkNotFrozen(); 261 CheckArg.isNotNull(actual, "actual"); 262 if (!actual.hasPath()) { 263 throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual)); 264 } 265 this.actualLocation = actual; 266 } 267 268 /** 269 * Get the actual location of the node whose children and properties were read. 270 * 271 * @return the actual location, or null if the actual location was not set 272 */ 273 public Location getActualLocationOfNode() { 274 return actualLocation; 275 } 276 277 /** 278 * {@inheritDoc} 279 * 280 * @see org.modeshape.graph.request.Request#cancel() 281 */ 282 @Override 283 public void cancel() { 284 super.cancel(); 285 this.actualLocation = null; 286 this.children.clear(); 287 this.properties.clear(); 288 } 289 290 /** 291 * {@inheritDoc} 292 * 293 * @see java.lang.Object#hashCode() 294 */ 295 @Override 296 public int hashCode() { 297 return HashCode.compute(at, workspaceName); 298 } 299 300 /** 301 * {@inheritDoc} 302 * 303 * @see java.lang.Object#equals(java.lang.Object) 304 */ 305 @Override 306 public boolean equals( Object obj ) { 307 if (obj == this) return true; 308 if (this.getClass().isInstance(obj)) { 309 ReadNodeRequest that = (ReadNodeRequest)obj; 310 if (!this.at().isSame(that.at())) return false; 311 if (!this.inWorkspace().equals(that.inWorkspace())) return false; 312 return true; 313 } 314 return false; 315 } 316 317 /** 318 * {@inheritDoc} 319 * 320 * @see java.lang.Object#toString() 321 */ 322 @Override 323 public String toString() { 324 return "read node at " + at() + " in the \"" + workspaceName + "\" workspace"; 325 } 326 327 @Override 328 public RequestType getType() { 329 return RequestType.READ_NODE; 330 } 331 }