001 /* 002 * JBoss DNA (http://www.jboss.org/dna) 003 * See the COPYRIGHT.txt file distributed with this work for information 004 * regarding copyright ownership. Some portions may be licensed 005 * to Red Hat, Inc. under one or more contributor license agreements. 006 * See the AUTHORS.txt file in the distribution for a full listing of 007 * individual contributors. 008 * 009 * Unless otherwise indicated, all code in JBoss DNA is licensed 010 * to you under the terms of the GNU Lesser General Public License as 011 * published by the Free Software Foundation; either version 2.1 of 012 * the License, or (at your option) any later version. 013 * 014 * JBoss DNA is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 * Lesser General Public License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this software; if not, write to the Free 021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 023 */ 024 package org.jboss.dna.graph.request; 025 026 import java.util.HashMap; 027 import java.util.Iterator; 028 import java.util.Map; 029 import org.jboss.dna.graph.Location; 030 import org.jboss.dna.graph.NodeConflictBehavior; 031 import org.jboss.dna.graph.property.Name; 032 import org.jboss.dna.graph.property.Path; 033 import org.jboss.dna.graph.property.Property; 034 import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior; 035 import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior; 036 037 /** 038 * A component that can be used to build requests while allowing different strategies for how requests are handled. Subclasses can 039 * simply override the {@link #process(Request)} method to define what happens with each request. 040 */ 041 public abstract class RequestBuilder { 042 043 /** 044 * Create a new builder. 045 */ 046 protected RequestBuilder() { 047 } 048 049 protected abstract <T extends Request> T process( T request ); 050 051 /** 052 * Add a request to obtain the information about the available workspaces. 053 * 054 * @return the request; never null 055 */ 056 public GetWorkspacesRequest getWorkspaces() { 057 GetWorkspacesRequest request = new GetWorkspacesRequest(); 058 process(request); 059 return request; 060 } 061 062 /** 063 * Add a request to verify the existance of the named workspace. 064 * 065 * @param workspaceName the desired name of the workspace, or null if the source's default workspace should be used 066 * @return the request; never null 067 */ 068 public VerifyWorkspaceRequest verifyWorkspace( String workspaceName ) { 069 return process(new VerifyWorkspaceRequest(workspaceName)); 070 } 071 072 /** 073 * Add a request to create a new workspace, and specify the behavior should a workspace already exists with a name that 074 * matches the desired name for the new workspace. 075 * 076 * @param desiredNameOfNewWorkspace the desired name of the new workspace 077 * @param createConflictBehavior the behavior if a workspace already exists with the same name, or null if the default 078 * behavior should be used 079 * @return the request; never null 080 */ 081 public CreateWorkspaceRequest createWorkspace( String desiredNameOfNewWorkspace, 082 CreateConflictBehavior createConflictBehavior ) { 083 return process(new CreateWorkspaceRequest(desiredNameOfNewWorkspace, createConflictBehavior)); 084 } 085 086 /** 087 * Add a request to clone an existing workspace to create a new workspace, and specify the behavior should a workspace already 088 * exists with a name that matches the desired name for the new workspace. 089 * 090 * @param nameOfWorkspaceToBeCloned the name of the existing workspace that is to be cloned 091 * @param desiredNameOfTargetWorkspace the desired name of the target workspace 092 * @param createConflictBehavior the behavior if a workspace already exists with the same name 093 * @param cloneConflictBehavior the behavior if the workspace to be cloned does not exist 094 * @return the request; never null 095 * @throws IllegalArgumentException if the either workspace name is null 096 */ 097 public CloneWorkspaceRequest cloneWorkspace( String nameOfWorkspaceToBeCloned, 098 String desiredNameOfTargetWorkspace, 099 CreateConflictBehavior createConflictBehavior, 100 CloneConflictBehavior cloneConflictBehavior ) { 101 return process(new CloneWorkspaceRequest(nameOfWorkspaceToBeCloned, desiredNameOfTargetWorkspace, createConflictBehavior, 102 cloneConflictBehavior)); 103 } 104 105 /** 106 * Add a request to destroy an existing workspace. 107 * 108 * @param workspaceName the name of the workspace that is to be destroyed 109 * @return the request; never null 110 * @throws IllegalArgumentException if the workspace name is null 111 */ 112 public DestroyWorkspaceRequest destroyWorkspace( String workspaceName ) { 113 return process(new DestroyWorkspaceRequest(workspaceName)); 114 } 115 116 /** 117 * Add a request to verify the existance and location of a node at the supplied location. 118 * 119 * @param at the location of the node to be verified 120 * @param workspaceName the name of the workspace containing the node 121 * @return the request; never null 122 * @throws IllegalArgumentException if the location or workspace name is null 123 */ 124 public VerifyNodeExistsRequest verifyNodeExists( Location at, 125 String workspaceName ) { 126 return process(new VerifyNodeExistsRequest(at, workspaceName)); 127 } 128 129 /** 130 * Add a request to read the properties and number of children of a node at the supplied location. 131 * 132 * @param at the location of the node to be read 133 * @param workspaceName the name of the workspace containing the node 134 * @return the request; never null 135 * @throws IllegalArgumentException if the location or workspace name is null 136 */ 137 public ReadNodeRequest readNode( Location at, 138 String workspaceName ) { 139 return process(new ReadNodeRequest(at, workspaceName)); 140 } 141 142 /** 143 * Add a request to read the children of a node at the supplied location in the designated workspace. 144 * 145 * @param of the location of the node whose children are to be read 146 * @param workspaceName the name of the workspace 147 * @return the request; never null 148 * @throws IllegalArgumentException if the location or workspace name is null 149 */ 150 public ReadAllChildrenRequest readAllChildren( Location of, 151 String workspaceName ) { 152 return process(new ReadAllChildrenRequest(of, workspaceName)); 153 } 154 155 /** 156 * Add a request to read the properties and number of children of a node at the supplied location. 157 * 158 * @param of the location of the node whose children are to be read 159 * @param workspaceName the name of the workspace 160 * @return the request; never null 161 * @throws IllegalArgumentException if the location or workspace name is null 162 */ 163 public ReadAllPropertiesRequest readAllProperties( Location of, 164 String workspaceName ) { 165 return process(new ReadAllPropertiesRequest(of, workspaceName)); 166 } 167 168 /** 169 * Add a request to read the properties and number of children of a node at the supplied location. 170 * 171 * @param of the location of the node whose children are to be read 172 * @param workspaceName the name of the workspace 173 * @param propertyName the name of the property to read 174 * @return the request; never null 175 * @throws IllegalArgumentException if the location or workspace name is null 176 */ 177 public ReadPropertyRequest readProperty( Location of, 178 String workspaceName, 179 Name propertyName ) { 180 return process(new ReadPropertyRequest(of, workspaceName, propertyName)); 181 } 182 183 /** 184 * Add a request to read the branch at the supplied location, to a maximum depth of 2. 185 * 186 * @param at the location of the branch 187 * @param workspaceName the name of the workspace containing the branch 188 * @return the request; never null 189 * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive 190 */ 191 public ReadBranchRequest readBranch( Location at, 192 String workspaceName ) { 193 return process(new ReadBranchRequest(at, workspaceName)); 194 } 195 196 /** 197 * Add a request to read the branch (of given depth) at the supplied location. 198 * 199 * @param at the location of the branch 200 * @param workspaceName the name of the workspace containing the branch 201 * @param maxDepth the maximum depth to read 202 * @return the request; never null 203 * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive 204 */ 205 public ReadBranchRequest readBranch( Location at, 206 String workspaceName, 207 int maxDepth ) { 208 return process(new ReadBranchRequest(at, workspaceName, maxDepth)); 209 } 210 211 /** 212 * Add a request to read a block of the children of a node at the supplied location. The block is defined by the starting 213 * index of the first child and the number of children to include. Note that this index is <i>not</i> the 214 * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in 215 * an array. 216 * 217 * @param of the location of the node whose children are to be read 218 * @param workspaceName the name of the workspace containing the parent 219 * @param startingIndex the zero-based index of the first child to be included in the block 220 * @param count the maximum number of children that should be included in the block 221 * @return the request; never null 222 * @throws IllegalArgumentException if the location or workspace name is null, if <code>startingIndex</code> is negative, or 223 * if <code>count</count> is less than 1. 224 */ 225 public ReadBlockOfChildrenRequest readBlockOfChildren( Location of, 226 String workspaceName, 227 int startingIndex, 228 int count ) { 229 return process(new ReadBlockOfChildrenRequest(of, workspaceName, startingIndex, count)); 230 } 231 232 /** 233 * Add a request to read those children of a node that are immediately after a supplied sibling node. 234 * 235 * @param startingAfter the location of the previous sibling that was the last child of the previous block of children read 236 * @param workspaceName the name of the workspace containing the node 237 * @param count the maximum number of children that should be included in the block 238 * @return the request; never null 239 * @throws IllegalArgumentException if the workspace name or <code>startingAfter</code> location is null, or if 240 * <code>count</count> is less than 1. 241 */ 242 public ReadNextBlockOfChildrenRequest readNextBlockOfChildren( Location startingAfter, 243 String workspaceName, 244 int count ) { 245 return process(new ReadNextBlockOfChildrenRequest(startingAfter, workspaceName, count)); 246 } 247 248 /** 249 * Add a request to create a node with the given properties under the supplied location. 250 * 251 * @param parentLocation the location of the existing parent node, under which the new child should be created 252 * @param workspaceName the name of the workspace containing the parent 253 * @param childName the name of the new child to create under the existing parent 254 * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification 255 * properties} for the new node 256 * @return the request; never null 257 * @throws IllegalArgumentException if the location, workspace name, or child name is null 258 */ 259 public CreateNodeRequest createNode( Location parentLocation, 260 String workspaceName, 261 Name childName, 262 Iterator<Property> properties ) { 263 return process(new CreateNodeRequest(parentLocation, workspaceName, childName, 264 CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR, properties)); 265 } 266 267 /** 268 * Add a request to create a node with the given properties under the supplied location. 269 * 270 * @param parentLocation the location of the existing parent node, under which the new child should be created 271 * @param workspaceName the name of the workspace containing the parent 272 * @param childName the name of the new child to create under the existing parent 273 * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification 274 * properties} for the new node 275 * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code> 276 * location 277 * @return the request; never null 278 * @throws IllegalArgumentException if the location, workspace name, or child name is null 279 */ 280 public CreateNodeRequest createNode( Location parentLocation, 281 String workspaceName, 282 Name childName, 283 Iterator<Property> properties, 284 NodeConflictBehavior conflictBehavior ) { 285 if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR; 286 return process(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties)); 287 } 288 289 /** 290 * Add a request to create a node with the given properties under the supplied location. 291 * 292 * @param parentLocation the location of the existing parent node, under which the new child should be created 293 * @param workspaceName the name of the workspace containing the parent 294 * @param childName the name of the new child to create under the existing parent 295 * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification 296 * properties} for the new node 297 * @return the request; never null 298 * @throws IllegalArgumentException if the location, workspace name, or child name is null 299 */ 300 public CreateNodeRequest createNode( Location parentLocation, 301 String workspaceName, 302 Name childName, 303 Property[] properties ) { 304 return process(new CreateNodeRequest(parentLocation, workspaceName, childName, 305 CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR, properties)); 306 } 307 308 /** 309 * Add a request to create a node with the given properties under the supplied location. 310 * 311 * @param parentLocation the location of the existing parent node, under which the new child should be created 312 * @param workspaceName the name of the workspace containing the parent 313 * @param childName the name of the new child to create under the existing parent 314 * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification 315 * properties} for the new node 316 * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code> 317 * location 318 * @return the request; never null 319 * @throws IllegalArgumentException if the location, workspace name, or child name is null 320 */ 321 public CreateNodeRequest createNode( Location parentLocation, 322 String workspaceName, 323 Name childName, 324 Property[] properties, 325 NodeConflictBehavior conflictBehavior ) { 326 if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR; 327 return process(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties)); 328 } 329 330 /** 331 * Add a request to update the property on the node at the supplied location. This request will create the property if it does 332 * not yet exist. 333 * 334 * @param on the location of the node to be read 335 * @param workspaceName the name of the workspace containing the node 336 * @param property the new property on the node 337 * @return the request; never null 338 * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update 339 */ 340 public SetPropertyRequest setProperty( Location on, 341 String workspaceName, 342 Property property ) { 343 return process(new SetPropertyRequest(on, workspaceName, property)); 344 } 345 346 /** 347 * Add a request to update the properties on the node at the supplied location. 348 * 349 * @param on the location of the node to be read 350 * @param workspaceName the name of the workspace containing the node 351 * @param properties the new properties on the node 352 * @return the {@link SetPropertyRequest} or {@link UpdatePropertiesRequest} request, depending upon the number of properties 353 * being set; never null 354 * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update 355 */ 356 public Request setProperties( Location on, 357 String workspaceName, 358 Property... properties ) { 359 if (properties.length == 1) { 360 return process(new SetPropertyRequest(on, workspaceName, properties[0])); 361 } 362 Map<Name, Property> propertyMap = new HashMap<Name, Property>(); 363 for (Property property : properties) { 364 propertyMap.put(property.getName(), property); 365 } 366 return process(new UpdatePropertiesRequest(on, workspaceName, propertyMap)); 367 } 368 369 /** 370 * Add a request to remove the property with the supplied name from the given node. Supplying a name for a property that does 371 * not exist will not cause an error. 372 * 373 * @param on the location of the node to be read 374 * @param workspaceName the name of the workspace containing the node 375 * @param propertyName the name of the property that is to be removed 376 * @return the request; never null 377 * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove 378 */ 379 public RemovePropertyRequest removeProperty( Location on, 380 String workspaceName, 381 Name propertyName ) { 382 return process(new RemovePropertyRequest(on, workspaceName, propertyName)); 383 } 384 385 /** 386 * Add a request to remove from the node the properties with the supplied names. Supplying a name for a property that does not 387 * exist will not cause an error. 388 * 389 * @param on the location of the node to be read 390 * @param workspaceName the name of the workspace containing the node 391 * @param propertyNames the names of the properties that are to be removed 392 * @return the {@link RemovePropertyRequest} or {@link UpdatePropertiesRequest} request, depending upon the number of 393 * properties being removed; never null 394 * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove 395 */ 396 public Request removeProperties( Location on, 397 String workspaceName, 398 Name... propertyNames ) { 399 if (propertyNames.length == 1) { 400 return process(new RemovePropertyRequest(on, workspaceName, propertyNames[0])); 401 } 402 Map<Name, Property> properties = new HashMap<Name, Property>(); 403 for (Name propertyName : propertyNames) { 404 properties.put(propertyName, null); 405 } 406 return process(new UpdatePropertiesRequest(on, workspaceName, properties)); 407 } 408 409 /** 410 * Add a request to rename the node at the supplied location. 411 * 412 * @param at the location of the node to be read 413 * @param workspaceName the name of the workspace containing the node 414 * @param newName the new name for the node 415 * @return the request; never null 416 * @throws IllegalArgumentException if the location or workspace name is null 417 */ 418 public RenameNodeRequest renameNode( Location at, 419 String workspaceName, 420 Name newName ) { 421 return process(new RenameNodeRequest(at, workspaceName, newName)); 422 } 423 424 /** 425 * Add a request to copy a branch to another. 426 * 427 * @param from the location of the top node in the existing branch that is to be copied 428 * @param fromWorkspace the name of the workspace where the <code>from</code> node exists 429 * @param into the location of the existing node into which the copy should be placed 430 * @param intoWorkspace the name of the workspace where the <code>into</code> node is to be copied 431 * @param nameForCopy the desired name for the node that results from the copy, or null if the name of the original should be 432 * used 433 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 434 * location, or null if the default conflict behavior should be used 435 * @return the request; never null 436 * @throws IllegalArgumentException if either of the locations or workspace names are null 437 */ 438 public CopyBranchRequest copyBranch( Location from, 439 String fromWorkspace, 440 Location into, 441 String intoWorkspace, 442 Name nameForCopy, 443 NodeConflictBehavior conflictBehavior ) { 444 if (conflictBehavior == null) conflictBehavior = CopyBranchRequest.DEFAULT_CONFLICT_BEHAVIOR; 445 return process(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace, nameForCopy, conflictBehavior)); 446 } 447 448 /** 449 * Create a request to move a branch from one location into another. 450 * 451 * @param from the location of the top node in the existing branch that is to be moved 452 * @param into the location of the existing node into which the branch should be moved 453 * @param workspaceName the name of the workspace 454 * @return the request; never null 455 * @throws IllegalArgumentException if any of the parameters are null 456 */ 457 public MoveBranchRequest moveBranch( Location from, 458 Location into, 459 String workspaceName ) { 460 return process(new MoveBranchRequest(from, into, workspaceName, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR)); 461 } 462 463 /** 464 * Create a request to move a branch from one location into another. 465 * 466 * @param from the location of the top node in the existing branch that is to be moved 467 * @param into the location of the existing node into which the branch should be moved 468 * @param workspaceName the name of the workspace 469 * @param newNameForNode the new name for the node being moved, or null if the name of the original should be used 470 * @return the request; never null 471 * @throws IllegalArgumentException if any of the parameters are null 472 */ 473 public MoveBranchRequest moveBranch( Location from, 474 Location into, 475 String workspaceName, 476 Name newNameForNode ) { 477 return process(new MoveBranchRequest(from, into, null, workspaceName, newNameForNode, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR)); 478 } 479 480 /** 481 * Create a request to move a branch from one location into another before the given child node of the new location. 482 * 483 * @param from the location of the top node in the existing branch that is to be moved 484 * @param into the location of the existing node into which the branch should be moved 485 * @param before the location of the node before which the branch should be moved; may be null 486 * @param workspaceName the name of the workspace 487 * @param newNameForNode the new name for the node being moved, or null if the name of the original should be used 488 * @return the request; never null 489 * @throws IllegalArgumentException if any of the parameters are null 490 */ 491 public MoveBranchRequest moveBranch( Location from, 492 Location into, 493 Location before, 494 String workspaceName, 495 Name newNameForNode ) { 496 return process(new MoveBranchRequest(from, into, before, workspaceName, newNameForNode, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR)); 497 } 498 /** 499 * Create a request to move a branch from one location into another. 500 * 501 * @param from the location of the top node in the existing branch that is to be moved 502 * @param into the location of the existing node into which the branch should be moved 503 * @param workspaceName the name of the workspace 504 * @param newNameForNode the new name for the node being moved, or null if the name of the original should be used 505 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 506 * location 507 * @return the request; never null 508 * @throws IllegalArgumentException if any of the parameters are null 509 */ 510 public MoveBranchRequest moveBranch( Location from, 511 Location into, 512 String workspaceName, 513 Name newNameForNode, 514 NodeConflictBehavior conflictBehavior ) { 515 if (conflictBehavior == null) conflictBehavior = MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR; 516 return process(new MoveBranchRequest(from, into, null, workspaceName, newNameForNode, conflictBehavior)); 517 } 518 519 /** 520 * Create a request to move a branch from one location into another. 521 * 522 * @param from the location of the top node in the existing branch that is to be moved 523 * @param into the location of the existing node into which the branch should be moved 524 * @param workspaceName the name of the workspace 525 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 526 * location 527 * @return the request; never null 528 * @throws IllegalArgumentException if any of the parameters are null 529 */ 530 public MoveBranchRequest moveBranch( Location from, 531 Location into, 532 String workspaceName, 533 NodeConflictBehavior conflictBehavior ) { 534 if (conflictBehavior == null) conflictBehavior = MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR; 535 return process(new MoveBranchRequest(from, into, workspaceName, conflictBehavior)); 536 } 537 538 /** 539 * Add a request to delete a branch. 540 * 541 * @param at the location of the top node in the existing branch that is to be deleted 542 * @param workspaceName the name of the workspace containing the parent 543 * @return the request; never null 544 * @throws IllegalArgumentException if the location or workspace name is null 545 */ 546 public DeleteBranchRequest deleteBranch( Location at, 547 String workspaceName ) { 548 return process(new DeleteBranchRequest(at, workspaceName)); 549 } 550 }