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 }