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 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA 010 * is licensed 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; 025 026 import java.io.File; 027 import java.io.IOException; 028 import java.io.InputStream; 029 import java.io.Reader; 030 import java.math.BigDecimal; 031 import java.net.URI; 032 import java.util.ArrayList; 033 import java.util.Calendar; 034 import java.util.Collection; 035 import java.util.Collections; 036 import java.util.Date; 037 import java.util.HashMap; 038 import java.util.Iterator; 039 import java.util.LinkedList; 040 import java.util.List; 041 import java.util.Map; 042 import java.util.Set; 043 import java.util.UUID; 044 import net.jcip.annotations.Immutable; 045 import net.jcip.annotations.NotThreadSafe; 046 import org.jboss.dna.common.collection.EmptyIterator; 047 import org.jboss.dna.common.util.CheckArg; 048 import org.jboss.dna.graph.cache.CachePolicy; 049 import org.jboss.dna.graph.connector.RepositoryConnection; 050 import org.jboss.dna.graph.connector.RepositoryConnectionFactory; 051 import org.jboss.dna.graph.connector.RepositorySource; 052 import org.jboss.dna.graph.connector.RepositorySourceException; 053 import org.jboss.dna.graph.io.GraphImporter; 054 import org.jboss.dna.graph.property.Binary; 055 import org.jboss.dna.graph.property.DateTime; 056 import org.jboss.dna.graph.property.Name; 057 import org.jboss.dna.graph.property.NameFactory; 058 import org.jboss.dna.graph.property.Path; 059 import org.jboss.dna.graph.property.PathNotFoundException; 060 import org.jboss.dna.graph.property.Property; 061 import org.jboss.dna.graph.property.PropertyFactory; 062 import org.jboss.dna.graph.property.Reference; 063 import org.jboss.dna.graph.property.ValueFormatException; 064 import org.jboss.dna.graph.property.Path.Segment; 065 import org.jboss.dna.graph.request.BatchRequestBuilder; 066 import org.jboss.dna.graph.request.CloneWorkspaceRequest; 067 import org.jboss.dna.graph.request.CompositeRequest; 068 import org.jboss.dna.graph.request.CreateNodeRequest; 069 import org.jboss.dna.graph.request.CreateWorkspaceRequest; 070 import org.jboss.dna.graph.request.InvalidRequestException; 071 import org.jboss.dna.graph.request.InvalidWorkspaceException; 072 import org.jboss.dna.graph.request.ReadAllChildrenRequest; 073 import org.jboss.dna.graph.request.ReadAllPropertiesRequest; 074 import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest; 075 import org.jboss.dna.graph.request.ReadBranchRequest; 076 import org.jboss.dna.graph.request.ReadNodeRequest; 077 import org.jboss.dna.graph.request.ReadPropertyRequest; 078 import org.jboss.dna.graph.request.Request; 079 import org.jboss.dna.graph.request.RequestBuilder; 080 import org.jboss.dna.graph.request.UnsupportedRequestException; 081 import org.jboss.dna.graph.request.VerifyWorkspaceRequest; 082 import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior; 083 import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior; 084 import org.xml.sax.SAXException; 085 086 /** 087 * A graph representation of the content within a {@link RepositorySource}, including mechanisms to interact and manipulate that 088 * content. The graph is designed to be an <i><a href="http://en.wikipedia.org/wiki/Domain_Specific_Language">embedded domain 089 * specific language</a></i>, meaning calls to it are designed to read like sentences even though they are really just Java 090 * methods. And to be more readable, methods can be chained together. 091 * 092 * @author Randall Hauch 093 */ 094 @NotThreadSafe 095 public class Graph { 096 097 protected static final Iterator<Property> EMPTY_PROPERTIES = new EmptyIterator<Property>(); 098 protected static final Iterable<Property> NO_PROPERTIES = new Iterable<Property>() { 099 public final Iterator<Property> iterator() { 100 return EMPTY_PROPERTIES; 101 } 102 }; 103 104 /** 105 * Create a graph instance that uses the supplied repository and {@link ExecutionContext context}. 106 * 107 * @param sourceName the name of the source that should be used 108 * @param connectionFactory the factory of repository connections 109 * @param context the context in which all executions should be performed 110 * @return the new graph 111 * @throws IllegalArgumentException if the source or context parameters are null 112 */ 113 public static Graph create( String sourceName, 114 RepositoryConnectionFactory connectionFactory, 115 ExecutionContext context ) { 116 return new Graph(sourceName, connectionFactory, context); 117 } 118 119 /** 120 * Create a graph instance that uses the supplied {@link RepositoryConnection} and {@link ExecutionContext context}. 121 * 122 * @param connection the connection that should be used 123 * @param context the context in which all executions should be performed 124 * @return the new graph 125 * @throws IllegalArgumentException if the connection or context parameters are null 126 */ 127 public static Graph create( final RepositoryConnection connection, 128 ExecutionContext context ) { 129 CheckArg.isNotNull(connection, "connection"); 130 final String connectorSourceName = connection.getSourceName(); 131 RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory() { 132 public RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException { 133 if (connectorSourceName.equals(sourceName)) return connection; 134 return null; 135 } 136 }; 137 return new Graph(connectorSourceName, connectionFactory, context); 138 } 139 140 /** 141 * Create a graph instance that uses the supplied {@link RepositoryConnection} and {@link ExecutionContext context}. 142 * 143 * @param source the source that should be used 144 * @param context the context in which all executions should be performed 145 * @return the new graph 146 * @throws IllegalArgumentException if the connection or context parameters are null 147 */ 148 public static Graph create( final RepositorySource source, 149 ExecutionContext context ) { 150 CheckArg.isNotNull(source, "source"); 151 final String connectorSourceName = source.getName(); 152 RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory() { 153 public RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException { 154 if (connectorSourceName.equals(sourceName)) return source.getConnection(); 155 return null; 156 } 157 }; 158 return new Graph(connectorSourceName, connectionFactory, context); 159 } 160 161 private final String sourceName; 162 private final RepositoryConnectionFactory connectionFactory; 163 private final ExecutionContext context; 164 protected final RequestBuilder requests; 165 protected final Conjunction<Graph> nextGraph; 166 private Workspace currentWorkspace; 167 168 protected Graph( String sourceName, 169 RepositoryConnectionFactory connectionFactory, 170 ExecutionContext context ) { 171 CheckArg.isNotNull(sourceName, "sourceName"); 172 CheckArg.isNotNull(connectionFactory, "connectionFactory"); 173 CheckArg.isNotNull(context, "context"); 174 this.sourceName = sourceName; 175 this.connectionFactory = connectionFactory; 176 this.context = context; 177 this.nextGraph = new Conjunction<Graph>() { 178 public Graph and() { 179 return Graph.this; 180 } 181 }; 182 this.requests = new RequestBuilder() { 183 @Override 184 protected <T extends Request> T process( T request ) { 185 Graph.this.execute(request); 186 return request; 187 } 188 }; 189 } 190 191 /** 192 * Get the RepositoryConnectionFactory that this graph uses to create {@link RepositoryConnection repository connections}. 193 * 194 * @return the factory repository connections used by this graph; never null 195 */ 196 public RepositoryConnectionFactory getConnectionFactory() { 197 return connectionFactory; 198 } 199 200 /** 201 * The name of the repository that will be used by this graph. This name is passed to the {@link #getConnectionFactory() 202 * connection factory} when this graph needs to {@link RepositoryConnectionFactory#createConnection(String) obtain} a 203 * {@link RepositoryConnection repository connection}. 204 * 205 * @return the name of the source 206 */ 207 public String getSourceName() { 208 return sourceName; 209 } 210 211 /** 212 * Get the context of execution within which operations on this graph are performed. 213 * 214 * @return the execution context; never null 215 */ 216 public ExecutionContext getContext() { 217 return context; 218 } 219 220 /** 221 * Obtain a connection to the source, execute the supplied request, and check the request for {@link Request#getError() 222 * errors}. If an error is found, then it is thrown (or wrapped by a {@link RepositorySourceException} if the error is not a 223 * {@link RuntimeException}. 224 * <p> 225 * This method is called automatically when the {@link #requests request builder} creates each request. 226 * </p> 227 * 228 * @param request the request to be executed (may be a {@link CompositeRequest}. 229 * @throws PathNotFoundException if the request used a node that did not exist 230 * @throws InvalidRequestException if the request was not valid 231 * @throws InvalidWorkspaceException if the workspace used in the request was not valid 232 * @throws UnsupportedRequestException if the request was not supported by the source 233 * @throws RepositorySourceException if an error occurs during execution 234 * @throws RuntimeException if a runtime error occurs during execution 235 */ 236 protected void execute( Request request ) { 237 RepositoryConnection connection = Graph.this.getConnectionFactory().createConnection(getSourceName()); 238 if (connection == null) { 239 throw new RepositorySourceException(GraphI18n.unableToFindRepositorySourceWithName.text(getSourceName())); 240 } 241 try { 242 connection.execute(Graph.this.getContext(), request); 243 } finally { 244 connection.close(); 245 } 246 if (request.hasError()) { 247 Throwable error = request.getError(); 248 if (error instanceof RuntimeException) throw (RuntimeException)error; 249 throw new RepositorySourceException(getSourceName(), error); 250 } 251 } 252 253 /** 254 * Get the default cache policy for this graph. May be null if such a policy has not been defined for thie 255 * {@link #getSourceName() source}. 256 * 257 * @return the default cache policy, or null if no such policy has been defined for the source 258 * @throws RepositorySourceException if no repository source with the {@link #getSourceName() name} could be found 259 */ 260 public CachePolicy getDefaultCachePolicy() { 261 RepositoryConnection connection = this.connectionFactory.createConnection(getSourceName()); 262 if (connection == null) { 263 throw new RepositorySourceException(GraphI18n.unableToFindRepositorySourceWithName.text(getSourceName())); 264 } 265 try { 266 return connection.getDefaultCachePolicy(); 267 } finally { 268 connection.close(); 269 } 270 } 271 272 /** 273 * Utility method to set the workspace that will be used by this graph. 274 * 275 * @param workspaceName the name of the workspace; may not be null 276 * @param actualRootLocation the actual location of the root node in the workspace; may not be null 277 * @return the workspace; never null 278 */ 279 protected Workspace setWorkspace( String workspaceName, 280 Location actualRootLocation ) { 281 assert workspaceName != null; 282 assert actualRootLocation != null; 283 this.currentWorkspace = new GraphWorkspace(workspaceName, actualRootLocation); 284 return this.currentWorkspace; 285 } 286 287 /** 288 * Get the name of the current workspace being used by this graph. If the graph has not yet been instructed to 289 * {@link #useWorkspace(String) use} or {@link #createWorkspace() create} a workspace, this method will assume that the 290 * source's default workspace is to be used and will obtain from the source the name of that default workspace. 291 * 292 * @return the name of the current workspace; never null 293 * @see #getCurrentWorkspace() 294 */ 295 public String getCurrentWorkspaceName() { 296 return getCurrentWorkspace().getName(); 297 } 298 299 /** 300 * Get the name of the current workspace being used by this graph. If the graph has not yet been instructed to 301 * {@link #useWorkspace(String) use} or {@link #createWorkspace() create} a workspace, this method will assume that the 302 * source's default workspace is to be used and will obtain from the source the name of that default workspace. If the source 303 * does not have a default workspace, this method will fail with an {@link InvalidWorkspaceException}. 304 * 305 * @return the name of the current workspace; never null 306 * @see #getCurrentWorkspaceName() 307 * @throws InvalidWorkspaceException if there is no current workspace 308 */ 309 public Workspace getCurrentWorkspace() { 310 if (this.currentWorkspace == null) { 311 useWorkspace(null); 312 } 313 assert this.currentWorkspace != null; 314 return this.currentWorkspace; 315 } 316 317 /** 318 * Get the set of workspace names that are known to this source and accessible by this {@link #getContext() context}. 319 * 320 * @return the set of workspace names; never null 321 */ 322 public Set<String> getWorkspaces() { 323 return requests.getWorkspaces().getAvailableWorkspaceNames(); 324 } 325 326 /** 327 * Switch this graph to use another existing workspace in the same source. 328 * 329 * @param workspaceName the name of the existing workspace that this graph should begin using, or null if the graph should use 330 * the "default" workspace in the source (if there is one) 331 * @return the workspace; never null 332 * @throws InvalidWorkspaceException if the workspace with the supplied name does not exist, or if null is supplied as the 333 * workspace name but the source does not have a default workspace 334 */ 335 public Workspace useWorkspace( String workspaceName ) { 336 VerifyWorkspaceRequest request = requests.verifyWorkspace(workspaceName); 337 return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot()); 338 } 339 340 /** 341 * Create a new workspace in the source used by this graph. This graph's workspace will be set as soon as the new workspace is 342 * created, and all subsequent operations will use the new workspace (until it is changed again by 343 * {@link #useWorkspace(String) using another workspace} or {@link #createWorkspace() creating another}. 344 * 345 * @return the interface used to complete the request to create a new workspace; never null 346 */ 347 public CreateWorkspace createWorkspace() { 348 return new CreateWorkspace() { 349 /** 350 * {@inheritDoc} 351 * 352 * @see org.jboss.dna.graph.Graph.NameWorkspace#named(java.lang.String) 353 */ 354 public Workspace named( String workspaceName ) { 355 CreateWorkspaceRequest request = requests.createWorkspace(workspaceName, CreateConflictBehavior.DO_NOT_CREATE); 356 return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot()); 357 } 358 359 /** 360 * {@inheritDoc} 361 * 362 * @see org.jboss.dna.graph.Graph.CreateWorkspace#namedSomethingLike(java.lang.String) 363 */ 364 public Workspace namedSomethingLike( String workspaceName ) { 365 CreateWorkspaceRequest request = requests.createWorkspace(workspaceName, 366 CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME); 367 return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot()); 368 } 369 370 /** 371 * {@inheritDoc} 372 * 373 * @see org.jboss.dna.graph.Graph.CreateWorkspace#clonedFrom(java.lang.String) 374 */ 375 public NameWorkspace clonedFrom( final String nameOfWorkspaceToClone ) { 376 return new NameWorkspace() { 377 /** 378 * {@inheritDoc} 379 * 380 * @see org.jboss.dna.graph.Graph.NameWorkspace#named(java.lang.String) 381 */ 382 public Workspace named( String nameOfWorkspaceToCreate ) { 383 CloneWorkspaceRequest request = requests.cloneWorkspace(nameOfWorkspaceToClone, 384 nameOfWorkspaceToCreate, 385 CreateConflictBehavior.DO_NOT_CREATE, 386 CloneConflictBehavior.DO_NOT_CLONE); 387 return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot()); 388 } 389 390 /** 391 * {@inheritDoc} 392 * 393 * @see org.jboss.dna.graph.Graph.NameWorkspace#namedSomethingLike(java.lang.String) 394 */ 395 public Workspace namedSomethingLike( String nameOfWorkspaceToCreate ) { 396 CloneWorkspaceRequest request = requests.cloneWorkspace(nameOfWorkspaceToClone, 397 nameOfWorkspaceToCreate, 398 CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME, 399 CloneConflictBehavior.DO_NOT_CLONE); 400 return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot()); 401 } 402 }; 403 } 404 }; 405 } 406 407 /** 408 * Begin the request to move the specified node into a parent node at a different location, which is specified via the 409 * <code>into(...)</code> method on the returned {@link Move} object. 410 * <p> 411 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 412 * method is called. 413 * </p> 414 * 415 * @param from the node that is to be moved. 416 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 417 * be moved 418 */ 419 public Move<Conjunction<Graph>> move( Node from ) { 420 return move(from.getLocation()); 421 } 422 423 /** 424 * Begin the request to move a node at the specified location into a parent node at a different location, which is specified 425 * via the <code>into(...)</code> method on the returned {@link Move} object. 426 * <p> 427 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 428 * method is called. 429 * </p> 430 * 431 * @param from the location of the node that is to be moved. 432 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 433 * be moved 434 */ 435 public Move<Conjunction<Graph>> move( Location from ) { 436 return new MoveAction<Conjunction<Graph>>(this.nextGraph, from) { 437 @Override 438 protected Conjunction<Graph> submit( Locations from, 439 Location into, 440 Name newName ) { 441 String workspaceName = getCurrentWorkspaceName(); 442 do { 443 requests.moveBranch(from.getLocation(), into, workspaceName, newName); 444 } while ((from = from.next()) != null); 445 return and(); 446 } 447 }; 448 } 449 450 /** 451 * Begin the request to move a node located at the supplied path into a parent node at a different location, which is 452 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 453 * <p> 454 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 455 * method is called. 456 * </p> 457 * 458 * @param fromPath the path to the node that is to be moved. 459 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 460 * be moved 461 */ 462 public Move<Conjunction<Graph>> move( String fromPath ) { 463 return move(Location.create(createPath(fromPath))); 464 } 465 466 /** 467 * Begin the request to move a node located at the supplied path into a parent node at a different location, which is 468 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 469 * <p> 470 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 471 * method is called. 472 * </p> 473 * 474 * @param from the path to the node that is to be moved. 475 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 476 * be moved 477 */ 478 public Move<Conjunction<Graph>> move( Path from ) { 479 return move(Location.create(from)); 480 } 481 482 /** 483 * Begin the request to move a node with the specified unique identifier into a parent node at a different location, which is 484 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 485 * <p> 486 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 487 * method is called. 488 * </p> 489 * 490 * @param from the UUID of the node that is to be moved. 491 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 492 * be moved 493 */ 494 public Move<Conjunction<Graph>> move( UUID from ) { 495 return move(Location.create(from)); 496 } 497 498 /** 499 * Begin the request to move a node with the specified unique identification property into a parent node at a different 500 * location, which is specified via the <code>into(...)</code> method on the returned {@link Move} object. The identification 501 * property should uniquely identify a single node. 502 * <p> 503 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 504 * method is called. 505 * </p> 506 * 507 * @param idProperty the unique identification property of the node that is to be moved. 508 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 509 * be moved 510 */ 511 public Move<Conjunction<Graph>> move( Property idProperty ) { 512 return move(Location.create(idProperty)); 513 } 514 515 /** 516 * Begin the request to move a node with the specified identification properties into a parent node at a different location, 517 * which is specified via the <code>into(...)</code> method on the returned {@link Move} object. The identification properties 518 * should uniquely identify a single node. 519 * <p> 520 * Like all other methods on the {@link Graph}, the move request will be performed immediately when the <code>into(...)</code> 521 * method is called. 522 * </p> 523 * 524 * @param firstIdProperty the first identification property of the node that is to be moved 525 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be moved 526 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is to 527 * be moved 528 */ 529 public Move<Conjunction<Graph>> move( Property firstIdProperty, 530 Property... additionalIdProperties ) { 531 return move(Location.create(firstIdProperty, additionalIdProperties)); 532 } 533 534 /** 535 * Begin the request to copy the specified node into a parent node at a different location, which is specified via the 536 * <code>into(...)</code> method on the returned {@link Copy} object. 537 * <p> 538 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 539 * method is called. 540 * </p> 541 * 542 * @param from the node that is to be copied. 543 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 544 * be copied 545 */ 546 public Copy<Graph> copy( Node from ) { 547 return copy(from.getLocation()); 548 } 549 550 /** 551 * Begin the request to copy a node at the specified location into a parent node at a different location, which is specified 552 * via the <code>into(...)</code> method on the returned {@link Copy} object. 553 * <p> 554 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 555 * method is called. 556 * </p> 557 * 558 * @param from the location of the node that is to be copied. 559 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 560 * be copied 561 */ 562 public Copy<Graph> copy( Location from ) { 563 return new CopyAction<Graph>(this, from) { 564 @Override 565 protected Graph submit( Locations from, 566 Location into, 567 Name childName ) { 568 String workspaceName = getCurrentWorkspaceName(); 569 do { 570 requests.copyBranch(from.getLocation(), 571 workspaceName, 572 into, 573 workspaceName, 574 childName, 575 NodeConflictBehavior.APPEND); 576 } while ((from = from.next()) != null); 577 return and(); 578 } 579 }; 580 } 581 582 /** 583 * Begin the request to copy a node located at the supplied path into a parent node at a different location, which is 584 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 585 * <p> 586 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 587 * method is called. 588 * </p> 589 * 590 * @param fromPath the path to the node that is to be copied. 591 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 592 * be copied 593 */ 594 public Copy<Graph> copy( String fromPath ) { 595 return copy(Location.create(createPath(fromPath))); 596 } 597 598 /** 599 * Begin the request to copy a node located at the supplied path into a parent node at a different location, which is 600 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 601 * <p> 602 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 603 * method is called. 604 * </p> 605 * 606 * @param from the path to the node that is to be copied. 607 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 608 * be copied 609 */ 610 public Copy<Graph> copy( Path from ) { 611 return copy(Location.create(from)); 612 } 613 614 /** 615 * Begin the request to copy a node with the specified unique identifier into a parent node at a different location, which is 616 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 617 * <p> 618 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 619 * method is called. 620 * </p> 621 * 622 * @param from the UUID of the node that is to be copied. 623 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 624 * be copied 625 */ 626 public Copy<Graph> copy( UUID from ) { 627 return copy(Location.create(from)); 628 } 629 630 /** 631 * Begin the request to copy a node with the specified unique identification property into a parent node at a different 632 * location, which is specified via the <code>into(...)</code> method on the returned {@link Copy} object. The identification 633 * property should uniquely identify a single node. 634 * <p> 635 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 636 * method is called. 637 * </p> 638 * 639 * @param idProperty the unique identification property of the node that is to be copied. 640 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 641 * be copied 642 */ 643 public Copy<Graph> copy( Property idProperty ) { 644 return copy(Location.create(idProperty)); 645 } 646 647 /** 648 * Begin the request to copy a node with the specified identification properties into a parent node at a different location, 649 * which is specified via the <code>into(...)</code> method on the returned {@link Copy} object. The identification properties 650 * should uniquely identify a single node. 651 * <p> 652 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>into(...)</code> 653 * method is called. 654 * </p> 655 * 656 * @param firstIdProperty the first identification property of the node that is to be copied 657 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be copied 658 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node is to 659 * be copied 660 */ 661 public Copy<Graph> copy( Property firstIdProperty, 662 Property... additionalIdProperties ) { 663 return copy(Location.create(firstIdProperty, additionalIdProperties)); 664 } 665 666 /** 667 * Request to delete the specified node. This request is submitted to the repository immediately. 668 * 669 * @param at the node that is to be deleted 670 * @return an object that may be used to start another request 671 */ 672 public Conjunction<Graph> delete( Node at ) { 673 requests.deleteBranch(at.getLocation(), getCurrentWorkspaceName()); 674 return nextGraph; 675 } 676 677 /** 678 * Request to delete the node at the given location. This request is submitted to the repository immediately. 679 * 680 * @param at the location of the node that is to be deleted 681 * @return an object that may be used to start another request 682 */ 683 public Conjunction<Graph> delete( Location at ) { 684 requests.deleteBranch(at, getCurrentWorkspaceName()); 685 return nextGraph; 686 } 687 688 /** 689 * Request to delete the node at the given path. This request is submitted to the repository immediately. 690 * 691 * @param atPath the path of the node that is to be deleted 692 * @return an object that may be used to start another request 693 */ 694 public Conjunction<Graph> delete( String atPath ) { 695 return delete(Location.create(createPath(atPath))); 696 } 697 698 /** 699 * Request to delete the node at the given path. This request is submitted to the repository immediately. 700 * 701 * @param at the path of the node that is to be deleted 702 * @return an object that may be used to start another request 703 */ 704 public Conjunction<Graph> delete( Path at ) { 705 return delete(Location.create(at)); 706 } 707 708 /** 709 * Request to delete the node with the given UUID. This request is submitted to the repository immediately. 710 * 711 * @param at the UUID of the node that is to be deleted 712 * @return an object that may be used to start another request 713 */ 714 public Conjunction<Graph> delete( UUID at ) { 715 return delete(Location.create(at)); 716 } 717 718 /** 719 * Request to delete the node with the given unique identification property. This request is submitted to the repository 720 * immediately. 721 * 722 * @param idProperty the unique identifying property of the node that is to be deleted 723 * @return an object that may be used to start another request 724 */ 725 public Conjunction<Graph> delete( Property idProperty ) { 726 return delete(Location.create(idProperty)); 727 } 728 729 /** 730 * Request to delete the node with the given identification properties. The identification properties should uniquely identify 731 * a single node. This request is submitted to the repository immediately. 732 * 733 * @param firstIdProperty the first identification property of the node that is to be copied 734 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be copied 735 * @return an object that may be used to start another request 736 */ 737 public Conjunction<Graph> delete( Property firstIdProperty, 738 Property... additionalIdProperties ) { 739 return delete(Location.create(firstIdProperty, additionalIdProperties)); 740 } 741 742 /** 743 * Begin the request to create a node located at the supplied path, and return an interface used to either add properties for 744 * the new node, or complete/submit the request and return the location, node, or graph. 745 * <p> 746 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 747 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 748 * parent or new node. 749 * </p> 750 * 751 * @param atPath the path to the node that is to be created. 752 * @return an object that may be used to start another request 753 */ 754 public CreateAt<Graph> createAt( String atPath ) { 755 return createAt(createPath(atPath)); 756 } 757 758 /** 759 * Begin the request to create a node located at the supplied path, and return an interface used to either add properties for 760 * the new node, or complete/submit the request and return the location, node, or graph. 761 * <p> 762 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 763 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 764 * parent or new node. 765 * </p> 766 * 767 * @param at the path to the node that is to be created. 768 * @return an object that may be used to start another request 769 */ 770 public CreateAt<Graph> createAt( final Path at ) { 771 CheckArg.isNotNull(at, "at"); 772 final Path parent = at.getParent(); 773 final Name childName = at.getLastSegment().getName(); 774 final String workspaceName = getCurrentWorkspaceName(); 775 return new CreateAt<Graph>() { 776 private final List<Property> properties = new LinkedList<Property>(); 777 778 public CreateAt<Graph> and( UUID uuid ) { 779 PropertyFactory factory = getContext().getPropertyFactory(); 780 properties.add(factory.create(DnaLexicon.UUID, uuid)); 781 return this; 782 } 783 784 public CreateAt<Graph> and( Property property ) { 785 properties.add(property); 786 return this; 787 } 788 789 public CreateAt<Graph> and( Iterable<Property> properties ) { 790 for (Property property : properties) { 791 this.properties.add(property); 792 } 793 return this; 794 } 795 796 public CreateAt<Graph> and( String name, 797 Object... values ) { 798 ExecutionContext context = getContext(); 799 PropertyFactory factory = context.getPropertyFactory(); 800 NameFactory nameFactory = context.getValueFactories().getNameFactory(); 801 properties.add(factory.create(nameFactory.create(name), values)); 802 return this; 803 } 804 805 public CreateAt<Graph> and( Name name, 806 Object... values ) { 807 ExecutionContext context = getContext(); 808 PropertyFactory factory = context.getPropertyFactory(); 809 properties.add(factory.create(name, values)); 810 return this; 811 } 812 813 public CreateAt<Graph> and( Property property, 814 Property... additionalProperties ) { 815 properties.add(property); 816 for (Property additionalProperty : additionalProperties) { 817 properties.add(additionalProperty); 818 } 819 return this; 820 } 821 822 public CreateAt<Graph> with( UUID uuid ) { 823 return and(uuid); 824 } 825 826 public CreateAt<Graph> with( Property property ) { 827 return and(property); 828 } 829 830 public CreateAt<Graph> with( Iterable<Property> properties ) { 831 return and(properties); 832 } 833 834 public CreateAt<Graph> with( Property property, 835 Property... additionalProperties ) { 836 return and(property, additionalProperties); 837 } 838 839 public CreateAt<Graph> with( String name, 840 Object... values ) { 841 return and(name, values); 842 } 843 844 public CreateAt<Graph> with( Name name, 845 Object... values ) { 846 return and(name, values); 847 } 848 849 public Location getLocation() { 850 Location parentLoc = Location.create(parent); 851 CreateNodeRequest request = requests.createNode(parentLoc, workspaceName, childName, this.properties.iterator()); 852 return request.getActualLocationOfNode(); 853 } 854 855 public Node getNode() { 856 Location parentLoc = Location.create(parent); 857 CreateNodeRequest request = requests.createNode(parentLoc, workspaceName, childName, this.properties.iterator()); 858 return getNodeAt(request.getActualLocationOfNode()); 859 } 860 861 public Graph and() { 862 requests.createNode(Location.create(parent), workspaceName, childName, this.properties.iterator()); 863 return Graph.this; 864 } 865 }; 866 } 867 868 /** 869 * Begin the request to create a node located at the supplied path. This request is submitted to the repository immediately. 870 * <p> 871 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 872 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 873 * parent or new node. 874 * </p> 875 * 876 * @param atPath the path to the node that is to be created. 877 * @return an object that may be used to start another request 878 */ 879 public Conjunction<Graph> create( String atPath ) { 880 Path at = createPath(atPath); 881 Path parent = at.getParent(); 882 Name child = at.getLastSegment().getName(); 883 requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, EMPTY_PROPERTIES); 884 return nextGraph; 885 } 886 887 /** 888 * Begin the request to create a node located at the supplied path. This request is submitted to the repository immediately. 889 * <p> 890 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 891 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 892 * parent or new node. 893 * </p> 894 * 895 * @param at the path to the node that is to be created. 896 * @return an object that may be used to start another request 897 */ 898 public Conjunction<Graph> create( final Path at ) { 899 Path parent = at.getParent(); 900 Name child = at.getLastSegment().getName(); 901 requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, EMPTY_PROPERTIES); 902 return nextGraph; 903 } 904 905 /** 906 * Begin the request to create a node located at the supplied path. This request is submitted to the repository immediately. 907 * <p> 908 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 909 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 910 * parent or new node. 911 * </p> 912 * 913 * @param atPath the path to the node that is to be created. 914 * @param properties the properties for the new node 915 * @return an object that may be used to start another request 916 */ 917 public Conjunction<Graph> create( String atPath, 918 Property... properties ) { 919 Path at = createPath(atPath); 920 Path parent = at.getParent(); 921 Name child = at.getLastSegment().getName(); 922 requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties); 923 return nextGraph; 924 } 925 926 /** 927 * Begin the request to create a node located at the supplied path. This request is submitted to the repository immediately. 928 * <p> 929 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 930 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 931 * parent or new node. 932 * </p> 933 * 934 * @param at the path to the node that is to be created. 935 * @param properties the properties for the new node 936 * @return an object that may be used to start another request 937 */ 938 public Conjunction<Graph> create( Path at, 939 Property... properties ) { 940 CheckArg.isNotNull(at, "at"); 941 Path parent = at.getParent(); 942 Name child = at.getLastSegment().getName(); 943 requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties); 944 return nextGraph; 945 } 946 947 /** 948 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 949 * the repository immediately. 950 * <p> 951 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 952 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 953 * parent or new node. 954 * </p> 955 * 956 * @param at the path to the node that is to be created. 957 * @param properties the properties for the new node 958 * @return an object that may be used to start another request 959 */ 960 public Conjunction<Graph> create( Path at, 961 Iterable<Property> properties ) { 962 CheckArg.isNotNull(at, "at"); 963 Path parent = at.getParent(); 964 Name child = at.getLastSegment().getName(); 965 requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties.iterator()); 966 return nextGraph; 967 } 968 969 /** 970 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 971 * the repository immediately. 972 * <p> 973 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 974 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 975 * parent or new node. 976 * </p> 977 * 978 * @param atPath the path to the node that is to be created. 979 * @return an object that may be used to start another request 980 */ 981 public GetNodeConjunction<Graph> createIfMissing( String atPath ) { 982 Path at = createPath(atPath); 983 Path parent = at.getParent(); 984 Name child = at.getLastSegment().getName(); 985 Location location = requests.createNode(Location.create(parent), 986 getCurrentWorkspaceName(), 987 child, 988 EMPTY_PROPERTIES, 989 NodeConflictBehavior.DO_NOT_REPLACE).getActualLocationOfNode(); 990 return new GetNodeOrReturnGraph(location); 991 } 992 993 /** 994 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 995 * the repository immediately. 996 * <p> 997 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 998 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 999 * parent or new node. 1000 * </p> 1001 * 1002 * @param at the path to the node that is to be created. 1003 * @return an object that may be used to start another request 1004 */ 1005 public GetNodeConjunction<Graph> createIfMissing( final Path at ) { 1006 Path parent = at.getParent(); 1007 Name child = at.getLastSegment().getName(); 1008 Location location = requests.createNode(Location.create(parent), 1009 getCurrentWorkspaceName(), 1010 child, 1011 EMPTY_PROPERTIES, 1012 NodeConflictBehavior.DO_NOT_REPLACE).getActualLocationOfNode(); 1013 return new GetNodeOrReturnGraph(location); 1014 } 1015 1016 /** 1017 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 1018 * the repository immediately. 1019 * <p> 1020 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 1021 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 1022 * parent or new node. 1023 * </p> 1024 * 1025 * @param atPath the path to the node that is to be created. 1026 * @param properties the properties for the new node 1027 * @return an object that may be used to start another request 1028 */ 1029 public GetNodeConjunction<Graph> createIfMissing( String atPath, 1030 Property... properties ) { 1031 Path at = createPath(atPath); 1032 Path parent = at.getParent(); 1033 Name child = at.getLastSegment().getName(); 1034 Location location = requests.createNode(Location.create(parent), 1035 getCurrentWorkspaceName(), 1036 child, 1037 properties, 1038 NodeConflictBehavior.UPDATE).getActualLocationOfNode(); 1039 return new GetNodeOrReturnGraph(location); 1040 } 1041 1042 /** 1043 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 1044 * the repository immediately. 1045 * <p> 1046 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 1047 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 1048 * parent or new node. 1049 * </p> 1050 * 1051 * @param at the path to the node that is to be created. 1052 * @param properties the properties for the new node 1053 * @return an object that may be used to start another request 1054 */ 1055 public GetNodeConjunction<Graph> createIfMissing( Path at, 1056 Property... properties ) { 1057 CheckArg.isNotNull(at, "at"); 1058 Path parent = at.getParent(); 1059 Name child = at.getLastSegment().getName(); 1060 Location location = requests.createNode(Location.create(parent), 1061 getCurrentWorkspaceName(), 1062 child, 1063 properties, 1064 NodeConflictBehavior.UPDATE).getActualLocationOfNode(); 1065 return new GetNodeOrReturnGraph(location); 1066 } 1067 1068 /** 1069 * Begin the request to create a node located at the supplied path, if the node does not exist. This request is submitted to 1070 * the repository immediately. 1071 * <p> 1072 * If you have the {@link Location} of the parent (for the new node) from a previous request, it is better and more efficient 1073 * to use {@link #createUnder(Location)}. However, this method work just as well if all you have is the {@link Path} to the 1074 * parent or new node. 1075 * </p> 1076 * 1077 * @param at the path to the node that is to be created. 1078 * @param properties the properties for the new node 1079 * @return an object that may be used to start another request 1080 */ 1081 public GetNodeConjunction<Graph> createIfMissing( Path at, 1082 Iterable<Property> properties ) { 1083 CheckArg.isNotNull(at, "at"); 1084 Path parent = at.getParent(); 1085 Name child = at.getLastSegment().getName(); 1086 Location location = requests.createNode(Location.create(parent), 1087 getCurrentWorkspaceName(), 1088 child, 1089 properties.iterator(), 1090 NodeConflictBehavior.UPDATE).getActualLocationOfNode(); 1091 return new GetNodeOrReturnGraph(location); 1092 } 1093 1094 /** 1095 * Begin the request to create a node under the existing parent node at the supplied location. Use this method if you are 1096 * creating a node when you have the {@link Location} of a parent from a previous request. 1097 * <p> 1098 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the <code>node(...)</code> 1099 * method is called on the returned object 1100 * </p> 1101 * 1102 * @param parent the location of the parent 1103 * @return the object used to start creating a node 1104 */ 1105 public CreateNode<Conjunction<Graph>> createUnder( final Location parent ) { 1106 final NameFactory nameFactory = getContext().getValueFactories().getNameFactory(); 1107 CheckArg.isNotNull(parent, "parent"); 1108 return new CreateNode<Conjunction<Graph>>() { 1109 public Conjunction<Graph> node( String name, 1110 Property... properties ) { 1111 Name child = nameFactory.create(name); 1112 requests.createNode(parent, getCurrentWorkspaceName(), child, properties); 1113 return nextGraph; 1114 } 1115 1116 public Conjunction<Graph> node( String name, 1117 Iterator<Property> properties ) { 1118 Name child = nameFactory.create(name); 1119 requests.createNode(parent, getCurrentWorkspaceName(), child, properties); 1120 return nextGraph; 1121 } 1122 1123 public Conjunction<Graph> node( String name, 1124 Iterable<Property> properties ) { 1125 Name child = nameFactory.create(name); 1126 requests.createNode(parent, getCurrentWorkspaceName(), child, properties.iterator()); 1127 return nextGraph; 1128 } 1129 }; 1130 } 1131 1132 /** 1133 * Set the properties on a node. 1134 * 1135 * @param properties the properties to set 1136 * @return the remove request object that should be used to specify the node on which the properties are to be set. 1137 */ 1138 public On<Conjunction<Graph>> set( final Property... properties ) { 1139 return new On<Conjunction<Graph>>() { 1140 public Conjunction<Graph> on( Location location ) { 1141 requests.setProperties(location, getCurrentWorkspaceName(), properties); 1142 return nextGraph; 1143 } 1144 1145 public Conjunction<Graph> on( String path ) { 1146 return on(Location.create(createPath(path))); 1147 } 1148 1149 public Conjunction<Graph> on( Path path ) { 1150 return on(Location.create(path)); 1151 } 1152 1153 public Conjunction<Graph> on( Property idProperty ) { 1154 return on(Location.create(idProperty)); 1155 } 1156 1157 public Conjunction<Graph> on( Property firstIdProperty, 1158 Property... additionalIdProperties ) { 1159 return on(Location.create(firstIdProperty, additionalIdProperties)); 1160 } 1161 1162 public Conjunction<Graph> on( Iterable<Property> idProperties ) { 1163 return on(Location.create(idProperties)); 1164 } 1165 1166 public Conjunction<Graph> on( UUID uuid ) { 1167 return on(Location.create(uuid)); 1168 } 1169 }; 1170 } 1171 1172 /** 1173 * Set a property on a node, starting with the name. The interface returned from this method should be used to specify the 1174 * value(s) and the location of the node onto which the property should be set. 1175 * 1176 * @param propertyName the property name 1177 * @return the interface used to specify the values 1178 */ 1179 public SetValues<Conjunction<Graph>> set( String propertyName ) { 1180 Name name = getContext().getValueFactories().getNameFactory().create(propertyName); 1181 return set(name); 1182 } 1183 1184 /** 1185 * Set a property on a node, starting with the name. The interface returned from this method should be used to specify the 1186 * value(s) and the location of the node onto which the property should be set. 1187 * 1188 * @param propertyName the property name 1189 * @return the interface used to specify the values 1190 */ 1191 public SetValues<Conjunction<Graph>> set( final Name propertyName ) { 1192 return new SetValues<Conjunction<Graph>>() { 1193 public SetValuesTo<Conjunction<Graph>> on( final Location location ) { 1194 return new SetValuesTo<Conjunction<Graph>>() { 1195 public Conjunction<Graph> to( Node value ) { 1196 Reference ref = (Reference)convertReferenceValue(value); 1197 Property property = getContext().getPropertyFactory().create(propertyName, ref); 1198 requests.setProperty(location, getCurrentWorkspaceName(), property); 1199 return nextGraph; 1200 } 1201 1202 public Conjunction<Graph> to( Location value ) { 1203 Reference ref = (Reference)convertReferenceValue(value); 1204 Property property = getContext().getPropertyFactory().create(propertyName, ref); 1205 requests.setProperty(location, getCurrentWorkspaceName(), property); 1206 return nextGraph; 1207 } 1208 1209 protected Conjunction<Graph> toValue( Object value ) { 1210 Property property = getContext().getPropertyFactory().create(propertyName, value); 1211 requests.setProperty(location, getCurrentWorkspaceName(), property); 1212 return nextGraph; 1213 } 1214 1215 public Conjunction<Graph> to( String value ) { 1216 return toValue(value); 1217 } 1218 1219 public Conjunction<Graph> to( int value ) { 1220 return toValue(Integer.valueOf(value)); 1221 } 1222 1223 public Conjunction<Graph> to( long value ) { 1224 return toValue(Long.valueOf(value)); 1225 } 1226 1227 public Conjunction<Graph> to( boolean value ) { 1228 return toValue(Boolean.valueOf(value)); 1229 } 1230 1231 public Conjunction<Graph> to( float value ) { 1232 return toValue(Float.valueOf(value)); 1233 } 1234 1235 public Conjunction<Graph> to( double value ) { 1236 return toValue(Double.valueOf(value)); 1237 } 1238 1239 public Conjunction<Graph> to( BigDecimal value ) { 1240 return toValue(value); 1241 } 1242 1243 public Conjunction<Graph> to( Calendar value ) { 1244 return toValue(value); 1245 } 1246 1247 public Conjunction<Graph> to( Date value ) { 1248 return toValue(value); 1249 } 1250 1251 public Conjunction<Graph> to( DateTime value ) { 1252 return toValue(value); 1253 } 1254 1255 public Conjunction<Graph> to( Name value ) { 1256 return toValue(value); 1257 } 1258 1259 public Conjunction<Graph> to( Path value ) { 1260 return toValue(value); 1261 } 1262 1263 public Conjunction<Graph> to( Reference value ) { 1264 return toValue(value); 1265 } 1266 1267 public Conjunction<Graph> to( URI value ) { 1268 return toValue(value); 1269 } 1270 1271 public Conjunction<Graph> to( UUID value ) { 1272 return toValue(value); 1273 } 1274 1275 public Conjunction<Graph> to( Binary value ) { 1276 return toValue(value); 1277 } 1278 1279 public Conjunction<Graph> to( byte[] value ) { 1280 return toValue(value); 1281 } 1282 1283 public Conjunction<Graph> to( InputStream stream, 1284 long approximateLength ) { 1285 Binary value = getContext().getValueFactories().getBinaryFactory().create(stream, approximateLength); 1286 return toValue(value); 1287 } 1288 1289 public Conjunction<Graph> to( Reader reader, 1290 long approximateLength ) { 1291 Binary value = getContext().getValueFactories().getBinaryFactory().create(reader, approximateLength); 1292 return toValue(value); 1293 } 1294 1295 public Conjunction<Graph> to( Object value ) { 1296 value = convertReferenceValue(value); 1297 Property property = getContext().getPropertyFactory().create(propertyName, value); 1298 requests.setProperty(location, getCurrentWorkspaceName(), property); 1299 return nextGraph; 1300 } 1301 1302 public Conjunction<Graph> to( Object firstValue, 1303 Object... otherValues ) { 1304 firstValue = convertReferenceValue(firstValue); 1305 for (int i = 0, len = otherValues.length; i != len; ++i) { 1306 otherValues[i] = convertReferenceValue(otherValues[i]); 1307 } 1308 Property property = getContext().getPropertyFactory().create(propertyName, firstValue, otherValues); 1309 requests.setProperty(location, getCurrentWorkspaceName(), property); 1310 return nextGraph; 1311 } 1312 1313 public Conjunction<Graph> to( Iterable<?> values ) { 1314 List<Object> valueList = new LinkedList<Object>(); 1315 for (Object value : values) { 1316 value = convertReferenceValue(value); 1317 valueList.add(value); 1318 } 1319 Property property = getContext().getPropertyFactory().create(propertyName, valueList); 1320 requests.setProperty(location, getCurrentWorkspaceName(), property); 1321 return nextGraph; 1322 } 1323 1324 public Conjunction<Graph> to( Iterator<?> values ) { 1325 List<Object> valueList = new LinkedList<Object>(); 1326 while (values.hasNext()) { 1327 Object value = values.next(); 1328 valueList.add(value); 1329 } 1330 Property property = getContext().getPropertyFactory().create(propertyName, valueList); 1331 requests.setProperty(location, getCurrentWorkspaceName(), property); 1332 return nextGraph; 1333 } 1334 }; 1335 } 1336 1337 public SetValuesTo<Conjunction<Graph>> on( String path ) { 1338 return on(Location.create(createPath(path))); 1339 } 1340 1341 public SetValuesTo<Conjunction<Graph>> on( Path path ) { 1342 return on(Location.create(path)); 1343 } 1344 1345 public SetValuesTo<Conjunction<Graph>> on( Property idProperty ) { 1346 return on(Location.create(idProperty)); 1347 } 1348 1349 public SetValuesTo<Conjunction<Graph>> on( Property firstIdProperty, 1350 Property... additionalIdProperties ) { 1351 return on(Location.create(firstIdProperty, additionalIdProperties)); 1352 } 1353 1354 public SetValuesTo<Conjunction<Graph>> on( Iterable<Property> idProperties ) { 1355 return on(Location.create(idProperties)); 1356 } 1357 1358 public SetValuesTo<Conjunction<Graph>> on( UUID uuid ) { 1359 return on(Location.create(uuid)); 1360 } 1361 1362 public On<Conjunction<Graph>> to( Node node ) { 1363 Reference value = (Reference)convertReferenceValue(node); 1364 return set(getContext().getPropertyFactory().create(propertyName, value)); 1365 } 1366 1367 public On<Conjunction<Graph>> to( Location location ) { 1368 Reference value = (Reference)convertReferenceValue(location); 1369 return set(getContext().getPropertyFactory().create(propertyName, value)); 1370 } 1371 1372 protected On<Conjunction<Graph>> toValue( Object value ) { 1373 return set(getContext().getPropertyFactory().create(propertyName, value)); 1374 } 1375 1376 public On<Conjunction<Graph>> to( String value ) { 1377 return toValue(value); 1378 } 1379 1380 public On<Conjunction<Graph>> to( int value ) { 1381 return toValue(Integer.valueOf(value)); 1382 } 1383 1384 public On<Conjunction<Graph>> to( long value ) { 1385 return toValue(Long.valueOf(value)); 1386 } 1387 1388 public On<Conjunction<Graph>> to( boolean value ) { 1389 return toValue(Boolean.valueOf(value)); 1390 } 1391 1392 public On<Conjunction<Graph>> to( float value ) { 1393 return toValue(Float.valueOf(value)); 1394 } 1395 1396 public On<Conjunction<Graph>> to( double value ) { 1397 return toValue(Double.valueOf(value)); 1398 } 1399 1400 public On<Conjunction<Graph>> to( BigDecimal value ) { 1401 return toValue(value); 1402 } 1403 1404 public On<Conjunction<Graph>> to( Calendar value ) { 1405 return toValue(value); 1406 } 1407 1408 public On<Conjunction<Graph>> to( Date value ) { 1409 return toValue(value); 1410 } 1411 1412 public On<Conjunction<Graph>> to( DateTime value ) { 1413 return toValue(value); 1414 } 1415 1416 public On<Conjunction<Graph>> to( Name value ) { 1417 return toValue(value); 1418 } 1419 1420 public On<Conjunction<Graph>> to( Path value ) { 1421 return toValue(value); 1422 } 1423 1424 public On<Conjunction<Graph>> to( Reference value ) { 1425 return toValue(value); 1426 } 1427 1428 public On<Conjunction<Graph>> to( URI value ) { 1429 return toValue(value); 1430 } 1431 1432 public On<Conjunction<Graph>> to( UUID value ) { 1433 return toValue(value); 1434 } 1435 1436 public On<Conjunction<Graph>> to( Binary value ) { 1437 return toValue(value); 1438 } 1439 1440 public On<Conjunction<Graph>> to( byte[] value ) { 1441 return toValue(value); 1442 } 1443 1444 public On<Conjunction<Graph>> to( InputStream stream, 1445 long approximateLength ) { 1446 Binary value = getContext().getValueFactories().getBinaryFactory().create(stream, approximateLength); 1447 return toValue(value); 1448 } 1449 1450 public On<Conjunction<Graph>> to( Reader reader, 1451 long approximateLength ) { 1452 Binary value = getContext().getValueFactories().getBinaryFactory().create(reader, approximateLength); 1453 return toValue(value); 1454 } 1455 1456 public On<Conjunction<Graph>> to( Object value ) { 1457 value = convertReferenceValue(value); 1458 return set(getContext().getPropertyFactory().create(propertyName, value)); 1459 } 1460 1461 public On<Conjunction<Graph>> to( Object firstValue, 1462 Object... otherValues ) { 1463 firstValue = convertReferenceValue(firstValue); 1464 for (int i = 0, len = otherValues.length; i != len; ++i) { 1465 otherValues[i] = convertReferenceValue(otherValues[i]); 1466 } 1467 return set(getContext().getPropertyFactory().create(propertyName, firstValue, otherValues)); 1468 } 1469 1470 public On<Conjunction<Graph>> to( Iterable<?> values ) { 1471 List<Object> valueList = new LinkedList<Object>(); 1472 for (Object value : values) { 1473 value = convertReferenceValue(value); 1474 valueList.add(value); 1475 } 1476 return set(getContext().getPropertyFactory().create(propertyName, valueList)); 1477 } 1478 1479 public On<Conjunction<Graph>> to( Iterator<?> values ) { 1480 List<Object> valueList = new LinkedList<Object>(); 1481 while (values.hasNext()) { 1482 Object value = values.next(); 1483 valueList.add(value); 1484 } 1485 return set(getContext().getPropertyFactory().create(propertyName, valueList)); 1486 } 1487 }; 1488 } 1489 1490 /** 1491 * Remove properties from the node at the given location. 1492 * 1493 * @param propertyNames the names of the properties to be removed 1494 * @return the remove request object that should be used to specify the node from which the properties are to be removed. 1495 */ 1496 public On<Conjunction<Graph>> remove( final Name... propertyNames ) { 1497 return new On<Conjunction<Graph>>() { 1498 public Conjunction<Graph> on( Location location ) { 1499 requests.removeProperties(location, getCurrentWorkspaceName(), propertyNames); 1500 return nextGraph; 1501 } 1502 1503 public Conjunction<Graph> on( String path ) { 1504 return on(Location.create(createPath(path))); 1505 } 1506 1507 public Conjunction<Graph> on( Path path ) { 1508 return on(Location.create(path)); 1509 } 1510 1511 public Conjunction<Graph> on( Property idProperty ) { 1512 return on(Location.create(idProperty)); 1513 } 1514 1515 public Conjunction<Graph> on( Property firstIdProperty, 1516 Property... additionalIdProperties ) { 1517 return on(Location.create(firstIdProperty, additionalIdProperties)); 1518 } 1519 1520 public Conjunction<Graph> on( Iterable<Property> idProperties ) { 1521 return on(Location.create(idProperties)); 1522 } 1523 1524 public Conjunction<Graph> on( UUID uuid ) { 1525 return on(Location.create(uuid)); 1526 } 1527 }; 1528 } 1529 1530 /** 1531 * Remove properties from the node at the given location. 1532 * 1533 * @param propertyNames the names of the properties to be removed 1534 * @return the remove request object that should be used to specify the node from which the properties are to be removed. 1535 */ 1536 public On<Conjunction<Graph>> remove( final String... propertyNames ) { 1537 NameFactory nameFactory = getContext().getValueFactories().getNameFactory(); 1538 int number = propertyNames.length; 1539 final Name[] names = new Name[number]; 1540 for (int i = 0; i != number; ++i) { 1541 names[i] = nameFactory.create(propertyNames[i]); 1542 } 1543 return new On<Conjunction<Graph>>() { 1544 public Conjunction<Graph> on( Location location ) { 1545 requests.removeProperties(location, getCurrentWorkspaceName(), names); 1546 return nextGraph; 1547 } 1548 1549 public Conjunction<Graph> on( String path ) { 1550 return on(Location.create(createPath(path))); 1551 } 1552 1553 public Conjunction<Graph> on( Path path ) { 1554 return on(Location.create(path)); 1555 } 1556 1557 public Conjunction<Graph> on( Property idProperty ) { 1558 return on(Location.create(idProperty)); 1559 } 1560 1561 public Conjunction<Graph> on( Property firstIdProperty, 1562 Property... additionalIdProperties ) { 1563 return on(Location.create(firstIdProperty, additionalIdProperties)); 1564 } 1565 1566 public Conjunction<Graph> on( Iterable<Property> idProperties ) { 1567 return on(Location.create(idProperties)); 1568 } 1569 1570 public Conjunction<Graph> on( UUID uuid ) { 1571 return on(Location.create(uuid)); 1572 } 1573 }; 1574 } 1575 1576 /** 1577 * Request that the properties be read on the node defined via the <code>on(...)</code> method on the returned {@link On} 1578 * object. Once the location is specified, the {@link Collection collection of properties} are read and then returned. 1579 * 1580 * @return the object that is used to specified the node whose properties are to be read, and which will return the properties 1581 */ 1582 public On<Collection<Property>> getProperties() { 1583 return new On<Collection<Property>>() { 1584 public Collection<Property> on( Location location ) { 1585 return requests.readAllProperties(location, getCurrentWorkspaceName()).getProperties(); 1586 } 1587 1588 public Collection<Property> on( String path ) { 1589 return on(Location.create(createPath(path))); 1590 } 1591 1592 public Collection<Property> on( Path path ) { 1593 return on(Location.create(path)); 1594 } 1595 1596 public Collection<Property> on( Property idProperty ) { 1597 return on(Location.create(idProperty)); 1598 } 1599 1600 public Collection<Property> on( Property firstIdProperty, 1601 Property... additionalIdProperties ) { 1602 return on(Location.create(firstIdProperty, additionalIdProperties)); 1603 } 1604 1605 public Collection<Property> on( Iterable<Property> idProperties ) { 1606 return on(Location.create(idProperties)); 1607 } 1608 1609 public Collection<Property> on( UUID uuid ) { 1610 return on(Location.create(uuid)); 1611 } 1612 }; 1613 } 1614 1615 /** 1616 * Request that the properties be read on the node defined via the <code>on(...)</code> method on the returned {@link On} 1617 * object. Once the location is specified, the {@link Map map of properties} are read and then returned. 1618 * 1619 * @return the object that is used to specified the node whose properties are to be read, and which will return the properties 1620 * as a map keyed by their name 1621 */ 1622 public On<Map<Name, Property>> getPropertiesByName() { 1623 return new On<Map<Name, Property>>() { 1624 public Map<Name, Property> on( Location location ) { 1625 return requests.readAllProperties(location, getCurrentWorkspaceName()).getPropertiesByName(); 1626 } 1627 1628 public Map<Name, Property> on( String path ) { 1629 return on(Location.create(createPath(path))); 1630 } 1631 1632 public Map<Name, Property> on( Path path ) { 1633 return on(Location.create(path)); 1634 } 1635 1636 public Map<Name, Property> on( Property idProperty ) { 1637 return on(Location.create(idProperty)); 1638 } 1639 1640 public Map<Name, Property> on( Property firstIdProperty, 1641 Property... additionalIdProperties ) { 1642 return on(Location.create(firstIdProperty, additionalIdProperties)); 1643 } 1644 1645 public Map<Name, Property> on( Iterable<Property> idProperties ) { 1646 return on(Location.create(idProperties)); 1647 } 1648 1649 public Map<Name, Property> on( UUID uuid ) { 1650 return on(Location.create(uuid)); 1651 } 1652 }; 1653 } 1654 1655 /** 1656 * Request that the children be read on the node defined via the <code>of(...)</code> method on the returned {@link Of} 1657 * object. The returned object is used to supply the remaining information, including either the {@link Children#of(Location) 1658 * location of the parent}, or that a subset of the children should be retrieved {@link Children#inBlockOf(int) in a block}. 1659 * 1660 * @return the object that is used to specify the remaining inputs for the request, and which will return the children 1661 */ 1662 public Children<List<Location>> getChildren() { 1663 return new Children<List<Location>>() { 1664 public List<Location> of( String path ) { 1665 return of(Location.create(createPath(path))); 1666 } 1667 1668 public List<Location> of( Path path ) { 1669 return of(Location.create(path)); 1670 } 1671 1672 public List<Location> of( Property idProperty ) { 1673 return of(Location.create(idProperty)); 1674 } 1675 1676 public List<Location> of( Property firstIdProperty, 1677 Property... additionalIdProperties ) { 1678 return of(Location.create(firstIdProperty, additionalIdProperties)); 1679 } 1680 1681 public List<Location> of( Iterable<Property> idProperties ) { 1682 return of(Location.create(idProperties)); 1683 } 1684 1685 public List<Location> of( UUID uuid ) { 1686 return of(Location.create(uuid)); 1687 } 1688 1689 public List<Location> of( Location at ) { 1690 return requests.readAllChildren(at, getCurrentWorkspaceName()).getChildren(); 1691 } 1692 1693 public BlockOfChildren<List<Location>> inBlockOf( final int blockSize ) { 1694 return new BlockOfChildren<List<Location>>() { 1695 public Under<List<Location>> startingAt( final int startingIndex ) { 1696 return new Under<List<Location>>() { 1697 public List<Location> under( String path ) { 1698 return under(Location.create(createPath(path))); 1699 } 1700 1701 public List<Location> under( Path path ) { 1702 return under(Location.create(path)); 1703 } 1704 1705 public List<Location> under( Property idProperty ) { 1706 return under(Location.create(idProperty)); 1707 } 1708 1709 public List<Location> under( Property firstIdProperty, 1710 Property... additionalIdProperties ) { 1711 return under(Location.create(firstIdProperty, additionalIdProperties)); 1712 } 1713 1714 public List<Location> under( UUID uuid ) { 1715 return under(Location.create(uuid)); 1716 } 1717 1718 public List<Location> under( Location at ) { 1719 return requests.readBlockOfChildren(at, getCurrentWorkspaceName(), startingIndex, blockSize) 1720 .getChildren(); 1721 } 1722 }; 1723 } 1724 1725 public List<Location> startingAfter( final Location previousSibling ) { 1726 return requests.readNextBlockOfChildren(previousSibling, getCurrentWorkspaceName(), blockSize) 1727 .getChildren(); 1728 } 1729 1730 public List<Location> startingAfter( String pathOfPreviousSibling ) { 1731 return startingAfter(Location.create(createPath(pathOfPreviousSibling))); 1732 } 1733 1734 public List<Location> startingAfter( Path pathOfPreviousSibling ) { 1735 return startingAfter(Location.create(pathOfPreviousSibling)); 1736 } 1737 1738 public List<Location> startingAfter( UUID uuidOfPreviousSibling ) { 1739 return startingAfter(Location.create(uuidOfPreviousSibling)); 1740 } 1741 1742 public List<Location> startingAfter( Property idPropertyOfPreviousSibling ) { 1743 return startingAfter(Location.create(idPropertyOfPreviousSibling)); 1744 } 1745 1746 public List<Location> startingAfter( Property firstIdProperyOfPreviousSibling, 1747 Property... additionalIdPropertiesOfPreviousSibling ) { 1748 return startingAfter(Location.create(firstIdProperyOfPreviousSibling, 1749 additionalIdPropertiesOfPreviousSibling)); 1750 } 1751 }; 1752 } 1753 }; 1754 } 1755 1756 /** 1757 * Request that the property with the given name be read on the node defined via the <code>on(...)</code> method on the 1758 * returned {@link On} object. Once the location is specified, the {@link Property property} is read and then returned. 1759 * 1760 * @param name the name of the property that is to be read 1761 * @return the object that is used to specified the node whose property is to be read, and which will return the property 1762 */ 1763 public On<Property> getProperty( final String name ) { 1764 Name nameObj = context.getValueFactories().getNameFactory().create(name); 1765 return getProperty(nameObj); 1766 } 1767 1768 /** 1769 * Request that the property with the given name be read on the node defined via the <code>on(...)</code> method on the 1770 * returned {@link On} object. Once the location is specified, the {@link Property property} is read and then returned. 1771 * 1772 * @param name the name of the property that is to be read 1773 * @return the object that is used to specified the node whose property is to be read, and which will return the property 1774 */ 1775 public On<Property> getProperty( final Name name ) { 1776 return new On<Property>() { 1777 public Property on( String path ) { 1778 return on(Location.create(createPath(path))); 1779 } 1780 1781 public Property on( Path path ) { 1782 return on(Location.create(path)); 1783 } 1784 1785 public Property on( Property idProperty ) { 1786 return on(Location.create(idProperty)); 1787 } 1788 1789 public Property on( Property firstIdProperty, 1790 Property... additionalIdProperties ) { 1791 return on(Location.create(firstIdProperty, additionalIdProperties)); 1792 } 1793 1794 public Property on( Iterable<Property> idProperties ) { 1795 return on(Location.create(idProperties)); 1796 } 1797 1798 public Property on( UUID uuid ) { 1799 return on(Location.create(uuid)); 1800 } 1801 1802 public Property on( Location at ) { 1803 return requests.readProperty(at, getCurrentWorkspaceName(), name).getProperty(); 1804 } 1805 }; 1806 } 1807 1808 /** 1809 * Request to read the node with the supplied UUID. 1810 * 1811 * @param uuid the UUID of the node that is to be read 1812 * @return the node that is read from the repository 1813 */ 1814 public Node getNodeAt( UUID uuid ) { 1815 return getNodeAt(Location.create(uuid)); 1816 } 1817 1818 /** 1819 * Request to read the node at the supplied location. 1820 * 1821 * @param location the location of the node that is to be read 1822 * @return the node that is read from the repository 1823 */ 1824 public Node getNodeAt( Location location ) { 1825 return new GraphNode(requests.readNode(location, getCurrentWorkspaceName())); 1826 } 1827 1828 /** 1829 * Request to read the node at the supplied path. 1830 * 1831 * @param path the path of the node that is to be read 1832 * @return the node that is read from the repository 1833 */ 1834 public Node getNodeAt( String path ) { 1835 return getNodeAt(Location.create(createPath(path))); 1836 } 1837 1838 /** 1839 * Request to read the node at the supplied path. 1840 * 1841 * @param path the path of the node that is to be read 1842 * @return the node that is read from the repository 1843 */ 1844 public Node getNodeAt( Path path ) { 1845 return getNodeAt(Location.create(path)); 1846 } 1847 1848 /** 1849 * Request to read the node with the supplied unique identifier property. 1850 * 1851 * @param idProperty the identification property that is unique to the node that is to be read 1852 * @return the node that is read from the repository 1853 */ 1854 public Node getNodeAt( Property idProperty ) { 1855 return getNodeAt(Location.create(idProperty)); 1856 } 1857 1858 /** 1859 * Request to read the node with the supplied unique identifier properties. 1860 * 1861 * @param firstIdProperty the first of the identification properties that uniquely identify the node that is to be read 1862 * @param additionalIdProperties the remaining identification properties that uniquely identify the node that is to be read 1863 * @return the node that is read from the repository 1864 */ 1865 public Node getNodeAt( Property firstIdProperty, 1866 Property... additionalIdProperties ) { 1867 return getNodeAt(Location.create(firstIdProperty, additionalIdProperties)); 1868 } 1869 1870 /** 1871 * Request to read the node with the supplied unique identifier properties. 1872 * 1873 * @param idProperties the identification properties that uniquely identify the node that is to be read 1874 * @return the node that is read from the repository 1875 */ 1876 public Node getNodeAt( Iterable<Property> idProperties ) { 1877 return getNodeAt(Location.create(idProperties)); 1878 } 1879 1880 /** 1881 * Request to read the node given by the supplied reference value. 1882 * 1883 * @param reference the reference property value that is to be resolved into a node 1884 * @return the node that is read from the repository 1885 * @throws ValueFormatException if the supplied reference could not be converted to an identifier property value 1886 */ 1887 public Node resolve( Reference reference ) { 1888 CheckArg.isNotNull(reference, "reference"); 1889 UUID uuid = context.getValueFactories().getUuidFactory().create(reference); 1890 return getNodeAt(uuid); 1891 } 1892 1893 /** 1894 * Request to read a subgraph of the specified depth, rooted at a location that will be specified via <code>at(...)</code> in 1895 * the resulting {@link At} object. All properties and children of every node in the subgraph will be read and returned in the 1896 * {@link Subgraph} object returned from the <code>at(...)</code> methods. 1897 * 1898 * @param depth the maximum depth of the subgraph that should be read 1899 * @return the component that should be used to specify the location of the node that is the top of the subgraph, and which 1900 * will return the {@link Subgraph} containing the results 1901 */ 1902 public At<Subgraph> getSubgraphOfDepth( final int depth ) { 1903 return new At<Subgraph>() { 1904 public Subgraph at( Location location ) { 1905 return new SubgraphResults(requests.readBranch(location, getCurrentWorkspaceName(), depth)); 1906 } 1907 1908 public Subgraph at( String path ) { 1909 return at(Location.create(createPath(path))); 1910 } 1911 1912 public Subgraph at( Path path ) { 1913 return at(Location.create(path)); 1914 } 1915 1916 public Subgraph at( UUID uuid ) { 1917 return at(Location.create(uuid)); 1918 } 1919 1920 public Subgraph at( Property idProperty ) { 1921 return at(Location.create(idProperty)); 1922 } 1923 1924 public Subgraph at( Property firstIdProperty, 1925 Property... additionalIdProperties ) { 1926 return at(Location.create(firstIdProperty, additionalIdProperties)); 1927 } 1928 1929 public Subgraph at( Iterable<Property> idProperties ) { 1930 return at(Location.create(idProperties)); 1931 } 1932 }; 1933 } 1934 1935 /** 1936 * Import the content from the XML file at the supplied URI, specifying via the returned {@link ImportInto object} where the 1937 * content is to be imported. 1938 * 1939 * @param uri the URI where the importer can read the content that is to be imported 1940 * @return the object that should be used to specify into which the content is to be imported 1941 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null 1942 */ 1943 public ImportInto<Conjunction<Graph>> importXmlFrom( final URI uri ) { 1944 return new ImportInto<Conjunction<Graph>>() { 1945 private boolean skipRootElement = false; 1946 1947 public ImportInto<Conjunction<Graph>> skippingRootElement( boolean skipRootElement ) { 1948 this.skipRootElement = skipRootElement; 1949 return this; 1950 } 1951 1952 public Conjunction<Graph> into( String path ) throws IOException, SAXException { 1953 return into(Location.create(createPath(path))); 1954 } 1955 1956 public Conjunction<Graph> into( Path path ) throws IOException, SAXException { 1957 return into(Location.create(path)); 1958 } 1959 1960 public Conjunction<Graph> into( Property idProperty ) throws IOException, SAXException { 1961 return into(Location.create(idProperty)); 1962 } 1963 1964 public Conjunction<Graph> into( Property firstIdProperty, 1965 Property... additionalIdProperties ) throws IOException, SAXException { 1966 return into(Location.create(firstIdProperty, additionalIdProperties)); 1967 } 1968 1969 public Conjunction<Graph> into( Iterable<Property> idProperties ) throws IOException, SAXException { 1970 return into(Location.create(idProperties)); 1971 } 1972 1973 public Conjunction<Graph> into( UUID uuid ) throws IOException, SAXException { 1974 return into(Location.create(uuid)); 1975 } 1976 1977 public Conjunction<Graph> into( Location at ) throws IOException, SAXException { 1978 GraphImporter importer = new GraphImporter(Graph.this); 1979 importer.importXml(uri, at, skipRootElement).execute(); // 'importXml' creates and uses a new batch 1980 return Graph.this.nextGraph; 1981 } 1982 }; 1983 } 1984 1985 /** 1986 * Import the content from the XML file at the supplied file location, specifying via the returned {@link ImportInto object} 1987 * where the content is to be imported. 1988 * 1989 * @param pathToFile the path to the XML file that should be imported. 1990 * @return the object that should be used to specify into which the content is to be imported 1991 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null 1992 */ 1993 public ImportInto<Conjunction<Graph>> importXmlFrom( String pathToFile ) { 1994 CheckArg.isNotNull(pathToFile, "pathToFile"); 1995 return importXmlFrom(new File(pathToFile).toURI()); 1996 } 1997 1998 /** 1999 * Import the content from the XML file at the supplied file, specifying via the returned {@link ImportInto object} where the 2000 * content is to be imported. 2001 * 2002 * @param file the XML file that should be imported. 2003 * @return the object that should be used to specify into which the content is to be imported 2004 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null 2005 */ 2006 public ImportInto<Conjunction<Graph>> importXmlFrom( File file ) { 2007 CheckArg.isNotNull(file, "file"); 2008 return importXmlFrom(file.toURI()); 2009 } 2010 2011 protected Path createPath( String path ) { 2012 return getContext().getValueFactories().getPathFactory().create(path); 2013 } 2014 2015 protected List<Segment> getSegments( List<Location> locations ) { 2016 List<Segment> segments = new ArrayList<Segment>(locations.size()); 2017 for (Location location : locations) { 2018 segments.add(location.getPath().getLastSegment()); 2019 } 2020 return segments; 2021 } 2022 2023 /** 2024 * Begin a batch of requests to perform various operations. Use this approach when multiple operations are to be built and 2025 * then executed with one submission to the underlying {@link #getSourceName() repository source}. The {@link Results results} 2026 * are not available until the {@link Batch#execute()} method is invoked. 2027 * 2028 * @return the batch object used to build and accumulate multiple requests and to submit them all for processing at once. 2029 * @see Batch#execute() 2030 * @see Results 2031 */ 2032 public Batch batch() { 2033 return new Batch(new BatchRequestBuilder()); 2034 } 2035 2036 /** 2037 * Begin a batch of requests to perform various operations, but specify the queue where all accumulated requests should be 2038 * placed. Use this approach when multiple operations are to be built and then executed with one submission to the underlying 2039 * {@link #getSourceName() repository source}. The {@link Results results} are not available until the {@link Batch#execute()} 2040 * method is invoked. 2041 * 2042 * @param builder the request builder that should be used; may not be null 2043 * @return the batch object used to build and accumulate multiple requests and to submit them all for processing at once. 2044 * @see Batch#execute() 2045 * @see Results 2046 */ 2047 public Batch batch( BatchRequestBuilder builder ) { 2048 CheckArg.isNotNull(builder, "builder"); 2049 return new Batch(builder); 2050 } 2051 2052 /** 2053 * Interface for creating multiple requests to perform various operations. Note that all the requests are accumulated until 2054 * the {@link #execute()} method is called. The results of all the operations are then available in the {@link Results} object 2055 * returned by the {@link #execute()}. 2056 * 2057 * @author Randall Hauch 2058 */ 2059 @Immutable 2060 public final class Batch implements Executable<Node> { 2061 protected final BatchRequestBuilder requestQueue; 2062 protected final BatchConjunction nextRequests; 2063 protected final String workspaceName; 2064 protected boolean executed = false; 2065 2066 /*package*/Batch( BatchRequestBuilder builder ) { 2067 assert builder != null; 2068 this.requestQueue = builder; 2069 this.workspaceName = Graph.this.getCurrentWorkspaceName(); 2070 this.nextRequests = new BatchConjunction() { 2071 public Batch and() { 2072 return Batch.this; 2073 } 2074 2075 public Results execute() { 2076 return Batch.this.execute(); 2077 } 2078 }; 2079 } 2080 2081 /** 2082 * Return whether this batch has been {@link #execute() executed}. 2083 * 2084 * @return true if this batch has already been executed, or false otherwise 2085 */ 2086 public boolean hasExecuted() { 2087 return executed; 2088 } 2089 2090 /** 2091 * Determine whether this batch needs to be executed (there are requests and the batch has not been executed yet). 2092 * 2093 * @return true if there are some requests in this batch that need to be executed, or false execution is not required 2094 */ 2095 public boolean isExecuteRequired() { 2096 return !executed && requestQueue.hasRequests(); 2097 } 2098 2099 /** 2100 * Obtain the graph that this batch uses. 2101 * 2102 * @return the graph; never null 2103 */ 2104 public Graph getGraph() { 2105 return Graph.this; 2106 } 2107 2108 /** 2109 * Get the name of the workspace that this batch is using. This is always constant throughout the lifetime of the batch. 2110 * 2111 * @return the name of the workspace; never null 2112 */ 2113 public String getCurrentWorkspaceName() { 2114 return this.workspaceName; 2115 } 2116 2117 protected final void assertNotExecuted() { 2118 if (executed) { 2119 throw new IllegalStateException(GraphI18n.unableToAddMoreRequestsToAlreadyExecutedBatch.text()); 2120 } 2121 } 2122 2123 /** 2124 * Begin the request to move the specified node into a parent node at a different location, which is specified via the 2125 * <code>into(...)</code> method on the returned {@link Move} object. 2126 * <p> 2127 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2128 * called. 2129 * </p> 2130 * 2131 * @param from the node that is to be moved. 2132 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2133 * to be moved 2134 */ 2135 public Move<BatchConjunction> move( Node from ) { 2136 return move(from.getLocation()); 2137 } 2138 2139 /** 2140 * Begin the request to move a node at the specified location into a parent node at a different location, which is 2141 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 2142 * <p> 2143 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2144 * called. 2145 * </p> 2146 * 2147 * @param from the location of the node that is to be moved. 2148 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2149 * to be moved 2150 */ 2151 public final Move<BatchConjunction> move( Location from ) { 2152 assertNotExecuted(); 2153 return new MoveAction<BatchConjunction>(this.nextRequests, from) { 2154 @Override 2155 protected BatchConjunction submit( Locations from, 2156 Location into, 2157 Name newName ) { 2158 String workspaceName = getCurrentWorkspaceName(); 2159 do { 2160 requestQueue.moveBranch(from.getLocation(), into, workspaceName, newName); 2161 } while ((from = from.next()) != null); 2162 return and(); 2163 } 2164 }; 2165 } 2166 2167 /** 2168 * Begin the request to move a node located at the supplied path into a parent node at a different location, which is 2169 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 2170 * <p> 2171 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2172 * called. 2173 * </p> 2174 * 2175 * @param fromPath the path to the node that is to be moved. 2176 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2177 * to be moved 2178 */ 2179 public Move<BatchConjunction> move( String fromPath ) { 2180 return move(Location.create(createPath(fromPath))); 2181 } 2182 2183 /** 2184 * Begin the request to move a node located at the supplied path into a parent node at a different location, which is 2185 * specified via the <code>into(...)</code> method on the returned {@link Move} object. 2186 * <p> 2187 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2188 * called. 2189 * </p> 2190 * 2191 * @param from the path to the node that is to be moved. 2192 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2193 * to be moved 2194 */ 2195 public Move<BatchConjunction> move( Path from ) { 2196 return move(Location.create(from)); 2197 } 2198 2199 /** 2200 * Begin the request to move a node with the specified unique identifier into a parent node at a different location, which 2201 * is specified via the <code>into(...)</code> method on the returned {@link Move} object. 2202 * <p> 2203 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2204 * called. 2205 * </p> 2206 * 2207 * @param from the UUID of the node that is to be moved. 2208 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2209 * to be moved 2210 */ 2211 public Move<BatchConjunction> move( UUID from ) { 2212 return move(Location.create(from)); 2213 } 2214 2215 /** 2216 * Begin the request to move a node with the specified unique identification property into a parent node at a different 2217 * location, which is specified via the <code>into(...)</code> method on the returned {@link Move} object. The 2218 * identification property should uniquely identify a single node. 2219 * <p> 2220 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2221 * called. 2222 * </p> 2223 * 2224 * @param idProperty the unique identification property of the node that is to be moved. 2225 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2226 * to be moved 2227 */ 2228 public Move<BatchConjunction> move( Property idProperty ) { 2229 return move(Location.create(idProperty)); 2230 } 2231 2232 /** 2233 * Begin the request to move a node with the specified identification properties into a parent node at a different 2234 * location, which is specified via the <code>into(...)</code> method on the returned {@link Move} object. The 2235 * identification properties should uniquely identify a single node. 2236 * <p> 2237 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2238 * called. 2239 * </p> 2240 * 2241 * @param firstIdProperty the first identification property of the node that is to be moved 2242 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be moved 2243 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2244 * to be moved 2245 */ 2246 public Move<BatchConjunction> move( Property firstIdProperty, 2247 Property... additionalIdProperties ) { 2248 return move(Location.create(firstIdProperty, additionalIdProperties)); 2249 } 2250 2251 /** 2252 * Begin the request to move a node with the specified identification properties into a parent node at a different 2253 * location, which is specified via the <code>into(...)</code> method on the returned {@link Move} object. The 2254 * identification properties should uniquely identify a single node. 2255 * <p> 2256 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2257 * called. 2258 * </p> 2259 * 2260 * @param idProperties the idenficiation properties of the node that is to be moved 2261 * @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is 2262 * to be moved 2263 */ 2264 public Move<BatchConjunction> move( Iterable<Property> idProperties ) { 2265 return move(Location.create(idProperties)); 2266 } 2267 2268 /** 2269 * Begin the request to copy the specified node into a parent node at a different location, which is specified via the 2270 * <code>into(...)</code> method on the returned {@link Copy} object. 2271 * <p> 2272 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2273 * called. 2274 * </p> 2275 * 2276 * @param from the node that is to be copied. 2277 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2278 * is to be copied 2279 */ 2280 public Copy<BatchConjunction> copy( Node from ) { 2281 return copy(from.getLocation()); 2282 } 2283 2284 /** 2285 * Begin the request to copy a node at the specified location into a parent node at a different location, which is 2286 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 2287 * <p> 2288 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2289 * called. 2290 * </p> 2291 * 2292 * @param from the location of the node that is to be copied. 2293 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2294 * is to be copied 2295 */ 2296 public Copy<BatchConjunction> copy( Location from ) { 2297 assertNotExecuted(); 2298 return new CopyAction<BatchConjunction>(this.nextRequests, from) { 2299 @Override 2300 protected BatchConjunction submit( Locations from, 2301 Location into, 2302 Name copyName ) { 2303 String workspaceName = getCurrentWorkspaceName(); 2304 do { 2305 requestQueue.copyBranch(from.getLocation(), workspaceName, into, workspaceName, copyName); 2306 } while ((from = from.next()) != null); 2307 return and(); 2308 } 2309 }; 2310 } 2311 2312 /** 2313 * Begin the request to copy a node located at the supplied path into a parent node at a different location, which is 2314 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 2315 * <p> 2316 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2317 * called. 2318 * </p> 2319 * 2320 * @param fromPath the path to the node that is to be copied. 2321 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2322 * is to be copied 2323 */ 2324 public Copy<BatchConjunction> copy( String fromPath ) { 2325 return copy(Location.create(createPath(fromPath))); 2326 } 2327 2328 /** 2329 * Begin the request to copy a node located at the supplied path into a parent node at a different location, which is 2330 * specified via the <code>into(...)</code> method on the returned {@link Copy} object. 2331 * <p> 2332 * Like all other methods on the {@link Graph}, the copy request will be performed immediately when the 2333 * <code>into(...)</code> method is called. 2334 * </p> 2335 * 2336 * @param from the path to the node that is to be copied. 2337 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2338 * is to be copied 2339 */ 2340 public Copy<BatchConjunction> copy( Path from ) { 2341 return copy(Location.create(from)); 2342 } 2343 2344 /** 2345 * Begin the request to copy a node with the specified unique identifier into a parent node at a different location, which 2346 * is specified via the <code>into(...)</code> method on the returned {@link Copy} object. 2347 * <p> 2348 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2349 * called. 2350 * </p> 2351 * 2352 * @param from the UUID of the node that is to be copied. 2353 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2354 * is to be copied 2355 */ 2356 public Copy<BatchConjunction> copy( UUID from ) { 2357 return copy(Location.create(from)); 2358 } 2359 2360 /** 2361 * Begin the request to copy a node with the specified unique identification property into a parent node at a different 2362 * location, which is specified via the <code>into(...)</code> method on the returned {@link Copy} object. The 2363 * identification property should uniquely identify a single node. 2364 * <p> 2365 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2366 * called. 2367 * </p> 2368 * 2369 * @param idProperty the unique identification property of the node that is to be copied. 2370 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2371 * is to be copied 2372 */ 2373 public Copy<BatchConjunction> copy( Property idProperty ) { 2374 return copy(Location.create(idProperty)); 2375 } 2376 2377 /** 2378 * Begin the request to copy a node with the specified identification properties into a parent node at a different 2379 * location, which is specified via the <code>into(...)</code> method on the returned {@link Copy} object. The 2380 * identification properties should uniquely identify a single node. 2381 * <p> 2382 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2383 * called. 2384 * </p> 2385 * 2386 * @param firstIdProperty the first identification property of the node that is to be copied 2387 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be copied 2388 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2389 * is to be copied 2390 */ 2391 public Copy<BatchConjunction> copy( Property firstIdProperty, 2392 Property... additionalIdProperties ) { 2393 return copy(Location.create(firstIdProperty, additionalIdProperties)); 2394 } 2395 2396 /** 2397 * Begin the request to copy a node with the specified identification properties into a parent node at a different 2398 * location, which is specified via the <code>into(...)</code> method on the returned {@link Copy} object. The 2399 * identification properties should uniquely identify a single node. 2400 * <p> 2401 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2402 * called. 2403 * </p> 2404 * 2405 * @param idProperties the identification properties of the node that is to be copied 2406 * @return the object that can be used to specify addition nodes to be copied or the location of the node where the node 2407 * is to be copied 2408 */ 2409 public Copy<BatchConjunction> copy( Iterable<Property> idProperties ) { 2410 return copy(Location.create(idProperties)); 2411 } 2412 2413 /** 2414 * Request to delete the specified node. 2415 * <p> 2416 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2417 * called. 2418 * </p> 2419 * 2420 * @param at the node that is to be deleted 2421 * @return an object that may be used to start another request 2422 */ 2423 public BatchConjunction delete( Node at ) { 2424 return delete(at.getLocation()); 2425 } 2426 2427 /** 2428 * Request to delete the node at the given location. 2429 * <p> 2430 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2431 * called. 2432 * </p> 2433 * 2434 * @param at the location of the node that is to be deleted 2435 * @return an object that may be used to start another request 2436 */ 2437 public BatchConjunction delete( Location at ) { 2438 assertNotExecuted(); 2439 this.requestQueue.deleteBranch(at, getCurrentWorkspaceName()); 2440 return nextRequests; 2441 } 2442 2443 /** 2444 * Request to delete the node at the given path. 2445 * <p> 2446 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2447 * called. 2448 * </p> 2449 * 2450 * @param atPath the path of the node that is to be deleted 2451 * @return an object that may be used to start another request 2452 */ 2453 public BatchConjunction delete( String atPath ) { 2454 return delete(Location.create(createPath(atPath))); 2455 } 2456 2457 /** 2458 * Request to delete the node at the given path. 2459 * <p> 2460 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2461 * called. 2462 * </p> 2463 * 2464 * @param at the path of the node that is to be deleted 2465 * @return an object that may be used to start another request 2466 */ 2467 public BatchConjunction delete( Path at ) { 2468 return delete(Location.create(at)); 2469 } 2470 2471 /** 2472 * Request to delete the node with the given UUID. 2473 * <p> 2474 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2475 * called. 2476 * </p> 2477 * 2478 * @param at the UUID of the node that is to be deleted 2479 * @return an object that may be used to start another request 2480 */ 2481 public BatchConjunction delete( UUID at ) { 2482 return delete(Location.create(at)); 2483 } 2484 2485 /** 2486 * Request to delete the node with the given unique identification property. 2487 * <p> 2488 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2489 * called. 2490 * </p> 2491 * 2492 * @param idProperty the unique identifying property of the node that is to be deleted 2493 * @return an object that may be used to start another request 2494 */ 2495 public BatchConjunction delete( Property idProperty ) { 2496 return delete(Location.create(idProperty)); 2497 } 2498 2499 /** 2500 * Request to delete the node with the given identification properties. The identification properties should uniquely 2501 * identify a single node. 2502 * <p> 2503 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2504 * called. 2505 * </p> 2506 * 2507 * @param firstIdProperty the first identification property of the node that is to be copied 2508 * @param additionalIdProperties the remaining idenficiation properties of the node that is to be copied 2509 * @return an object that may be used to start another request 2510 */ 2511 public BatchConjunction delete( Property firstIdProperty, 2512 Property... additionalIdProperties ) { 2513 return delete(Location.create(firstIdProperty, additionalIdProperties)); 2514 } 2515 2516 /** 2517 * Request to delete the node with the given identification properties. The identification properties should uniquely 2518 * identify a single node. 2519 * <p> 2520 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2521 * called. 2522 * </p> 2523 * 2524 * @param idProperties the identification property of the node that is to be copied 2525 * @return an object that may be used to start another request 2526 */ 2527 public BatchConjunction delete( Iterable<Property> idProperties ) { 2528 return delete(Location.create(idProperties)); 2529 } 2530 2531 /** 2532 * Begin the request to create a node located at the supplied path. 2533 * <p> 2534 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2535 * called. 2536 * </p> 2537 * 2538 * @param atPath the path to the node that is to be created. 2539 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2540 * node where the node is to be created 2541 */ 2542 public Create<Batch> create( String atPath ) { 2543 return create(createPath(atPath)); 2544 } 2545 2546 /** 2547 * Begin the request to create a node located at the supplied path. 2548 * <p> 2549 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2550 * called. 2551 * </p> 2552 * 2553 * @param atPath the path to the node that is to be created. 2554 * @param property a property for the new node 2555 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2556 * node where the node is to be created 2557 */ 2558 public Create<Batch> create( String atPath, 2559 Property property ) { 2560 return create(createPath(atPath)).with(property); 2561 } 2562 2563 /** 2564 * Begin the request to create a node located at the supplied path. 2565 * <p> 2566 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2567 * called. 2568 * </p> 2569 * 2570 * @param atPath the path to the node that is to be created. 2571 * @param firstProperty a property for the new node 2572 * @param additionalProperties additional properties for the new node 2573 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2574 * node where the node is to be created 2575 */ 2576 public Create<Batch> create( String atPath, 2577 Property firstProperty, 2578 Property... additionalProperties ) { 2579 return create(createPath(atPath)).with(firstProperty, additionalProperties); 2580 } 2581 2582 /** 2583 * Begin the request to create a node located at the supplied path. 2584 * <p> 2585 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2586 * called. 2587 * </p> 2588 * 2589 * @param at the path to the node that is to be created. 2590 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2591 * node where the node is to be created 2592 */ 2593 public final Create<Batch> create( Path at ) { 2594 assertNotExecuted(); 2595 CheckArg.isNotNull(at, "at"); 2596 Path parent = at.getParent(); 2597 Name name = at.getLastSegment().getName(); 2598 return create(Location.create(parent), name); 2599 } 2600 2601 protected final CreateAction<Batch> create( Location parent, 2602 Name child ) { 2603 return new CreateAction<Batch>(this, parent, getCurrentWorkspaceName(), child) { 2604 @Override 2605 protected Batch submit( Location parent, 2606 String workspaceName, 2607 Name childName, 2608 Collection<Property> properties ) { 2609 requestQueue.createNode(parent, workspaceName, childName, properties.iterator()); 2610 return Batch.this; 2611 } 2612 2613 /** 2614 * {@inheritDoc} 2615 * 2616 * @see org.jboss.dna.graph.Graph.Executable#execute() 2617 */ 2618 public Results execute() { 2619 and(); 2620 return Batch.this.execute(); 2621 } 2622 }; 2623 } 2624 2625 /** 2626 * Begin the request to create a node located at the supplied path. 2627 * <p> 2628 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2629 * called. 2630 * </p> 2631 * 2632 * @param at the path to the node that is to be created. 2633 * @param properties the iterator over the properties for the new node 2634 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2635 * node where the node is to be created 2636 */ 2637 public Create<Batch> create( Path at, 2638 Iterable<Property> properties ) { 2639 Create<Batch> action = create(at); 2640 for (Property property : properties) { 2641 action.and(property); 2642 } 2643 return action; 2644 } 2645 2646 /** 2647 * Begin the request to create a node located at the supplied path. 2648 * <p> 2649 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2650 * called. 2651 * </p> 2652 * 2653 * @param at the path to the node that is to be created. 2654 * @param property a property for the new node 2655 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2656 * node where the node is to be created 2657 */ 2658 public Create<Batch> create( Path at, 2659 Property property ) { 2660 return create(at).with(property); 2661 } 2662 2663 /** 2664 * Begin the request to create a node located at the supplied path. 2665 * <p> 2666 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 2667 * called. 2668 * </p> 2669 * 2670 * @param at the path to the node that is to be created. 2671 * @param firstProperty a property for the new node 2672 * @param additionalProperties additional properties for the new node 2673 * @return the object that can be used to specify addition properties for the new node to be copied or the location of the 2674 * node where the node is to be created 2675 */ 2676 public Create<Batch> create( Path at, 2677 Property firstProperty, 2678 Property... additionalProperties ) { 2679 return create(at).with(firstProperty, additionalProperties); 2680 } 2681 2682 /** 2683 * Begin the request to create a node under the existing parent node at the supplied location. This request is submitted 2684 * to the repository after the returned components are completed. 2685 * 2686 * @param parent the location of the parent 2687 * @return the object used to start creating a node 2688 */ 2689 public CreateNodeNamed<Batch> createUnder( Location parent ) { 2690 CheckArg.isNotNull(parent, "parent"); 2691 return new CreateNodeNamedAction<Batch>(this, parent) { 2692 @Override 2693 protected CreateAction<Batch> createWith( Batch batch, 2694 Location parent, 2695 Name childName ) { 2696 return Batch.this.create(parent, childName); 2697 } 2698 }; 2699 } 2700 2701 /** 2702 * Set the properties on a node. 2703 * 2704 * @param properties the properties to set 2705 * @return the interface that should be used to specify the node on which the properties are to be set. 2706 */ 2707 public On<BatchConjunction> set( final Property... properties ) { 2708 return new On<BatchConjunction>() { 2709 public BatchConjunction on( Location location ) { 2710 requestQueue.setProperties(location, getCurrentWorkspaceName(), properties); 2711 return nextRequests; 2712 } 2713 2714 public BatchConjunction on( String path ) { 2715 return on(Location.create(createPath(path))); 2716 } 2717 2718 public BatchConjunction on( Path path ) { 2719 return on(Location.create(path)); 2720 } 2721 2722 public BatchConjunction on( Property idProperty ) { 2723 return on(Location.create(idProperty)); 2724 } 2725 2726 public BatchConjunction on( Property firstIdProperty, 2727 Property... additionalIdProperties ) { 2728 return on(Location.create(firstIdProperty, additionalIdProperties)); 2729 } 2730 2731 public BatchConjunction on( Iterable<Property> idProperties ) { 2732 return on(Location.create(idProperties)); 2733 } 2734 2735 public BatchConjunction on( UUID uuid ) { 2736 return on(Location.create(uuid)); 2737 } 2738 }; 2739 } 2740 2741 /** 2742 * Set a property on a node, starting with the name. The interface returned from this method should be used to specify the 2743 * value(s) and the location of the node onto which the property should be set. 2744 * 2745 * @param propertyName the property name 2746 * @return the interface used to specify the values 2747 */ 2748 public SetValues<BatchConjunction> set( String propertyName ) { 2749 Name name = getContext().getValueFactories().getNameFactory().create(propertyName); 2750 return set(name); 2751 } 2752 2753 /** 2754 * Set a property on a node, starting with the name. The interface returned from this method should be used to specify the 2755 * value(s) and the location of the node onto which the property should be set. 2756 * 2757 * @param propertyName the property name 2758 * @return the interface used to specify the values 2759 */ 2760 public SetValues<BatchConjunction> set( final Name propertyName ) { 2761 return new SetValues<BatchConjunction>() { 2762 public SetValuesTo<BatchConjunction> on( final Location location ) { 2763 return new SetValuesTo<BatchConjunction>() { 2764 public BatchConjunction to( Node value ) { 2765 return to(value.getLocation()); 2766 } 2767 2768 public BatchConjunction to( Location value ) { 2769 Reference ref = (Reference)convertReferenceValue(value); 2770 Property property = getContext().getPropertyFactory().create(propertyName, ref); 2771 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2772 return nextRequests; 2773 } 2774 2775 protected BatchConjunction toValue( Object value ) { 2776 Property property = getContext().getPropertyFactory().create(propertyName, value); 2777 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2778 return nextRequests; 2779 } 2780 2781 public BatchConjunction to( String value ) { 2782 return toValue(value); 2783 } 2784 2785 public BatchConjunction to( int value ) { 2786 return toValue(Integer.valueOf(value)); 2787 } 2788 2789 public BatchConjunction to( long value ) { 2790 return toValue(Long.valueOf(value)); 2791 } 2792 2793 public BatchConjunction to( boolean value ) { 2794 return toValue(Boolean.valueOf(value)); 2795 } 2796 2797 public BatchConjunction to( float value ) { 2798 return toValue(Float.valueOf(value)); 2799 } 2800 2801 public BatchConjunction to( double value ) { 2802 return toValue(Double.valueOf(value)); 2803 } 2804 2805 public BatchConjunction to( BigDecimal value ) { 2806 return toValue(value); 2807 } 2808 2809 public BatchConjunction to( Calendar value ) { 2810 return toValue(value); 2811 } 2812 2813 public BatchConjunction to( Date value ) { 2814 return toValue(value); 2815 } 2816 2817 public BatchConjunction to( DateTime value ) { 2818 return toValue(value); 2819 } 2820 2821 public BatchConjunction to( Name value ) { 2822 return toValue(value); 2823 } 2824 2825 public BatchConjunction to( Path value ) { 2826 return toValue(value); 2827 } 2828 2829 public BatchConjunction to( Reference value ) { 2830 return toValue(value); 2831 } 2832 2833 public BatchConjunction to( URI value ) { 2834 return toValue(value); 2835 } 2836 2837 public BatchConjunction to( UUID value ) { 2838 return toValue(value); 2839 } 2840 2841 public BatchConjunction to( Binary value ) { 2842 return toValue(value); 2843 } 2844 2845 public BatchConjunction to( byte[] value ) { 2846 return toValue(value); 2847 } 2848 2849 public BatchConjunction to( InputStream stream, 2850 long approximateLength ) { 2851 Binary value = getContext().getValueFactories().getBinaryFactory().create(stream, approximateLength); 2852 return toValue(value); 2853 } 2854 2855 public BatchConjunction to( Reader reader, 2856 long approximateLength ) { 2857 Binary value = getContext().getValueFactories().getBinaryFactory().create(reader, approximateLength); 2858 return toValue(value); 2859 } 2860 2861 public BatchConjunction to( Object value ) { 2862 value = convertReferenceValue(value); 2863 Property property = getContext().getPropertyFactory().create(propertyName, value); 2864 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2865 return nextRequests; 2866 } 2867 2868 public BatchConjunction to( Object firstValue, 2869 Object... otherValues ) { 2870 firstValue = convertReferenceValue(firstValue); 2871 for (int i = 0, len = otherValues.length; i != len; ++i) { 2872 otherValues[i] = convertReferenceValue(otherValues[i]); 2873 } 2874 Property property = getContext().getPropertyFactory().create(propertyName, firstValue, otherValues); 2875 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2876 return nextRequests; 2877 } 2878 2879 public BatchConjunction to( Iterable<?> values ) { 2880 List<Object> valueList = new LinkedList<Object>(); 2881 for (Object value : values) { 2882 value = convertReferenceValue(value); 2883 valueList.add(value); 2884 } 2885 Property property = getContext().getPropertyFactory().create(propertyName, valueList); 2886 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2887 return nextRequests; 2888 } 2889 2890 public BatchConjunction to( Iterator<?> values ) { 2891 List<Object> valueList = new LinkedList<Object>(); 2892 while (values.hasNext()) { 2893 Object value = values.next(); 2894 valueList.add(value); 2895 } 2896 Property property = getContext().getPropertyFactory().create(propertyName, valueList); 2897 requestQueue.setProperty(location, getCurrentWorkspaceName(), property); 2898 return nextRequests; 2899 } 2900 2901 }; 2902 } 2903 2904 public SetValuesTo<BatchConjunction> on( String path ) { 2905 return on(Location.create(createPath(path))); 2906 } 2907 2908 public SetValuesTo<BatchConjunction> on( Path path ) { 2909 return on(Location.create(path)); 2910 } 2911 2912 public SetValuesTo<BatchConjunction> on( Property idProperty ) { 2913 return on(Location.create(idProperty)); 2914 } 2915 2916 public SetValuesTo<BatchConjunction> on( Property firstIdProperty, 2917 Property... additionalIdProperties ) { 2918 return on(Location.create(firstIdProperty, additionalIdProperties)); 2919 } 2920 2921 public SetValuesTo<BatchConjunction> on( Iterable<Property> idProperties ) { 2922 return on(Location.create(idProperties)); 2923 } 2924 2925 public SetValuesTo<BatchConjunction> on( UUID uuid ) { 2926 return on(Location.create(uuid)); 2927 } 2928 2929 public On<BatchConjunction> to( Node value ) { 2930 Object reference = convertReferenceValue(value); 2931 return set(getContext().getPropertyFactory().create(propertyName, reference)); 2932 } 2933 2934 public On<BatchConjunction> to( Location value ) { 2935 Object reference = convertReferenceValue(value); 2936 return set(getContext().getPropertyFactory().create(propertyName, reference)); 2937 } 2938 2939 protected On<BatchConjunction> toValue( Object value ) { 2940 return set(getContext().getPropertyFactory().create(propertyName, value)); 2941 } 2942 2943 public On<BatchConjunction> to( String value ) { 2944 return toValue(value); 2945 } 2946 2947 public On<BatchConjunction> to( int value ) { 2948 return toValue(Integer.valueOf(value)); 2949 } 2950 2951 public On<BatchConjunction> to( long value ) { 2952 return toValue(Long.valueOf(value)); 2953 } 2954 2955 public On<BatchConjunction> to( boolean value ) { 2956 return toValue(Boolean.valueOf(value)); 2957 } 2958 2959 public On<BatchConjunction> to( float value ) { 2960 return toValue(Float.valueOf(value)); 2961 } 2962 2963 public On<BatchConjunction> to( double value ) { 2964 return toValue(Double.valueOf(value)); 2965 } 2966 2967 public On<BatchConjunction> to( BigDecimal value ) { 2968 return toValue(value); 2969 } 2970 2971 public On<BatchConjunction> to( Calendar value ) { 2972 return toValue(value); 2973 } 2974 2975 public On<BatchConjunction> to( Date value ) { 2976 return toValue(value); 2977 } 2978 2979 public On<BatchConjunction> to( DateTime value ) { 2980 return toValue(value); 2981 } 2982 2983 public On<BatchConjunction> to( Name value ) { 2984 return toValue(value); 2985 } 2986 2987 public On<BatchConjunction> to( Path value ) { 2988 return toValue(value); 2989 } 2990 2991 public On<BatchConjunction> to( Reference value ) { 2992 return toValue(value); 2993 } 2994 2995 public On<BatchConjunction> to( URI value ) { 2996 return toValue(value); 2997 } 2998 2999 public On<BatchConjunction> to( UUID value ) { 3000 return toValue(value); 3001 } 3002 3003 public On<BatchConjunction> to( Binary value ) { 3004 return toValue(value); 3005 } 3006 3007 public On<BatchConjunction> to( byte[] value ) { 3008 return toValue(value); 3009 } 3010 3011 public On<BatchConjunction> to( InputStream stream, 3012 long approximateLength ) { 3013 Binary value = getContext().getValueFactories().getBinaryFactory().create(stream, approximateLength); 3014 return toValue(value); 3015 } 3016 3017 public On<BatchConjunction> to( Reader reader, 3018 long approximateLength ) { 3019 Binary value = getContext().getValueFactories().getBinaryFactory().create(reader, approximateLength); 3020 return toValue(value); 3021 } 3022 3023 public On<BatchConjunction> to( Object value ) { 3024 value = convertReferenceValue(value); 3025 return set(getContext().getPropertyFactory().create(propertyName, value)); 3026 } 3027 3028 public On<BatchConjunction> to( Object firstValue, 3029 Object... otherValues ) { 3030 Object[] values = new Object[otherValues.length + 1]; 3031 values[0] = convertReferenceValue(firstValue); 3032 for (int i = 0, len = otherValues.length; i != len; ++i) { 3033 values[i + 1] = convertReferenceValue(otherValues[i]); 3034 } 3035 return set(getContext().getPropertyFactory().create(propertyName, values)); 3036 } 3037 3038 public On<BatchConjunction> to( Iterable<?> values ) { 3039 List<Object> valueList = new LinkedList<Object>(); 3040 for (Object value : values) { 3041 value = convertReferenceValue(value); 3042 valueList.add(value); 3043 } 3044 return set(getContext().getPropertyFactory().create(propertyName, valueList)); 3045 } 3046 3047 public On<BatchConjunction> to( Iterator<?> values ) { 3048 List<Object> valueList = new LinkedList<Object>(); 3049 while (values.hasNext()) { 3050 Object value = values.next(); 3051 valueList.add(value); 3052 } 3053 return set(getContext().getPropertyFactory().create(propertyName, valueList)); 3054 } 3055 }; 3056 } 3057 3058 /** 3059 * Remove properties from the node at the given location. 3060 * 3061 * @param propertyNames the names of the properties to be removed 3062 * @return the remove request object that should be used to specify the node from which the properties are to be removed. 3063 */ 3064 public On<BatchConjunction> remove( final Name... propertyNames ) { 3065 return new On<BatchConjunction>() { 3066 public BatchConjunction on( Location location ) { 3067 requestQueue.removeProperties(location, getCurrentWorkspaceName(), propertyNames); 3068 return nextRequests; 3069 } 3070 3071 public BatchConjunction on( String path ) { 3072 return on(Location.create(createPath(path))); 3073 } 3074 3075 public BatchConjunction on( Path path ) { 3076 return on(Location.create(path)); 3077 } 3078 3079 public BatchConjunction on( Property idProperty ) { 3080 return on(Location.create(idProperty)); 3081 } 3082 3083 public BatchConjunction on( Property firstIdProperty, 3084 Property... additionalIdProperties ) { 3085 return on(Location.create(firstIdProperty, additionalIdProperties)); 3086 } 3087 3088 public BatchConjunction on( Iterable<Property> idProperties ) { 3089 return on(Location.create(idProperties)); 3090 } 3091 3092 public BatchConjunction on( UUID uuid ) { 3093 return on(Location.create(uuid)); 3094 } 3095 }; 3096 } 3097 3098 /** 3099 * Remove properties from the node at the given location. 3100 * 3101 * @param propertyNames the names of the properties to be removed 3102 * @return the remove request object that should be used to specify the node from which the properties are to be removed. 3103 */ 3104 public On<BatchConjunction> remove( String... propertyNames ) { 3105 NameFactory nameFactory = getContext().getValueFactories().getNameFactory(); 3106 int number = propertyNames.length; 3107 final Name[] names = new Name[number]; 3108 for (int i = 0; i != number; ++i) { 3109 names[i] = nameFactory.create(propertyNames[i]); 3110 } 3111 return new On<BatchConjunction>() { 3112 public BatchConjunction on( Location location ) { 3113 requestQueue.removeProperties(location, getCurrentWorkspaceName(), names); 3114 return nextRequests; 3115 } 3116 3117 public BatchConjunction on( String path ) { 3118 return on(Location.create(createPath(path))); 3119 } 3120 3121 public BatchConjunction on( Path path ) { 3122 return on(Location.create(path)); 3123 } 3124 3125 public BatchConjunction on( Property idProperty ) { 3126 return on(Location.create(idProperty)); 3127 } 3128 3129 public BatchConjunction on( Property firstIdProperty, 3130 Property... additionalIdProperties ) { 3131 return on(Location.create(firstIdProperty, additionalIdProperties)); 3132 } 3133 3134 public BatchConjunction on( Iterable<Property> idProperties ) { 3135 return on(Location.create(idProperties)); 3136 } 3137 3138 public BatchConjunction on( UUID uuid ) { 3139 return on(Location.create(uuid)); 3140 } 3141 }; 3142 } 3143 3144 /** 3145 * Request to read the node with the supplied UUID. 3146 * <p> 3147 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3148 * called. 3149 * </p> 3150 * 3151 * @param uuid the UUID of the node that is to be read 3152 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3153 */ 3154 public BatchConjunction read( UUID uuid ) { 3155 return read(Location.create(uuid)); 3156 } 3157 3158 /** 3159 * Request to read the node at the supplied location. 3160 * <p> 3161 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3162 * called. 3163 * </p> 3164 * 3165 * @param location the location of the node that is to be read 3166 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3167 */ 3168 public BatchConjunction read( Location location ) { 3169 assertNotExecuted(); 3170 requestQueue.readNode(location, getCurrentWorkspaceName()); 3171 return nextRequests; 3172 } 3173 3174 /** 3175 * Request to read the node at the supplied path. 3176 * <p> 3177 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3178 * called. 3179 * </p> 3180 * 3181 * @param path the path of the node that is to be read 3182 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3183 */ 3184 public BatchConjunction read( String path ) { 3185 return read(Location.create(createPath(path))); 3186 } 3187 3188 /** 3189 * Request to read the node at the supplied path. 3190 * <p> 3191 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3192 * called. 3193 * </p> 3194 * 3195 * @param path the path of the node that is to be read 3196 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3197 */ 3198 public BatchConjunction read( Path path ) { 3199 return read(Location.create(path)); 3200 } 3201 3202 /** 3203 * Request to read the node with the supplied unique identifier property. 3204 * <p> 3205 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3206 * called. 3207 * </p> 3208 * 3209 * @param idProperty the identification property that is unique to the node that is to be read 3210 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3211 */ 3212 public BatchConjunction read( Property idProperty ) { 3213 return read(Location.create(idProperty)); 3214 } 3215 3216 /** 3217 * Request to read the node with the supplied unique identifier properties. 3218 * <p> 3219 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3220 * called. 3221 * </p> 3222 * 3223 * @param firstIdProperty the first of the identification properties that uniquely identify the node that is to be read 3224 * @param additionalIdProperties the remaining identification properties that uniquely identify the node that is to be 3225 * read 3226 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3227 */ 3228 public BatchConjunction read( Property firstIdProperty, 3229 Property... additionalIdProperties ) { 3230 return read(Location.create(firstIdProperty, additionalIdProperties)); 3231 } 3232 3233 /** 3234 * Request to read the node with the supplied unique identifier properties. 3235 * <p> 3236 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3237 * called. 3238 * </p> 3239 * 3240 * @param idProperties the identification properties that uniquely identify the node that is to be read 3241 * @return the interface that can either execute the batched requests or continue to add additional requests to the batch 3242 */ 3243 public BatchConjunction read( Iterable<Property> idProperties ) { 3244 return read(Location.create(idProperties)); 3245 } 3246 3247 /** 3248 * Request that the property with the given name be read on the node defined via the <code>on(...)</code> method on the 3249 * returned {@link On} object. 3250 * <p> 3251 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3252 * called. 3253 * </p> 3254 * 3255 * @param propertyName the name of the property that is to be read 3256 * @return the object that is used to specified the node whose property is to be read 3257 */ 3258 public On<BatchConjunction> readProperty( String propertyName ) { 3259 assertNotExecuted(); 3260 Name name = Graph.this.getContext().getValueFactories().getNameFactory().create(propertyName); 3261 return readProperty(name); 3262 } 3263 3264 /** 3265 * Request that the property with the given name be read on the node defined via the <code>on(...)</code> method on the 3266 * returned {@link On} object. 3267 * <p> 3268 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3269 * called. 3270 * </p> 3271 * 3272 * @param name the name of the property that is to be read 3273 * @return the object that is used to specified the node whose property is to be read 3274 */ 3275 public On<BatchConjunction> readProperty( final Name name ) { 3276 assertNotExecuted(); 3277 return new On<BatchConjunction>() { 3278 public BatchConjunction on( String path ) { 3279 return on(Location.create(createPath(path))); 3280 } 3281 3282 public BatchConjunction on( Path path ) { 3283 return on(Location.create(path)); 3284 } 3285 3286 public BatchConjunction on( Property idProperty ) { 3287 return on(Location.create(idProperty)); 3288 } 3289 3290 public BatchConjunction on( Property firstIdProperty, 3291 Property... additionalIdProperties ) { 3292 return on(Location.create(firstIdProperty, additionalIdProperties)); 3293 } 3294 3295 public BatchConjunction on( Iterable<Property> idProperties ) { 3296 return on(Location.create(idProperties)); 3297 } 3298 3299 public BatchConjunction on( UUID uuid ) { 3300 return on(Location.create(uuid)); 3301 } 3302 3303 public BatchConjunction on( Location at ) { 3304 requestQueue.readProperty(at, getCurrentWorkspaceName(), name); 3305 return Batch.this.nextRequests; 3306 } 3307 }; 3308 } 3309 3310 /** 3311 * Request that the properties be read on the node defined via the <code>on(...)</code> method on the returned {@link On} 3312 * object. 3313 * <p> 3314 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3315 * called. 3316 * </p> 3317 * 3318 * @return the object that is used to specified the node whose properties are to be read, 3319 */ 3320 public On<BatchConjunction> readProperties() { 3321 assertNotExecuted(); 3322 return new On<BatchConjunction>() { 3323 public BatchConjunction on( Location location ) { 3324 requestQueue.readAllProperties(location, getCurrentWorkspaceName()); 3325 return Batch.this.nextRequests; 3326 } 3327 3328 public BatchConjunction on( String path ) { 3329 return on(Location.create(createPath(path))); 3330 } 3331 3332 public BatchConjunction on( Path path ) { 3333 return on(Location.create(path)); 3334 } 3335 3336 public BatchConjunction on( Property idProperty ) { 3337 return on(Location.create(idProperty)); 3338 } 3339 3340 public BatchConjunction on( Property firstIdProperty, 3341 Property... additionalIdProperties ) { 3342 return on(Location.create(firstIdProperty, additionalIdProperties)); 3343 } 3344 3345 public BatchConjunction on( Iterable<Property> idProperties ) { 3346 return on(Location.create(idProperties)); 3347 } 3348 3349 public BatchConjunction on( UUID uuid ) { 3350 return on(Location.create(uuid)); 3351 } 3352 }; 3353 } 3354 3355 /** 3356 * Request that the children be read on the node defined via the <code>of(...)</code> method on the returned {@link Of} 3357 * object. 3358 * <p> 3359 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3360 * called. 3361 * </p> 3362 * 3363 * @return the object that is used to specified the node whose children are to be read 3364 */ 3365 public Of<BatchConjunction> readChildren() { 3366 assertNotExecuted(); 3367 return new Of<BatchConjunction>() { 3368 public BatchConjunction of( String path ) { 3369 return of(Location.create(createPath(path))); 3370 } 3371 3372 public BatchConjunction of( Path path ) { 3373 return of(Location.create(path)); 3374 } 3375 3376 public BatchConjunction of( Property idProperty ) { 3377 return of(Location.create(idProperty)); 3378 } 3379 3380 public BatchConjunction of( Property firstIdProperty, 3381 Property... additionalIdProperties ) { 3382 return of(Location.create(firstIdProperty, additionalIdProperties)); 3383 } 3384 3385 public BatchConjunction of( Iterable<Property> idProperties ) { 3386 return of(Location.create(idProperties)); 3387 } 3388 3389 public BatchConjunction of( UUID uuid ) { 3390 return of(Location.create(uuid)); 3391 } 3392 3393 public BatchConjunction of( Location at ) { 3394 requestQueue.readAllChildren(at, getCurrentWorkspaceName()); 3395 return Batch.this.nextRequests; 3396 } 3397 }; 3398 } 3399 3400 /** 3401 * Request to read a subgraph of the specified depth, rooted at a location that will be specified via <code>at(...)</code> 3402 * in the resulting {@link At} object. 3403 * <p> 3404 * Like all other methods on the {@link Batch}, the request will be performed when the {@link #execute()} method is 3405 * called. 3406 * </p> 3407 * 3408 * @param depth the maximum depth of the subgraph that should be read 3409 * @return the component that should be used to specify the location of the node that is the top of the subgraph 3410 */ 3411 public At<BatchConjunction> readSubgraphOfDepth( final int depth ) { 3412 assertNotExecuted(); 3413 return new At<BatchConjunction>() { 3414 public BatchConjunction at( Location location ) { 3415 requestQueue.readBranch(location, getCurrentWorkspaceName()); 3416 return Batch.this.nextRequests; 3417 } 3418 3419 public BatchConjunction at( String path ) { 3420 return at(Location.create(createPath(path))); 3421 } 3422 3423 public BatchConjunction at( Path path ) { 3424 return at(Location.create(path)); 3425 } 3426 3427 public BatchConjunction at( UUID uuid ) { 3428 return at(Location.create(uuid)); 3429 } 3430 3431 public BatchConjunction at( Property idProperty ) { 3432 return at(Location.create(idProperty)); 3433 } 3434 3435 public BatchConjunction at( Property firstIdProperty, 3436 Property... additionalIdProperties ) { 3437 return at(Location.create(firstIdProperty, additionalIdProperties)); 3438 } 3439 3440 public BatchConjunction at( Iterable<Property> idProperties ) { 3441 return at(Location.create(idProperties)); 3442 } 3443 }; 3444 } 3445 3446 /** 3447 * {@inheritDoc} 3448 * 3449 * @see org.jboss.dna.graph.Graph.Executable#execute() 3450 */ 3451 public Results execute() { 3452 executed = true; 3453 Request request = requestQueue.pop(); 3454 if (request == null) { 3455 return new BatchResults(); 3456 } 3457 Graph.this.execute(request); 3458 if (request instanceof CompositeRequest) { 3459 CompositeRequest composite = (CompositeRequest)request; 3460 return new BatchResults(composite.getRequests()); 3461 } 3462 return new BatchResults(request); 3463 } 3464 } 3465 3466 /** 3467 * Utility method for checking a property value. If the value is a {@link Node} or {@link Location}, a {@link Reference} value 3468 * is created (if the node/location has a UUID); otherwise, the value is returned as is. 3469 * 3470 * @param value the property value 3471 * @return the property value, which may be a {@link Reference} if the input value is a Node or Location 3472 */ 3473 protected Object convertReferenceValue( Object value ) { 3474 if (value instanceof Node) { 3475 Node node = (Node)value; 3476 UUID uuid = node.getLocation().getUuid(); 3477 if (uuid == null) { 3478 // Look for a property ... 3479 Property uuidProperty = node.getProperty(DnaLexicon.UUID); 3480 if (uuidProperty != null) { 3481 uuid = context.getValueFactories().getUuidFactory().create(uuidProperty.getFirstValue()); 3482 } else { 3483 uuidProperty = node.getProperty(JcrLexicon.UUID); 3484 if (uuidProperty != null) { 3485 uuid = context.getValueFactories().getUuidFactory().create(uuidProperty.getFirstValue()); 3486 } 3487 } 3488 } 3489 if (uuid == null) { 3490 String nodeString = node.getLocation().getString(getContext().getNamespaceRegistry()); 3491 String msg = GraphI18n.unableToCreateReferenceToNodeWithoutUuid.text(nodeString); 3492 throw new IllegalArgumentException(msg); 3493 } 3494 return getContext().getValueFactories().getReferenceFactory().create(uuid); 3495 } 3496 if (value instanceof Location) { 3497 Location location = (Location)value; 3498 UUID uuid = location.getUuid(); 3499 if (uuid == null) { 3500 String nodeString = location.getString(getContext().getNamespaceRegistry()); 3501 String msg = GraphI18n.unableToCreateReferenceToNodeWithoutUuid.text(nodeString); 3502 throw new IllegalArgumentException(msg); 3503 } 3504 return getContext().getValueFactories().getReferenceFactory().create(uuid); 3505 } 3506 return value; 3507 } 3508 3509 /** 3510 * The interface used to specify the name of a new workspace. 3511 */ 3512 public interface NameWorkspace { 3513 3514 /** 3515 * Specify the name of the new workspace that is to be created. 3516 * 3517 * @param workspaceName the name of the existing workspace that will be cloned to create the new workspace; 3518 * @return the workspace; never null 3519 * @throws IllegalArgumentException if the name of the new workspace is null 3520 * @throws InvalidWorkspaceException if there is already an existing workspace with the supplied name 3521 */ 3522 Workspace named( String workspaceName ); 3523 3524 /** 3525 * Specify the name of the new workspace that is to be created. If a workspace with the supplied name already exists, the 3526 * new workspace name will be adjusted so that it is unique. 3527 * 3528 * @param workspaceName the name of the existing workspace that will be cloned to create the new workspace; 3529 * @return the workspace; never null 3530 * @throws IllegalArgumentException if the name of the new workspace is null 3531 */ 3532 Workspace namedSomethingLike( String workspaceName ); 3533 } 3534 3535 /** 3536 * The interface used to create a new workspace. 3537 */ 3538 public interface CreateWorkspace extends NameWorkspace { 3539 /** 3540 * Specify that the new workspace should be initialized as a clone of another existing workspace. 3541 * 3542 * @param originalWorkspaceName the name of the existing workspace that will be cloned to create the new workspace; 3543 * @return the interface that should be used to set the name of the new workspace; never null 3544 * @throws IllegalArgumentException if the name of the original workspace is null 3545 * @throws InvalidWorkspaceException if there is no such workspace with the supplied name 3546 */ 3547 NameWorkspace clonedFrom( String originalWorkspaceName ); 3548 } 3549 3550 /** 3551 * A interface used to execute the accumulated {@link Batch requests}. 3552 * 3553 * @author Randall Hauch 3554 * @param <NodeType> the type of node that is returned 3555 */ 3556 public interface Executable<NodeType extends Node> { 3557 /** 3558 * Stop accumulating the requests, submit them to the repository source, and return the results. 3559 * 3560 * @return the results containing the requested information from the repository. 3561 * @throws PathNotFoundException if a request used a node that did not exist 3562 * @throws InvalidRequestException if a request was not valid 3563 * @throws InvalidWorkspaceException if the workspace used in a request was not valid 3564 * @throws UnsupportedRequestException if a request was not supported by the source 3565 * @throws RepositorySourceException if an error occurs during execution 3566 * @throws RuntimeException if a runtime error occurs during execution 3567 */ 3568 Results execute(); 3569 } 3570 3571 /** 3572 * A interface that can be used to finish the current request and start another. 3573 * 3574 * @param <Next> the interface that will be used to start another request 3575 * @author Randall Hauch 3576 */ 3577 public interface Conjunction<Next> { 3578 /** 3579 * Finish the request and prepare to start another. 3580 * 3581 * @return the interface that can be used to start another request; never null 3582 */ 3583 Next and(); 3584 } 3585 3586 /** 3587 * A component that defines the location into which a node should be copied or moved. 3588 * 3589 * @param <Next> The interface that is to be returned when this request is completed 3590 * @author Randall Hauch 3591 */ 3592 public interface Into<Next> { 3593 /** 3594 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3595 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3596 * same-name-sibling index). If you want to control the name of the node for the newly copied/moved node, use 3597 * {@link To#to(Location)} instead. 3598 * 3599 * @param parentLocation the location of the new parent 3600 * @return the interface for additional requests or actions 3601 * @see To#to(Location) 3602 */ 3603 Next into( Location parentLocation ); 3604 3605 /** 3606 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3607 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3608 * same-name-sibling index). If you want to control the name of the node for the newly copied/moved node, use 3609 * {@link To#to(String)} instead. 3610 * 3611 * @param parentPath the path of the new parent 3612 * @return the interface for additional requests or actions 3613 * @see To#to(String) 3614 */ 3615 Next into( String parentPath ); 3616 3617 /** 3618 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3619 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3620 * same-name-sibling index). If you want to control the name of the node for the newly copied/moved node, use 3621 * {@link To#to(Path)} instead. 3622 * 3623 * @param parentPath the path of the new parent 3624 * @return the interface for additional requests or actions 3625 * @see To#to(Path) 3626 */ 3627 Next into( Path parentPath ); 3628 3629 /** 3630 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3631 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3632 * same-name-sibling index). 3633 * 3634 * @param parentUuid the UUID of the new parent 3635 * @return the interface for additional requests or actions 3636 */ 3637 Next into( UUID parentUuid ); 3638 3639 /** 3640 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3641 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3642 * same-name-sibling index). 3643 * 3644 * @param parentIdProperty the property that uniquely identifies the new parent 3645 * @return the interface for additional requests or actions 3646 */ 3647 Next into( Property parentIdProperty ); 3648 3649 /** 3650 * Finish the request by specifying the location of the parent into which the node should be copied/moved. This operation 3651 * will result in the copied/moved node having the same name as the original (but with the appropriately-determined 3652 * same-name-sibling index). 3653 * 3654 * @param firstParentIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies 3655 * the new parent 3656 * @param additionalParentIdProperties the additional properties that, with the <code>additionalIdProperties</code>, 3657 * uniquely identifies the new parent 3658 * @return the interface for additional requests or actions 3659 */ 3660 Next into( Property firstParentIdProperty, 3661 Property... additionalParentIdProperties ); 3662 } 3663 3664 /** 3665 * A component that defines the location to which a node should be copied or moved. 3666 * 3667 * @param <Next> The interface that is to be returned when this request is completed 3668 * @author Randall Hauch 3669 */ 3670 public interface To<Next> { 3671 /** 3672 * Finish the request by specifying the Location.create where the node should be copied/moved. Unlike 3673 * {@link Into#into(Location)}, which specifies the location of the parent and which assumes the new node should have the 3674 * same name as the original, this method allows the caller to specify a new name for the new node. 3675 * 3676 * @param desiredLocation the desired location for the new node, which must have a {@link Location#getPath() path} 3677 * @return the interface for additional requests or actions 3678 * @see Into#into(Location) 3679 */ 3680 Next to( Location desiredLocation ); 3681 3682 /** 3683 * Finish the request by specifying the Location.create where the node should be copied/moved. Unlike 3684 * {@link Into#into(String)}, which specifies the location of the parent and which assumes the new node should have the 3685 * same name as the original, this method allows the caller to specify a new name for the new node. 3686 * 3687 * @param desiredPath the path for the new node 3688 * @return the interface for additional requests or actions 3689 * @see Into#into(String) 3690 */ 3691 Next to( String desiredPath ); 3692 3693 /** 3694 * Finish the request by specifying the Location.create where the node should be copied/moved. Unlike 3695 * {@link Into#into(Path)} , which specifies the location of the parent and which assumes the new node should have the 3696 * same name as the original, this method allows the caller to specify a new name for the new node. 3697 * 3698 * @param desiredPath the path for the new node 3699 * @return the interface for additional requests or actions 3700 * @see Into#into(Path) 3701 */ 3702 Next to( Path desiredPath ); 3703 } 3704 3705 /** 3706 * A component that defines a new name for a node. 3707 * 3708 * @param <Next> The interface that is to be returned when this request is completed 3709 * @author Randall Hauch 3710 */ 3711 public interface AsName<Next> { 3712 /** 3713 * Finish the request by specifying the new name. 3714 * 3715 * @param newName the new name 3716 * @return the interface for additional requests or actions 3717 */ 3718 Next as( String newName ); 3719 3720 /** 3721 * Finish the request by specifying the new name. 3722 * 3723 * @param newName the new name 3724 * @return the interface for additional requests or actions 3725 */ 3726 Next as( Name newName ); 3727 } 3728 3729 /** 3730 * A interface that is used to add more locations that are to be copied/moved. 3731 * 3732 * @param <Next> The interface that is to be returned when this request is completed 3733 * @author Randall Hauch 3734 */ 3735 public interface And<Next> { 3736 /** 3737 * Specify that another node should also be copied or moved. 3738 * 3739 * @param from the location of the node to be copied or moved 3740 * @return the interface for finishing the request 3741 */ 3742 Next and( Location from ); 3743 3744 /** 3745 * Specify that another node should also be copied or moved. 3746 * 3747 * @param fromPath the path of the node to be copied or moved 3748 * @return the interface for finishing the request 3749 */ 3750 Next and( String fromPath ); 3751 3752 /** 3753 * Specify that another node should also be copied or moved. 3754 * 3755 * @param from the path of the node to be copied or moved 3756 * @return the interface for finishing the request 3757 */ 3758 Next and( Path from ); 3759 3760 /** 3761 * Specify that another node should also be copied or moved. 3762 * 3763 * @param from the UUID of the node to be copied or moved 3764 * @return the interface for finishing the request 3765 */ 3766 Next and( UUID from ); 3767 3768 /** 3769 * Specify that another node should also be copied or moved. 3770 * 3771 * @param idProperty the property that uniquely identifies the node to be copied or moved 3772 * @return the interface for finishing the request 3773 */ 3774 Next and( Property idProperty ); 3775 3776 /** 3777 * Specify that another node should also be copied or moved. 3778 * 3779 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 3780 * node to be copied or moved 3781 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 3782 * identifies the node to be copied or moved 3783 * @return the interface for finishing the request 3784 */ 3785 Next and( Property firstIdProperty, 3786 Property... additionalIdProperties ); 3787 3788 /** 3789 * Specify that another node should also be copied or moved. 3790 * 3791 * @param idProperties the properties that uniquely identifies the node to be copied or moved 3792 * @return the interface for finishing the request 3793 */ 3794 Next and( Iterable<Property> idProperties ); 3795 } 3796 3797 /** 3798 * The interface for defining additional nodes to be moved and the parent into which the node(s) are to be moved. 3799 * 3800 * @param <Next> The interface that is to be returned when this request is completed 3801 * @author Randall Hauch 3802 */ 3803 public interface Move<Next> extends AsName<Into<Next>>, Into<Next>, And<Move<Next>> { 3804 } 3805 3806 /** 3807 * The interface for defining additional nodes to be copied and the locations where the copy is to be placed. The 3808 * <code>to(...)</code> methods allow you to specify the location of the copy, including the name for the node that results 3809 * from the copy. Alternatively, you can use the <code>into(...)</code> methods to specify the parent location where the copy 3810 * is to be placed, which will assume the new copy will have the same name as the original. 3811 * 3812 * @param <Next> The interface that is to be returned when this request is completed 3813 * @author Randall Hauch 3814 */ 3815 public interface Copy<Next> extends To<Next>, Into<Next>, And<Copy<Next>> { 3816 } 3817 3818 /** 3819 * The interface for defining additional properties on a new node. 3820 * 3821 * @param <Next> The interface that is to be returned when this create request is completed 3822 * @author Randall Hauch 3823 */ 3824 public interface Create<Next> extends Conjunction<Next>, Executable<Node> { 3825 /** 3826 * Specify the UUID that should the new node should have. This is an alias for {@link #and(UUID)}. 3827 * 3828 * @param uuid the UUID 3829 * @return this same interface so additional properties may be added 3830 */ 3831 Create<Next> with( UUID uuid ); 3832 3833 /** 3834 * Specify a property that should the new node should have. This is an alias for {@link #and(Property)}. 3835 * 3836 * @param property the property 3837 * @return this same interface so additional properties may be added 3838 */ 3839 Create<Next> with( Property property ); 3840 3841 /** 3842 * Specify property that should the new node should have. This is an alias for {@link #and(Iterable)}. 3843 * 3844 * @param properties the properties that should be added 3845 * @return this same interface so additional properties may be added 3846 */ 3847 Create<Next> with( Iterable<Property> properties ); 3848 3849 /** 3850 * Specify a property that should the new node should have. This is an alias for {@link #and(String, Object...)}. 3851 * 3852 * @param propertyName the name of the property 3853 * @param values the property values 3854 * @return this same interface so additional properties may be added 3855 */ 3856 Create<Next> with( String propertyName, 3857 Object... values ); 3858 3859 /** 3860 * Specify a property that should the new node should have. This is an alias for {@link #and(Name, Object...)}. 3861 * 3862 * @param propertyName the name of the property 3863 * @param values the property values 3864 * @return this same interface so additional properties may be added 3865 */ 3866 Create<Next> with( Name propertyName, 3867 Object... values ); 3868 3869 /** 3870 * Specify properties that should the new node should have. This is an alias for {@link #and(Property, Property...)}. 3871 * 3872 * @param firstProperty the first property 3873 * @param additionalProperties the additional property 3874 * @return this same interface so additional properties may be added 3875 */ 3876 Create<Next> with( Property firstProperty, 3877 Property... additionalProperties ); 3878 3879 /** 3880 * Specify the UUID that should the new node should have. 3881 * 3882 * @param uuid the UUID 3883 * @return this same interface so additional properties may be added 3884 */ 3885 Create<Next> and( UUID uuid ); 3886 3887 /** 3888 * Specify a property that should the new node should have. 3889 * 3890 * @param property the property 3891 * @return this same interface so additional properties may be added 3892 */ 3893 Create<Next> and( Property property ); 3894 3895 /** 3896 * Specify property that should the new node should have. This is equivalent to calling {@link #and(Property)} for each of 3897 * the properties in the supplied {@link Iterable}. 3898 * 3899 * @param properties the properties that should be added 3900 * @return this same interface so additional properties may be added 3901 */ 3902 Create<Next> and( Iterable<Property> properties ); 3903 3904 /** 3905 * Specify a property that should the new node should have. 3906 * 3907 * @param propertyName the name of the property 3908 * @param values the property values 3909 * @return this same interface so additional properties may be added 3910 */ 3911 Create<Next> and( String propertyName, 3912 Object... values ); 3913 3914 /** 3915 * Specify a property that should the new node should have. 3916 * 3917 * @param propertyName the name of the property 3918 * @param values the property values 3919 * @return this same interface so additional properties may be added 3920 */ 3921 Create<Next> and( Name propertyName, 3922 Object... values ); 3923 3924 /** 3925 * Specify properties that should the new node should have. 3926 * 3927 * @param firstProperty the first property 3928 * @param additionalProperties the additional property 3929 * @return this same interface so additional properties may be added 3930 */ 3931 Create<Next> and( Property firstProperty, 3932 Property... additionalProperties ); 3933 } 3934 3935 /** 3936 * The interface for defining additional properties on a new node. 3937 * 3938 * @param <Next> The interface that is to be returned when this create request is completed 3939 * @author Randall Hauch 3940 */ 3941 public interface CreateAt<Next> extends Conjunction<Next> { 3942 /** 3943 * Specify the UUID that should the new node should have. This is an alias for {@link #and(UUID)}. 3944 * 3945 * @param uuid the UUID 3946 * @return this same interface so additional properties may be added 3947 */ 3948 CreateAt<Next> with( UUID uuid ); 3949 3950 /** 3951 * Specify a property that should the new node should have. This is an alias for {@link #and(Property)}. 3952 * 3953 * @param property the property 3954 * @return this same interface so additional properties may be added 3955 */ 3956 CreateAt<Next> with( Property property ); 3957 3958 /** 3959 * Specify property that should the new node should have. This is an alias for {@link #and(Iterable)}. 3960 * 3961 * @param properties the properties that should be added 3962 * @return this same interface so additional properties may be added 3963 */ 3964 CreateAt<Next> with( Iterable<Property> properties ); 3965 3966 /** 3967 * Specify a property that should the new node should have. This is an alias for {@link #and(String, Object...)}. 3968 * 3969 * @param propertyName the name of the property 3970 * @param values the property values 3971 * @return this same interface so additional properties may be added 3972 */ 3973 CreateAt<Next> with( String propertyName, 3974 Object... values ); 3975 3976 /** 3977 * Specify a property that should the new node should have. This is an alias for {@link #and(Name, Object...)}. 3978 * 3979 * @param propertyName the name of the property 3980 * @param values the property values 3981 * @return this same interface so additional properties may be added 3982 */ 3983 CreateAt<Next> with( Name propertyName, 3984 Object... values ); 3985 3986 /** 3987 * Specify properties that should the new node should have. This is an alias for {@link #and(Property, Property...)}. 3988 * 3989 * @param firstProperty the first property 3990 * @param additionalProperties the additional property 3991 * @return this same interface so additional properties may be added 3992 */ 3993 CreateAt<Next> with( Property firstProperty, 3994 Property... additionalProperties ); 3995 3996 /** 3997 * Specify the UUID that should the new node should have. 3998 * 3999 * @param uuid the UUID 4000 * @return this same interface so additional properties may be added 4001 */ 4002 CreateAt<Next> and( UUID uuid ); 4003 4004 /** 4005 * Specify a property that should the new node should have. 4006 * 4007 * @param property the property 4008 * @return this same interface so additional properties may be added 4009 */ 4010 CreateAt<Next> and( Property property ); 4011 4012 /** 4013 * Specify property that should the new node should have. This is equivalent to calling {@link #and(Property)} for each of 4014 * the properties in the supplied {@link Iterable}. 4015 * 4016 * @param properties the properties that should be added 4017 * @return this same interface so additional properties may be added 4018 */ 4019 CreateAt<Next> and( Iterable<Property> properties ); 4020 4021 /** 4022 * Specify a property that should the new node should have. 4023 * 4024 * @param propertyName the name of the property 4025 * @param values the property values 4026 * @return this same interface so additional properties may be added 4027 */ 4028 CreateAt<Next> and( String propertyName, 4029 Object... values ); 4030 4031 /** 4032 * Specify a property that should the new node should have. 4033 * 4034 * @param propertyName the name of the property 4035 * @param values the property values 4036 * @return this same interface so additional properties may be added 4037 */ 4038 CreateAt<Next> and( Name propertyName, 4039 Object... values ); 4040 4041 /** 4042 * Specify properties that should the new node should have. 4043 * 4044 * @param firstProperty the first property 4045 * @param additionalProperties the additional property 4046 * @return this same interface so additional properties may be added 4047 */ 4048 CreateAt<Next> and( Property firstProperty, 4049 Property... additionalProperties ); 4050 4051 /** 4052 * Complete this request, submit it, and return the actual location of the created node. 4053 * 4054 * @return the actual location of the just-created node; never null 4055 */ 4056 Location getLocation(); 4057 4058 /** 4059 * Complete this request, submit it, and return the actual node that was created. 4060 * 4061 * @return the actual node that was just created; never null 4062 */ 4063 Node getNode(); 4064 } 4065 4066 /** 4067 * The interface for defining the node upon which a request operates. 4068 * 4069 * @param <Next> The interface that is to be returned when the request is completed 4070 * @author Randall Hauch 4071 */ 4072 public interface On<Next> { 4073 /** 4074 * Specify the location of the node upon which the request is to operate. 4075 * 4076 * @param to the location of the new parent 4077 * @return the interface for additional requests or actions 4078 */ 4079 Next on( Location to ); 4080 4081 /** 4082 * Specify the path of the node upon which the request is to operate. 4083 * 4084 * @param toPath the path of the new parent 4085 * @return the interface for additional requests or actions 4086 */ 4087 Next on( String toPath ); 4088 4089 /** 4090 * Specify the path of the node upon which the request is to operate. 4091 * 4092 * @param to the path of the new parent 4093 * @return the interface for additional requests or actions 4094 */ 4095 Next on( Path to ); 4096 4097 /** 4098 * Specify the UUID of the node upon which the request is to operate. 4099 * 4100 * @param to the UUID of the new parent 4101 * @return the interface for additional requests or actions 4102 */ 4103 Next on( UUID to ); 4104 4105 /** 4106 * Specify the unique identification property that identifies the node upon which the request is to operate. 4107 * 4108 * @param idProperty the property that uniquely identifies the new parent 4109 * @return the interface for additional requests or actions 4110 */ 4111 Next on( Property idProperty ); 4112 4113 /** 4114 * Specify the unique identification properties that identify the node upon which the request is to operate. 4115 * 4116 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 4117 * new parent 4118 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 4119 * identifies the new parent 4120 * @return the interface for additional requests or actions 4121 */ 4122 Next on( Property firstIdProperty, 4123 Property... additionalIdProperties ); 4124 4125 /** 4126 * Specify the unique identification properties that identify the node upon which the request is to operate. 4127 * 4128 * @param idProperties the properties that uniquely identifies the new parent 4129 * @return the interface for additional requests or actions 4130 */ 4131 Next on( Iterable<Property> idProperties ); 4132 } 4133 4134 /** 4135 * The interface for defining the node upon which a request operates. 4136 * 4137 * @param <Next> The interface that is to be returned when the request is completed 4138 * @author Randall Hauch 4139 */ 4140 public interface Of<Next> { 4141 /** 4142 * Specify the location of the node upon which the request is to operate. 4143 * 4144 * @param to the location of the new parent 4145 * @return the interface for additional requests or actions 4146 */ 4147 Next of( Location to ); 4148 4149 /** 4150 * Specify the path of the node upon which the request is to operate. 4151 * 4152 * @param toPath the path of the new parent 4153 * @return the interface for additional requests or actions 4154 */ 4155 Next of( String toPath ); 4156 4157 /** 4158 * Specify the path of the node upon which the request is to operate. 4159 * 4160 * @param to the path of the new parent 4161 * @return the interface for additional requests or actions 4162 */ 4163 Next of( Path to ); 4164 4165 /** 4166 * Specify the UUID of the node upon which the request is to operate. 4167 * 4168 * @param to the UUID of the new parent 4169 * @return the interface for additional requests or actions 4170 */ 4171 Next of( UUID to ); 4172 4173 /** 4174 * Specify the unique identification property that identifies the node upon which the request is to operate. 4175 * 4176 * @param idProperty the property that uniquely identifies the new parent 4177 * @return the interface for additional requests or actions 4178 */ 4179 Next of( Property idProperty ); 4180 4181 /** 4182 * Specify the unique identification properties that identify the node upon which the request is to operate. 4183 * 4184 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 4185 * new parent 4186 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 4187 * identifies the new parent 4188 * @return the interface for additional requests or actions 4189 */ 4190 Next of( Property firstIdProperty, 4191 Property... additionalIdProperties ); 4192 4193 /** 4194 * Specify the unique identification properties that identify the node upon which the request is to operate. 4195 * 4196 * @param idProperties the properties that uniquely identifies the new parent 4197 * @return the interface for additional requests or actions 4198 */ 4199 Next of( Iterable<Property> idProperties ); 4200 } 4201 4202 /** 4203 * The interface for defining the node upon which which a request operates. 4204 * 4205 * @param <Next> The interface that is to be returned when the request is completed 4206 * @author Randall Hauch 4207 */ 4208 public interface At<Next> { 4209 /** 4210 * Specify the location of the node upon which the request is to operate. 4211 * 4212 * @param to the location of the new parent 4213 * @return the interface for additional requests or actions 4214 */ 4215 Next at( Location to ); 4216 4217 /** 4218 * Specify the path of the node upon which the request is to operate. 4219 * 4220 * @param toPath the path of the new parent 4221 * @return the interface for additional requests or actions 4222 */ 4223 Next at( String toPath ); 4224 4225 /** 4226 * Specify the path of the node upon which the request is to operate. 4227 * 4228 * @param to the path of the new parent 4229 * @return the interface for additional requests or actions 4230 */ 4231 Next at( Path to ); 4232 4233 /** 4234 * Specify the UUID of the node upon which the request is to operate. 4235 * 4236 * @param to the UUID of the new parent 4237 * @return the interface for additional requests or actions 4238 */ 4239 Next at( UUID to ); 4240 4241 /** 4242 * Specify the unique identification property that identifies the node upon which the request is to operate. 4243 * 4244 * @param idProperty the property that uniquely identifies the new parent 4245 * @return the interface for additional requests or actions 4246 */ 4247 Next at( Property idProperty ); 4248 4249 /** 4250 * Specify the unique identification properties that identify the node upon which the request is to operate. 4251 * 4252 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 4253 * new parent 4254 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 4255 * identifies the new parent 4256 * @return the interface for additional requests or actions 4257 */ 4258 Next at( Property firstIdProperty, 4259 Property... additionalIdProperties ); 4260 4261 /** 4262 * Specify the unique identification properties that identify the node upon which the request is to operate. 4263 * 4264 * @param idProperties the properties that uniquely identifies the new parent 4265 * @return the interface for additional requests or actions 4266 */ 4267 Next at( Iterable<Property> idProperties ); 4268 } 4269 4270 /** 4271 * A component used to supply the details for getting children of another node. If all of the children are to be obtained, 4272 * then the parent can be specified using one of the <code>of(...)</code> methods on this component. If, however, only some of 4273 * the nodes are to be returned (e.g., a "block" of children), then specify the {@link #inBlockOf(int) block size} followed by 4274 * the {@link BlockOfChildren block size and parent}. 4275 * 4276 * @param <Next> 4277 * @author Randall Hauch 4278 */ 4279 public interface Children<Next> extends Of<Next> { 4280 /** 4281 * Specify that a block of children are to be retreived, and in particular the number of children that are to be returned. 4282 * 4283 * @param blockSize the number of children that are to be retrieved in the block; must be positive 4284 * @return the interface used to specify the starting point for the block and the parent 4285 */ 4286 BlockOfChildren<Next> inBlockOf( int blockSize ); 4287 } 4288 4289 /** 4290 * A component used to specify a block of children starting either {@link #startingAt(int) at a particular index} or 4291 * {@link #startingAfter(Location) after a previous sibling}. 4292 * 4293 * @param <Next> 4294 * @author Randall Hauch 4295 */ 4296 public interface BlockOfChildren<Next> { 4297 /** 4298 * Specify the block of children is to start at the supplied index. 4299 * 4300 * @param startingIndex the zero-based index of the first child to be returned in the block 4301 * @return interface used to specify the parent of the children; never null 4302 */ 4303 Under<Next> startingAt( int startingIndex ); 4304 4305 /** 4306 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4307 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4308 * block. 4309 * 4310 * @param previousSibling the location of the sibling node that is before the first node in the block 4311 * @return the children; never null 4312 */ 4313 Next startingAfter( Location previousSibling ); 4314 4315 /** 4316 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4317 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4318 * block. 4319 * 4320 * @param pathToPreviousSiblingName the path of the sibling node that is before the first node in the block 4321 * @return the children; never null 4322 */ 4323 Next startingAfter( String pathToPreviousSiblingName ); 4324 4325 /** 4326 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4327 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4328 * block. 4329 * 4330 * @param previousSibling the path of the sibling node that is before the first node in the block 4331 * @return the children; never null 4332 */ 4333 Next startingAfter( Path previousSibling ); 4334 4335 /** 4336 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4337 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4338 * block. 4339 * 4340 * @param previousSiblingUuid the UUID of the sibling node that is before the first node in the block 4341 * @return the children; never null 4342 */ 4343 Next startingAfter( UUID previousSiblingUuid ); 4344 4345 /** 4346 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4347 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4348 * block. 4349 * 4350 * @param idPropertyOfPreviousSibling the property that uniquely identifies the previous sibling 4351 * @return the children; never null 4352 */ 4353 Next startingAfter( Property idPropertyOfPreviousSibling ); 4354 4355 /** 4356 * Specify the block of children is to start with the child immediately following the supplied node. This method is 4357 * typically used when a previous block of children has already been retrieved and this request is retrieving the next 4358 * block. 4359 * 4360 * @param firstIdPropertyOfPreviousSibling the first property that, with the <code>additionalIdProperties</code>, uniquely 4361 * identifies the previous sibling 4362 * @param additionalIdPropertiesOfPreviousSibling the additional properties that, with the 4363 * <code>additionalIdProperties</code>, uniquely identifies the previous sibling 4364 * @return the children; never null 4365 */ 4366 Next startingAfter( Property firstIdPropertyOfPreviousSibling, 4367 Property... additionalIdPropertiesOfPreviousSibling ); 4368 } 4369 4370 /** 4371 * The interface for defining the node under which which a request operates. 4372 * 4373 * @param <Next> The interface that is to be returned when the request is completed 4374 * @author Randall Hauch 4375 */ 4376 public interface Under<Next> { 4377 /** 4378 * Specify the location of the node under which the request is to operate. 4379 * 4380 * @param to the location of the new parent 4381 * @return the interface for additional requests or actions 4382 */ 4383 Next under( Location to ); 4384 4385 /** 4386 * Specify the path of the node under which the request is to operate. 4387 * 4388 * @param toPath the path of the new parent 4389 * @return the interface for additional requests or actions 4390 */ 4391 Next under( String toPath ); 4392 4393 /** 4394 * Specify the path of the node under which the request is to operate. 4395 * 4396 * @param to the path of the new parent 4397 * @return the interface for additional requests or actions 4398 */ 4399 Next under( Path to ); 4400 4401 /** 4402 * Specify the UUID of the node under which the request is to operate. 4403 * 4404 * @param to the UUID of the new parent 4405 * @return the interface for additional requests or actions 4406 */ 4407 Next under( UUID to ); 4408 4409 /** 4410 * Specify the unique identification property that identifies the node under which the request is to operate. 4411 * 4412 * @param idProperty the property that uniquely identifies the new parent 4413 * @return the interface for additional requests or actions 4414 */ 4415 Next under( Property idProperty ); 4416 4417 /** 4418 * Specify the unique identification properties that identify the node under which the request is to operate. 4419 * 4420 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 4421 * new parent 4422 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 4423 * identifies the new parent 4424 * @return the interface for additional requests or actions 4425 */ 4426 Next under( Property firstIdProperty, 4427 Property... additionalIdProperties ); 4428 } 4429 4430 /** 4431 * A component used to set the values on a property. 4432 * 4433 * @param <Next> the next command 4434 * @author Randall Hauch 4435 */ 4436 public interface SetValues<Next> extends On<SetValuesTo<Next>>, SetValuesTo<On<Next>> { 4437 } 4438 4439 /** 4440 * A component used to set the values on a property. 4441 * 4442 * @param <Next> 4443 * @author Randall Hauch 4444 */ 4445 public interface SetValuesTo<Next> { 4446 4447 /** 4448 * Set the property value to be a reference to the given node. Note that it is an error if the Node does not have a 4449 * {@link Location#getUuid() UUID}. 4450 * 4451 * @param node the node to which a reference should be set 4452 * @return the interface for additional requests or actions 4453 * @throws IllegalArgumentException if the value is a Node that has no {@link Location#getUuid() UUID} 4454 */ 4455 Next to( Node node ); 4456 4457 /** 4458 * Set the property value to be a reference to the given location. Note that it is an error if the Location does not have 4459 * a {@link Location#getUuid() UUID}. 4460 * 4461 * @param location the location to which a reference should be set 4462 * @return the interface for additional requests or actions 4463 * @throws IllegalArgumentException if the value is a Location that has no {@link Location#getUuid() UUID} 4464 */ 4465 Next to( Location location ); 4466 4467 /** 4468 * Set the property value to the given string. 4469 * 4470 * @param value the property value 4471 * @return the interface for additional requests or actions 4472 */ 4473 Next to( String value ); 4474 4475 /** 4476 * Set the property value to the given integer value. 4477 * 4478 * @param value the property value 4479 * @return the interface for additional requests or actions 4480 */ 4481 Next to( int value ); 4482 4483 /** 4484 * Set the property value to the given long value. 4485 * 4486 * @param value the property value 4487 * @return the interface for additional requests or actions 4488 */ 4489 Next to( long value ); 4490 4491 /** 4492 * Set the property value to the given boolean value. 4493 * 4494 * @param value the property value 4495 * @return the interface for additional requests or actions 4496 */ 4497 Next to( boolean value ); 4498 4499 /** 4500 * Set the property value to the given float value. 4501 * 4502 * @param value the property value 4503 * @return the interface for additional requests or actions 4504 */ 4505 Next to( float value ); 4506 4507 /** 4508 * Set the property value to the given double value. 4509 * 4510 * @param value the property value 4511 * @return the interface for additional requests or actions 4512 */ 4513 Next to( double value ); 4514 4515 /** 4516 * Set the property value to the given decimal value. 4517 * 4518 * @param value the property value 4519 * @return the interface for additional requests or actions 4520 */ 4521 Next to( BigDecimal value ); 4522 4523 /** 4524 * Set the property value to the date given by the supplied calendar. 4525 * 4526 * @param value the property value 4527 * @return the interface for additional requests or actions 4528 */ 4529 Next to( Calendar value ); 4530 4531 /** 4532 * Set the property value to the given date. 4533 * 4534 * @param value the property value 4535 * @return the interface for additional requests or actions 4536 */ 4537 Next to( Date value ); 4538 4539 /** 4540 * Set the property value to the given date-time instant. 4541 * 4542 * @param value the property value 4543 * @return the interface for additional requests or actions 4544 */ 4545 Next to( DateTime value ); 4546 4547 /** 4548 * Set the property value to the given Name. 4549 * 4550 * @param value the property value 4551 * @return the interface for additional requests or actions 4552 */ 4553 Next to( Name value ); 4554 4555 /** 4556 * Set the property value to the given Path. 4557 * 4558 * @param value the property value 4559 * @return the interface for additional requests or actions 4560 */ 4561 Next to( Path value ); 4562 4563 /** 4564 * Set the property value to the given Reference. See also {@link #to(Node)}. 4565 * 4566 * @param value the property value 4567 * @return the interface for additional requests or actions 4568 */ 4569 Next to( Reference value ); 4570 4571 /** 4572 * Set the property value to the given URI. 4573 * 4574 * @param value the property value 4575 * @return the interface for additional requests or actions 4576 */ 4577 Next to( URI value ); 4578 4579 /** 4580 * Set the property value to the given UUID. 4581 * 4582 * @param value the property value 4583 * @return the interface for additional requests or actions 4584 */ 4585 Next to( UUID value ); 4586 4587 /** 4588 * Set the property value to the given binary value. 4589 * 4590 * @param value the property value 4591 * @return the interface for additional requests or actions 4592 */ 4593 Next to( Binary value ); 4594 4595 /** 4596 * Set the property value to the given byte array. 4597 * 4598 * @param value the property value 4599 * @return the interface for additional requests or actions 4600 */ 4601 Next to( byte[] value ); 4602 4603 /** 4604 * Set the property value to the given string. 4605 * 4606 * @param stream the stream containing the content to be used for the property value 4607 * @param approximateLength the approximate length of the content (in bytes) 4608 * @return the interface for additional requests or actions 4609 */ 4610 Next to( InputStream stream, 4611 long approximateLength ); 4612 4613 /** 4614 * Set the property value to the given string. 4615 * 4616 * @param reader the reader containing the content to be used for the property value 4617 * @param approximateLength the approximate length of the content (in bytes) 4618 * @return the interface for additional requests or actions 4619 */ 4620 Next to( Reader reader, 4621 long approximateLength ); 4622 4623 /** 4624 * Set the property value to the given object. The supplied <code>value</code> should be a valid property value, or a 4625 * {@link Node} (or {@link Location}) if the property value is to be a reference to that node (or location). Note that it 4626 * is an error if the Node (or Location) does not have a {@link Location#getUuid() UUID}. 4627 * 4628 * @param value the property value 4629 * @return the interface for additional requests or actions 4630 * @throws IllegalArgumentException if the value is a Node or Location that has no {@link Location#getUuid() UUID} 4631 */ 4632 Next to( Object value ); 4633 4634 /** 4635 * Set the property value to the given objects. Each of the supplied values should be a valid property value, or a 4636 * {@link Node} (or {@link Location}) if the property value is to be a reference to that node (or location). Note that it 4637 * is an error if the Node (or Location) does not have a {@link Location#getUuid() UUID}. 4638 * 4639 * @param firstValue the first property value 4640 * @param otherValues the remaining property values 4641 * @return the interface for additional requests or actions 4642 * @throws IllegalArgumentException if the any of the values is a Node or Location that has no {@link Location#getUuid() 4643 * UUID} 4644 */ 4645 Next to( Object firstValue, 4646 Object... otherValues ); 4647 4648 /** 4649 * Set the property value to the given object. Each of the supplied values should be a valid property value, or a 4650 * {@link Node} (or {@link Location}) if the property value is to be a reference to that node (or location). Note that it 4651 * is an error if the Node (or Location) does not have a {@link Location#getUuid() UUID}. 4652 * 4653 * @param values the container for the property values 4654 * @return the interface for additional requests or actions 4655 * @throws IllegalArgumentException if the any of the values is a Node or Location that has no {@link Location#getUuid() 4656 * UUID} 4657 */ 4658 Next to( Iterable<?> values ); 4659 4660 /** 4661 * Set the property value to the given object. Each of the supplied values should be a valid property value, or a 4662 * {@link Node} (or {@link Location}) if the property value is to be a reference to that node (or location). Note that it 4663 * is an error if the Node (or Location) does not have a {@link Location#getUuid() UUID}. 4664 * 4665 * @param values the iterator over the property values 4666 * @return the interface for additional requests or actions 4667 * @throws IllegalArgumentException if the any of the values is a Node or Location that has no {@link Location#getUuid() 4668 * UUID} 4669 */ 4670 Next to( Iterator<?> values ); 4671 } 4672 4673 /** 4674 * A component that defines a node that is to be created. 4675 * 4676 * @param <Next> The interface that is to be returned to complete the create request 4677 * @author Randall Hauch 4678 */ 4679 public interface CreateNode<Next> { 4680 /** 4681 * Specify the name of the node that is to be created. 4682 * 4683 * @param nodeName the name of the new node 4684 * @param properties the properties for the new node 4685 * @return the next component for making additional requests. 4686 */ 4687 Next node( String nodeName, 4688 Property... properties ); 4689 4690 /** 4691 * Specify the name of the node that is to be created. 4692 * 4693 * @param nodeName the name of the new node 4694 * @param properties the properties for the new node 4695 * @return the next component for making additional requests. 4696 */ 4697 Next node( String nodeName, 4698 Iterator<Property> properties ); 4699 4700 /** 4701 * Specify the name of the node that is to be created. 4702 * 4703 * @param nodeName the name of the new node 4704 * @param properties the properties for the new node 4705 * @return the next component for making additional requests. 4706 */ 4707 Next node( String nodeName, 4708 Iterable<Property> properties ); 4709 } 4710 4711 /** 4712 * A component that defines a node that is to be created. 4713 * 4714 * @param <Next> The interface that is to be returned to complete the create request 4715 * @author Randall Hauch 4716 */ 4717 public interface CreateNodeNamed<Next> { 4718 /** 4719 * Specify the name of the node that is to be created. 4720 * 4721 * @param nodeName the name of the new node 4722 * @return the interface used to complete the request 4723 */ 4724 Create<Next> nodeNamed( String nodeName ); 4725 4726 /** 4727 * Specify the name of the node that is to be created. 4728 * 4729 * @param nodeName the name of the new node 4730 * @return the interface used to complete the request 4731 */ 4732 Create<Next> nodeNamed( Name nodeName ); 4733 } 4734 4735 /** 4736 * A component that defines the location into which a node should be copied or moved. 4737 * 4738 * @param <Next> The interface that is to be returned when this request is completed 4739 * @author Randall Hauch 4740 */ 4741 public interface ImportInto<Next> { 4742 /** 4743 * Specify whether the root element in the XML document should be skipped (that is, not be represented by a node). By 4744 * default, the root element is not skipped. 4745 * 4746 * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element 4747 * @return the interface used to specify the location where the content should be placed 4748 */ 4749 ImportInto<Next> skippingRootElement( boolean skip ); 4750 4751 /** 4752 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4753 * 4754 * @param to the location of the new parent 4755 * @return the interface for additional requests or actions 4756 * @throws IOException if there is a problem reading the content being imported 4757 * @throws SAXException if there is a problem with the SAX Parser 4758 */ 4759 Next into( Location to ) throws IOException, SAXException; 4760 4761 /** 4762 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4763 * 4764 * @param toPath the path of the new parent 4765 * @return the interface for additional requests or actions 4766 * @throws IOException if there is a problem reading the content being imported 4767 * @throws SAXException if there is a problem with the SAX Parser 4768 */ 4769 Next into( String toPath ) throws IOException, SAXException; 4770 4771 /** 4772 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4773 * 4774 * @param to the path of the new parent 4775 * @return the interface for additional requests or actions 4776 * @throws IOException if there is a problem reading the content being imported 4777 * @throws SAXException if there is a problem with the SAX Parser 4778 */ 4779 Next into( Path to ) throws IOException, SAXException; 4780 4781 /** 4782 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4783 * 4784 * @param to the UUID of the new parent 4785 * @return the interface for additional requests or actions 4786 * @throws IOException if there is a problem reading the content being imported 4787 * @throws SAXException if there is a problem with the SAX Parser 4788 */ 4789 Next into( UUID to ) throws IOException, SAXException; 4790 4791 /** 4792 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4793 * 4794 * @param idProperty the property that uniquely identifies the new parent 4795 * @return the interface for additional requests or actions 4796 * @throws IOException if there is a problem reading the content being imported 4797 * @throws SAXException if there is a problem with the SAX Parser 4798 */ 4799 Next into( Property idProperty ) throws IOException, SAXException; 4800 4801 /** 4802 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4803 * 4804 * @param firstIdProperty the first property that, with the <code>additionalIdProperties</code>, uniquely identifies the 4805 * new parent 4806 * @param additionalIdProperties the additional properties that, with the <code>additionalIdProperties</code>, uniquely 4807 * identifies the new parent 4808 * @return the interface for additional requests or actions 4809 * @throws IOException if there is a problem reading the content being imported 4810 * @throws SAXException if there is a problem with the SAX Parser 4811 */ 4812 Next into( Property firstIdProperty, 4813 Property... additionalIdProperties ) throws IOException, SAXException; 4814 4815 /** 4816 * Finish the import by specifying the Location.create into which the node should be copied/moved. 4817 * 4818 * @param idProperties the properties that uniquely identifies the new parent 4819 * @return the interface for additional requests or actions 4820 * @throws IOException if there is a problem reading the content being imported 4821 * @throws SAXException if there is a problem with the SAX Parser 4822 */ 4823 Next into( Iterable<Property> idProperties ) throws IOException, SAXException; 4824 } 4825 4826 public interface BatchConjunction extends Conjunction<Batch>, Executable<Node> { 4827 } 4828 4829 public interface GetNodeConjunction<Next> extends Conjunction<Next> { 4830 Node andReturn(); 4831 } 4832 4833 protected class GetNodeOrReturnGraph implements GetNodeConjunction<Graph> { 4834 private final Location location; 4835 4836 GetNodeOrReturnGraph( Location location ) { 4837 assert location != null; 4838 this.location = location; 4839 } 4840 4841 /** 4842 * {@inheritDoc} 4843 * 4844 * @see org.jboss.dna.graph.Graph.Conjunction#and() 4845 */ 4846 public Graph and() { 4847 return Graph.this; 4848 } 4849 4850 /** 4851 * {@inheritDoc} 4852 * 4853 * @see org.jboss.dna.graph.Graph.GetNodeConjunction#andReturn() 4854 */ 4855 public Node andReturn() { 4856 return and().getNodeAt(location); 4857 } 4858 } 4859 4860 // ---------------------------------------------------------------------------------------------------------------- 4861 // Node Implementation 4862 // ---------------------------------------------------------------------------------------------------------------- 4863 @Immutable 4864 protected class GraphNode implements Node { 4865 private final ReadNodeRequest request; 4866 4867 /*package*/GraphNode( ReadNodeRequest request ) { 4868 this.request = request; 4869 } 4870 4871 public Location getLocation() { 4872 return request.getActualLocationOfNode(); 4873 } 4874 4875 public Graph getGraph() { 4876 return Graph.this; 4877 } 4878 4879 public Collection<Property> getProperties() { 4880 return request.getProperties(); 4881 } 4882 4883 public Property getProperty( Name name ) { 4884 return getPropertiesByName().get(name); 4885 } 4886 4887 public Property getProperty( String nameStr ) { 4888 Name name = getContext().getValueFactories().getNameFactory().create(nameStr); 4889 return getPropertiesByName().get(name); 4890 } 4891 4892 public Map<Name, Property> getPropertiesByName() { 4893 return request.getPropertiesByName(); 4894 } 4895 4896 public List<Location> getChildren() { 4897 return request.getChildren(); 4898 } 4899 4900 public boolean hasChildren() { 4901 return request.getChildren().size() > 0; 4902 } 4903 4904 public List<Segment> getChildrenSegments() { 4905 return getSegments(getChildren()); 4906 } 4907 4908 public Iterator<Location> iterator() { 4909 return request.getChildren().iterator(); 4910 } 4911 4912 @Override 4913 public int hashCode() { 4914 return getLocation().hashCode(); 4915 } 4916 4917 @Override 4918 public boolean equals( Object obj ) { 4919 if (obj instanceof Node) { 4920 Node that = (Node)obj; 4921 return this.getLocation().equals(that.getLocation()); 4922 } 4923 return false; 4924 } 4925 4926 @Override 4927 public String toString() { 4928 return "Node " + getLocation().toString(); 4929 } 4930 } 4931 4932 // ---------------------------------------------------------------------------------------------------------------- 4933 // Results implementation for the batched requests 4934 // ---------------------------------------------------------------------------------------------------------------- 4935 @Immutable 4936 class BatchResults implements Results { 4937 private final Map<Path, BatchResultsNode> nodes = new HashMap<Path, BatchResultsNode>(); 4938 4939 /*package*/BatchResults( List<Request> requests ) { 4940 for (Request request : requests) { 4941 if (request instanceof ReadAllPropertiesRequest) { 4942 ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request; 4943 getOrCreateNode(read.getActualLocationOfNode()).setProperties(read.getPropertiesByName()); 4944 } else if (request instanceof ReadPropertyRequest) { 4945 ReadPropertyRequest read = (ReadPropertyRequest)request; 4946 getOrCreateNode(read.getActualLocationOfNode()).addProperty(read.getProperty()); 4947 } else if (request instanceof ReadNodeRequest) { 4948 ReadNodeRequest read = (ReadNodeRequest)request; 4949 BatchResultsNode node = getOrCreateNode(read.getActualLocationOfNode()); 4950 node.setProperties(read.getPropertiesByName()); 4951 node.setChildren(read.getChildren()); 4952 } else if (request instanceof ReadBlockOfChildrenRequest) { 4953 throw new IllegalStateException(); 4954 } else if (request instanceof ReadAllChildrenRequest) { 4955 ReadAllChildrenRequest read = (ReadAllChildrenRequest)request; 4956 getOrCreateNode(read.getActualLocationOfNode()).setChildren(read.getChildren()); 4957 } else if (request instanceof ReadBranchRequest) { 4958 ReadBranchRequest read = (ReadBranchRequest)request; 4959 for (Location location : read) { 4960 BatchResultsNode node = getOrCreateNode(location); 4961 node.setProperties(read.getPropertiesFor(location)); 4962 node.setChildren(read.getChildren(location)); 4963 } 4964 } 4965 } 4966 for (Map.Entry<Path, BatchResultsNode> entry : nodes.entrySet()) { 4967 entry.getValue().freeze(); 4968 } 4969 } 4970 4971 /*package*/BatchResults( Request request ) { 4972 if (request instanceof ReadAllPropertiesRequest) { 4973 ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request; 4974 getOrCreateNode(read.getActualLocationOfNode()).setProperties(read.getPropertiesByName()); 4975 } else if (request instanceof ReadPropertyRequest) { 4976 ReadPropertyRequest read = (ReadPropertyRequest)request; 4977 getOrCreateNode(read.getActualLocationOfNode()).addProperty(read.getProperty()); 4978 } else if (request instanceof ReadNodeRequest) { 4979 ReadNodeRequest read = (ReadNodeRequest)request; 4980 BatchResultsNode node = getOrCreateNode(read.getActualLocationOfNode()); 4981 node.setProperties(read.getPropertiesByName()); 4982 node.setChildren(read.getChildren()); 4983 } else if (request instanceof ReadBlockOfChildrenRequest) { 4984 throw new IllegalStateException(); 4985 } else if (request instanceof ReadAllChildrenRequest) { 4986 ReadAllChildrenRequest read = (ReadAllChildrenRequest)request; 4987 getOrCreateNode(read.getActualLocationOfNode()).setChildren(read.getChildren()); 4988 } else if (request instanceof ReadBranchRequest) { 4989 ReadBranchRequest read = (ReadBranchRequest)request; 4990 for (Location location : read) { 4991 BatchResultsNode node = getOrCreateNode(location); 4992 node.setProperties(read.getPropertiesFor(location)); 4993 node.setChildren(read.getChildren(location)); 4994 } 4995 } 4996 for (Map.Entry<Path, BatchResultsNode> entry : nodes.entrySet()) { 4997 entry.getValue().freeze(); 4998 } 4999 } 5000 5001 /*package*/BatchResults() { 5002 } 5003 5004 private BatchResultsNode getOrCreateNode( Location location ) { 5005 BatchResultsNode node = nodes.get(location); 5006 if (node == null) { 5007 node = new BatchResultsNode(location); 5008 assert location.getPath() != null; 5009 nodes.put(location.getPath(), node); 5010 } 5011 return node; 5012 } 5013 5014 public Graph getGraph() { 5015 return Graph.this; 5016 } 5017 5018 protected void checkIsAbsolute( Path path ) { 5019 if (!path.isAbsolute()) { 5020 throw new IllegalArgumentException(GraphI18n.pathIsNotAbsolute.text(path)); 5021 } 5022 } 5023 5024 public Node getNode( String pathStr ) { 5025 Path path = createPath(pathStr); 5026 checkIsAbsolute(path); 5027 return nodes.get(path); 5028 } 5029 5030 public Node getNode( Path path ) { 5031 CheckArg.isNotNull(path, "path"); 5032 checkIsAbsolute(path); 5033 return nodes.get(path); 5034 } 5035 5036 public Node getNode( Location location ) { 5037 CheckArg.isNotNull(location, "location"); 5038 CheckArg.isNotNull(location.getPath(), "location.getPath()"); 5039 return nodes.get(location.getPath()); 5040 } 5041 5042 public boolean includes( String path ) { 5043 return getNode(path) != null; 5044 } 5045 5046 public boolean includes( Path path ) { 5047 return getNode(path) != null; 5048 } 5049 5050 public boolean includes( Location location ) { 5051 return getNode(location) != null; 5052 } 5053 5054 public Iterator<Node> iterator() { 5055 List<Path> paths = new ArrayList<Path>(nodes.keySet()); 5056 Collections.sort(paths); 5057 final Iterator<Path> pathIter = paths.iterator(); 5058 return new Iterator<Node>() { 5059 public boolean hasNext() { 5060 return pathIter.hasNext(); 5061 } 5062 5063 public Node next() { 5064 Path nextPath = pathIter.next(); 5065 return getNode(nextPath); 5066 } 5067 5068 public void remove() { 5069 throw new UnsupportedOperationException(); 5070 } 5071 }; 5072 } 5073 } 5074 5075 @Immutable 5076 class BatchResultsNode implements Node { 5077 private final Location location; 5078 private Map<Name, Property> properties; 5079 private List<Location> children; 5080 5081 BatchResultsNode( Location location ) { 5082 this.location = location; 5083 } 5084 5085 void addProperty( Property property ) { 5086 if (this.properties == null) this.properties = new HashMap<Name, Property>(); 5087 this.properties.put(property.getName(), property); 5088 } 5089 5090 void setProperties( Map<Name, Property> properties ) { 5091 this.properties = properties; 5092 } 5093 5094 void setChildren( List<Location> children ) { 5095 this.children = children; 5096 } 5097 5098 void freeze() { 5099 if (properties != null) properties = Collections.unmodifiableMap(properties); 5100 else properties = Collections.emptyMap(); 5101 if (children != null) children = Collections.unmodifiableList(children); 5102 else children = Collections.emptyList(); 5103 } 5104 5105 public List<Segment> getChildrenSegments() { 5106 return getSegments(getChildren()); 5107 } 5108 5109 public Graph getGraph() { 5110 return Graph.this; 5111 } 5112 5113 public Location getLocation() { 5114 return location; 5115 } 5116 5117 public Collection<Property> getProperties() { 5118 return properties.values(); 5119 } 5120 5121 public Map<Name, Property> getPropertiesByName() { 5122 return properties; 5123 } 5124 5125 public Property getProperty( Name name ) { 5126 return properties.get(name); 5127 } 5128 5129 public Property getProperty( String nameStr ) { 5130 Name name = getContext().getValueFactories().getNameFactory().create(nameStr); 5131 return properties.get(name); 5132 } 5133 5134 public List<Location> getChildren() { 5135 return children; 5136 } 5137 5138 public boolean hasChildren() { 5139 return children.size() != 0; 5140 } 5141 5142 public Iterator<Location> iterator() { 5143 return children.iterator(); 5144 } 5145 5146 @Override 5147 public int hashCode() { 5148 return location.hashCode(); 5149 } 5150 5151 @Override 5152 public boolean equals( Object obj ) { 5153 if (obj instanceof Node) { 5154 Node that = (Node)obj; 5155 return this.location.equals(that.getLocation()); 5156 } 5157 return false; 5158 } 5159 5160 @Override 5161 public String toString() { 5162 return "Node " + getLocation().toString(); 5163 } 5164 5165 } 5166 5167 // ---------------------------------------------------------------------------------------------------------------- 5168 // Subgraph and SubgraphNode implementations 5169 // ---------------------------------------------------------------------------------------------------------------- 5170 @Immutable 5171 class SubgraphResults implements Subgraph { 5172 private final ReadBranchRequest request; 5173 5174 SubgraphResults( ReadBranchRequest request ) { 5175 this.request = request; 5176 } 5177 5178 public Graph getGraph() { 5179 return Graph.this; 5180 } 5181 5182 public Location getLocation() { 5183 return request.getActualLocationOfNode(); 5184 } 5185 5186 public SubgraphNode getRoot() { 5187 return getNode(getLocation()); 5188 } 5189 5190 public int getMaximumDepth() { 5191 return request.maximumDepth(); 5192 } 5193 5194 public Iterator<SubgraphNode> iterator() { 5195 final Iterator<Location> iter = request.iterator(); 5196 return new Iterator<SubgraphNode>() { 5197 public boolean hasNext() { 5198 return iter.hasNext(); 5199 } 5200 5201 public SubgraphNode next() { 5202 return getNode(iter.next()); 5203 } 5204 5205 public void remove() { 5206 throw new UnsupportedOperationException(); 5207 } 5208 }; 5209 } 5210 5211 public boolean includes( Path path ) { 5212 CheckArg.isNotNull(path, "path"); 5213 path = getAbsolutePath(path); 5214 return request.includes(path); 5215 } 5216 5217 public boolean includes( Location location ) { 5218 CheckArg.isNotNull(location, "location"); 5219 return request.includes(location); 5220 } 5221 5222 public boolean includes( String pathStr ) { 5223 Path path = createPath(pathStr); 5224 path = getAbsolutePath(path); 5225 return includes(path); 5226 } 5227 5228 public SubgraphNode getNode( Location location ) { 5229 if (!location.hasPath()) return null; 5230 Location actualLocation = request.getLocationFor(location.getPath()); 5231 if (actualLocation == null) return null; 5232 return new SubgraphNodeImpl(actualLocation, request); 5233 } 5234 5235 public SubgraphNode getNode( Path path ) { 5236 path = getAbsolutePath(path); 5237 if (!includes(path)) return null; 5238 Location location = request.getLocationFor(path); 5239 if (location == null) return null; 5240 return new SubgraphNodeImpl(location, request); 5241 } 5242 5243 public SubgraphNode getNode( String pathStr ) { 5244 CheckArg.isNotEmpty(pathStr, "path"); 5245 Path path = createPath(pathStr); 5246 path = getAbsolutePath(path); 5247 return getNode(path); 5248 } 5249 5250 public SubgraphNode getNode( Name relativePath ) { 5251 Path path = getGraph().getContext() 5252 .getValueFactories() 5253 .getPathFactory() 5254 .create(getLocation().getPath(), relativePath); 5255 path = path.getNormalizedPath(); 5256 return getNode(path); 5257 } 5258 5259 protected Path getAbsolutePath( Path absoluteOrRelative ) { 5260 Path result = absoluteOrRelative; 5261 if (!result.isAbsolute()) { 5262 result = getGraph().getContext().getValueFactories().getPathFactory().create(getLocation().getPath(), result); 5263 result = result.getNormalizedPath(); 5264 } 5265 return result; 5266 } 5267 5268 @Override 5269 public int hashCode() { 5270 return getLocation().hashCode(); 5271 } 5272 5273 @Override 5274 public String toString() { 5275 return "Subgraph " + getLocation().toString(); 5276 } 5277 } 5278 5279 protected static final List<Location> NO_CHILDREN = Collections.emptyList(); 5280 5281 @Immutable 5282 class SubgraphNodeImpl implements SubgraphNode { 5283 private final Location location; 5284 private final ReadBranchRequest request; 5285 5286 SubgraphNodeImpl( Location location, 5287 ReadBranchRequest request ) { 5288 this.location = location; 5289 this.request = request; 5290 } 5291 5292 public List<Location> getChildren() { 5293 List<Location> children = request.getChildren(location); 5294 if (children == null) children = NO_CHILDREN; 5295 return children; 5296 } 5297 5298 public Graph getGraph() { 5299 return Graph.this; 5300 } 5301 5302 public Location getLocation() { 5303 return location; 5304 } 5305 5306 public Collection<Property> getProperties() { 5307 return getPropertiesByName().values(); 5308 } 5309 5310 public Map<Name, Property> getPropertiesByName() { 5311 return request.getPropertiesFor(location); 5312 } 5313 5314 public Property getProperty( Name name ) { 5315 return getPropertiesByName().get(name); 5316 } 5317 5318 public Property getProperty( String nameStr ) { 5319 Name name = getContext().getValueFactories().getNameFactory().create(nameStr); 5320 return getPropertiesByName().get(name); 5321 } 5322 5323 public boolean hasChildren() { 5324 return getChildren().size() != 0; 5325 } 5326 5327 public List<Segment> getChildrenSegments() { 5328 return getSegments(getChildren()); 5329 } 5330 5331 public Iterator<Location> iterator() { 5332 return getChildren().iterator(); 5333 } 5334 5335 public SubgraphNode getNode( Name childName ) { 5336 Path path = getContext().getValueFactories().getPathFactory().create(location.getPath(), childName); 5337 Location location = request.getLocationFor(path); 5338 if (location == null) return null; 5339 return new SubgraphNodeImpl(location, request); 5340 } 5341 5342 public SubgraphNode getNode( Path relativePath ) { 5343 Path path = getContext().getValueFactories().getPathFactory().create(location.getPath(), relativePath); 5344 path = path.getNormalizedPath(); 5345 Location location = request.getLocationFor(path); 5346 if (location == null) return null; 5347 return new SubgraphNodeImpl(location, request); 5348 } 5349 5350 @Override 5351 public int hashCode() { 5352 return location.hashCode(); 5353 } 5354 5355 @Override 5356 public boolean equals( Object obj ) { 5357 if (obj instanceof Node) { 5358 Node that = (Node)obj; 5359 return this.location.equals(that.getLocation()); 5360 } 5361 return false; 5362 } 5363 5364 @Override 5365 public String toString() { 5366 return "Node " + getLocation().toString(); 5367 } 5368 } 5369 5370 // ---------------------------------------------------------------------------------------------------------------- 5371 // Action Implementations 5372 // ---------------------------------------------------------------------------------------------------------------- 5373 @Immutable 5374 protected abstract class AbstractAction<T> implements Conjunction<T> { 5375 private final T afterConjunction; 5376 5377 /*package*/AbstractAction( T afterConjunction ) { 5378 this.afterConjunction = afterConjunction; 5379 } 5380 5381 /*package*/T afterConjunction() { 5382 return this.afterConjunction; 5383 } 5384 5385 public T and() { 5386 return this.afterConjunction; 5387 } 5388 5389 /*package*/Path createPath( String path ) { 5390 return Graph.this.getContext().getValueFactories().getPathFactory().create(path); 5391 } 5392 5393 /*package*/Name createName( String name ) { 5394 return Graph.this.getContext().getValueFactories().getNameFactory().create(name); 5395 } 5396 } 5397 5398 @NotThreadSafe 5399 protected abstract class MoveAction<T> extends AbstractAction<T> implements Move<T> { 5400 private final Locations from; 5401 private Name newName; 5402 5403 /*package*/MoveAction( T afterConjunction, 5404 Location from ) { 5405 super(afterConjunction); 5406 this.from = new Locations(from); 5407 } 5408 5409 public Move<T> and( Location from ) { 5410 this.from.add(from); 5411 return this; 5412 } 5413 5414 public Move<T> and( String from ) { 5415 this.from.add(Location.create(createPath(from))); 5416 return this; 5417 } 5418 5419 public Move<T> and( Path from ) { 5420 this.from.add(Location.create(from)); 5421 return this; 5422 } 5423 5424 public Move<T> and( Property firstFrom, 5425 Property... additionalFroms ) { 5426 this.from.add(Location.create(firstFrom, additionalFroms)); 5427 return this; 5428 } 5429 5430 public Move<T> and( Iterable<Property> idPropertiesFrom ) { 5431 this.from.add(Location.create(idPropertiesFrom)); 5432 return this; 5433 } 5434 5435 public Move<T> and( Property from ) { 5436 this.from.add(Location.create(from)); 5437 return this; 5438 } 5439 5440 public Move<T> and( UUID from ) { 5441 this.from.add(Location.create(from)); 5442 return this; 5443 } 5444 5445 public Into<T> as( Name newName ) { 5446 this.newName = newName; 5447 return this; 5448 } 5449 5450 /** 5451 * {@inheritDoc} 5452 * 5453 * @see org.jboss.dna.graph.Graph.AsName#as(java.lang.String) 5454 */ 5455 public Into<T> as( String newName ) { 5456 return as(createName(newName)); 5457 } 5458 5459 /** 5460 * Submit any requests to move the targets into the supplied parent location 5461 * 5462 * @param from the location(s) that are being moved; never null 5463 * @param into the parent location 5464 * @param newName the new name for the node being moved; may be null 5465 * @return this object, for method chaining 5466 */ 5467 protected abstract T submit( Locations from, 5468 Location into, 5469 Name newName ); 5470 5471 public T into( Location into ) { 5472 return submit(from, into, newName); 5473 } 5474 5475 public T into( Path into ) { 5476 return submit(from, Location.create(into), newName); 5477 } 5478 5479 public T into( UUID into ) { 5480 return submit(from, Location.create(into), newName); 5481 } 5482 5483 public T into( Property firstIdProperty, 5484 Property... additionalIdProperties ) { 5485 return submit(from, Location.create(firstIdProperty, additionalIdProperties), newName); 5486 } 5487 5488 public T into( Property into ) { 5489 return submit(from, Location.create(into), newName); 5490 } 5491 5492 public T into( String into ) { 5493 return submit(from, Location.create(createPath(into)), newName); 5494 } 5495 } 5496 5497 @NotThreadSafe 5498 protected abstract class CopyAction<T> extends AbstractAction<T> implements Copy<T> { 5499 private final Locations from; 5500 5501 /*package*/CopyAction( T afterConjunction, 5502 Location from ) { 5503 super(afterConjunction); 5504 this.from = new Locations(from); 5505 } 5506 5507 public Copy<T> and( Location from ) { 5508 this.from.add(from); 5509 return this; 5510 } 5511 5512 public Copy<T> and( String from ) { 5513 this.from.add(Location.create(createPath(from))); 5514 return this; 5515 } 5516 5517 public Copy<T> and( Path from ) { 5518 this.from.add(Location.create(from)); 5519 return this; 5520 } 5521 5522 public Copy<T> and( Property firstFrom, 5523 Property... additionalFroms ) { 5524 this.from.add(Location.create(firstFrom, additionalFroms)); 5525 return this; 5526 } 5527 5528 public Copy<T> and( Iterable<Property> idProperties ) { 5529 this.from.add(Location.create(idProperties)); 5530 return this; 5531 } 5532 5533 public Copy<T> and( Property from ) { 5534 this.from.add(Location.create(from)); 5535 return this; 5536 } 5537 5538 public Copy<T> and( UUID from ) { 5539 this.from.add(Location.create(from)); 5540 return this; 5541 } 5542 5543 /** 5544 * Submit any requests to move the targets into the supplied parent location 5545 * 5546 * @param from the locations that are being copied 5547 * @param into the parent location 5548 * @param nameForCopy the name that should be used for the copy, or null if the name should be the same as the original 5549 * @return this object, for method chaining 5550 */ 5551 protected abstract T submit( Locations from, 5552 Location into, 5553 Name nameForCopy ); 5554 5555 public T into( Location into ) { 5556 return submit(from, into, null); 5557 } 5558 5559 public T into( Path into ) { 5560 return submit(from, Location.create(into), null); 5561 } 5562 5563 public T into( UUID into ) { 5564 return submit(from, Location.create(into), null); 5565 } 5566 5567 public T into( Property firstIdProperty, 5568 Property... additionalIdProperties ) { 5569 return submit(from, Location.create(firstIdProperty, additionalIdProperties), null); 5570 } 5571 5572 public T into( Property into ) { 5573 return submit(from, Location.create(into), null); 5574 } 5575 5576 public T into( String into ) { 5577 return submit(from, Location.create(createPath(into)), null); 5578 } 5579 5580 public T to( Location desiredLocation ) { 5581 if (!desiredLocation.hasPath()) { 5582 throw new IllegalArgumentException(GraphI18n.unableToCopyToLocationWithoutAPath.text(this.from, desiredLocation)); 5583 } 5584 Path desiredPath = desiredLocation.getPath(); 5585 if (desiredPath.isRoot()) { 5586 throw new IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from, desiredLocation)); 5587 } 5588 Path parent = desiredPath.getParent(); 5589 return submit(from, Location.create(parent), desiredPath.getLastSegment().getName()); 5590 } 5591 5592 public T to( Path desiredPath ) { 5593 if (desiredPath.isRoot()) { 5594 throw new IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from, desiredPath)); 5595 } 5596 Path parent = desiredPath.getParent(); 5597 return submit(from, Location.create(parent), desiredPath.getLastSegment().getName()); 5598 } 5599 5600 public T to( String desiredPath ) { 5601 return to(createPath(desiredPath)); 5602 } 5603 } 5604 5605 @NotThreadSafe 5606 protected abstract class CreateAction<T> extends AbstractAction<T> implements Create<T> { 5607 private final String workspaceName; 5608 private final Location parent; 5609 private final Name childName; 5610 private final Map<Name, Property> properties = new HashMap<Name, Property>(); 5611 private boolean submitted = false; 5612 5613 /*package*/CreateAction( T afterConjunction, 5614 Location parent, 5615 String workspaceName, 5616 Name childName ) { 5617 super(afterConjunction); 5618 this.parent = parent; 5619 this.workspaceName = workspaceName; 5620 this.childName = childName; 5621 } 5622 5623 public Create<T> and( UUID uuid ) { 5624 PropertyFactory factory = getContext().getPropertyFactory(); 5625 properties.put(DnaLexicon.UUID, factory.create(DnaLexicon.UUID, uuid)); 5626 return this; 5627 } 5628 5629 public Create<T> and( Property property ) { 5630 properties.put(property.getName(), property); 5631 return this; 5632 } 5633 5634 public Create<T> and( Iterable<Property> properties ) { 5635 for (Property property : properties) { 5636 this.properties.put(property.getName(), property); 5637 } 5638 return this; 5639 } 5640 5641 public Create<T> and( String name, 5642 Object... values ) { 5643 ExecutionContext context = getContext(); 5644 PropertyFactory factory = context.getPropertyFactory(); 5645 NameFactory nameFactory = context.getValueFactories().getNameFactory(); 5646 Name propertyName = nameFactory.create(name); 5647 properties.put(propertyName, factory.create(propertyName, values)); 5648 return this; 5649 } 5650 5651 public Create<T> and( Name name, 5652 Object... values ) { 5653 PropertyFactory factory = getContext().getPropertyFactory(); 5654 properties.put(name, factory.create(name, values)); 5655 return this; 5656 } 5657 5658 public Create<T> and( Property property, 5659 Property... additionalProperties ) { 5660 properties.put(property.getName(), property); 5661 for (Property additionalProperty : additionalProperties) { 5662 properties.put(additionalProperty.getName(), additionalProperty); 5663 } 5664 return this; 5665 } 5666 5667 public Create<T> with( UUID uuid ) { 5668 return and(uuid); 5669 } 5670 5671 public Create<T> with( Property property ) { 5672 return and(property); 5673 } 5674 5675 public Create<T> with( Iterable<Property> properties ) { 5676 return and(properties); 5677 } 5678 5679 public Create<T> with( Property property, 5680 Property... additionalProperties ) { 5681 return and(property, additionalProperties); 5682 } 5683 5684 public Create<T> with( String name, 5685 Object... values ) { 5686 return and(name, values); 5687 } 5688 5689 public Create<T> with( Name name, 5690 Object... values ) { 5691 return and(name, values); 5692 } 5693 5694 protected abstract T submit( Location parent, 5695 String workspaceName, 5696 Name childName, 5697 Collection<Property> properties ); 5698 5699 @Override 5700 public T and() { 5701 if (!submitted) { 5702 submit(parent, workspaceName, childName, this.properties.values()); 5703 submitted = true; 5704 } 5705 return super.and(); 5706 } 5707 } 5708 5709 @NotThreadSafe 5710 protected abstract class CreateNodeNamedAction<T> extends AbstractAction<T> implements CreateNodeNamed<T> { 5711 private final Location parent; 5712 5713 protected CreateNodeNamedAction( T afterConjunction, 5714 Location parent ) { 5715 super(afterConjunction); 5716 this.parent = parent; 5717 } 5718 5719 public CreateAction<T> nodeNamed( String name ) { 5720 NameFactory factory = getContext().getValueFactories().getNameFactory(); 5721 Name nameObj = factory.create(name); 5722 return createWith(afterConjunction(), parent, nameObj); 5723 } 5724 5725 public CreateAction<T> nodeNamed( Name name ) { 5726 return createWith(afterConjunction(), parent, name); 5727 } 5728 5729 protected abstract CreateAction<T> createWith( T afterConjunction, 5730 Location parent, 5731 Name nodeName ); 5732 } 5733 5734 @Immutable 5735 protected static final class GraphWorkspace implements Workspace { 5736 private final String name; 5737 private final Location root; 5738 5739 GraphWorkspace( String name, 5740 Location root ) { 5741 assert name != null; 5742 assert root != null; 5743 this.name = name; 5744 this.root = root; 5745 } 5746 5747 /** 5748 * {@inheritDoc} 5749 * 5750 * @see org.jboss.dna.graph.Workspace#getName() 5751 */ 5752 public String getName() { 5753 return name; 5754 } 5755 5756 /** 5757 * {@inheritDoc} 5758 * 5759 * @see org.jboss.dna.graph.Workspace#getRoot() 5760 */ 5761 public Location getRoot() { 5762 return root; 5763 } 5764 5765 /** 5766 * {@inheritDoc} 5767 * 5768 * @see java.lang.Object#hashCode() 5769 */ 5770 @Override 5771 public int hashCode() { 5772 return this.name.hashCode(); 5773 } 5774 5775 /** 5776 * {@inheritDoc} 5777 * 5778 * @see java.lang.Object#equals(java.lang.Object) 5779 */ 5780 @Override 5781 public boolean equals( Object obj ) { 5782 if (obj == this) return true; 5783 if (obj instanceof GraphWorkspace) { 5784 GraphWorkspace that = (GraphWorkspace)obj; 5785 if (!this.getName().equals(that.getName())) return false; 5786 // all root nodes should be equivalent, so no need to check 5787 return true; 5788 } 5789 return false; 5790 } 5791 5792 /** 5793 * {@inheritDoc} 5794 * 5795 * @see java.lang.Object#toString() 5796 */ 5797 @Override 5798 public String toString() { 5799 return "Workspace \"" + this.name + "\" (root = " + this.root + " )"; 5800 } 5801 } 5802 5803 /** 5804 * A set of nodes returned from a {@link Graph graph}, with methods to access the properties and children of the nodes in the 5805 * result. The {@link #iterator()} method can be used to iterate all over the nodes in the result. 5806 * 5807 * @author Randall Hauch 5808 * @param <NodeType> the type of node that tis results deals with 5809 */ 5810 @Immutable 5811 public interface BaseResults<NodeType extends Node> extends Iterable<NodeType> { 5812 5813 /** 5814 * Get the graph containing the node. 5815 * 5816 * @return the graph 5817 */ 5818 Graph getGraph(); 5819 5820 /** 5821 * Get the node at the supplied location. 5822 * 5823 * @param path the path of the node in these results 5824 * @return the node, or null if the node is not {@link #includes(Path) included} in these results 5825 */ 5826 NodeType getNode( String path ); 5827 5828 /** 5829 * Get the node at the supplied location. 5830 * 5831 * @param path the path of the node in these results 5832 * @return the node, or null if the node is not {@link #includes(Path) included} in these results 5833 */ 5834 NodeType getNode( Path path ); 5835 5836 /** 5837 * Get the node at the supplied location. 5838 * 5839 * @param location the location of the node 5840 * @return the node, or null if the node is not {@link #includes(Path) included} in these results 5841 */ 5842 NodeType getNode( Location location ); 5843 5844 /** 5845 * Return whether these results include a node at the supplied location. 5846 * 5847 * @param path the path of the node in these results 5848 * @return true if this subgraph includes the supplied location, or false otherwise 5849 */ 5850 boolean includes( String path ); 5851 5852 /** 5853 * Return whether this subgraph has a node at the supplied location. 5854 * 5855 * @param path the path of the node in these results 5856 * @return true if these results includes the supplied location, or false otherwise 5857 */ 5858 boolean includes( Path path ); 5859 5860 /** 5861 * Return whether this subgraph has a node at the supplied location. 5862 * 5863 * @param location the location of the node in these results 5864 * @return true if these results includes the supplied location, or false otherwise 5865 */ 5866 boolean includes( Location location ); 5867 5868 } 5869 }