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 }