View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.connector.map;
25  
26  import java.util.Set;
27  import java.util.UUID;
28  import org.modeshape.graph.ExecutionContext;
29  import org.modeshape.graph.Location;
30  import org.modeshape.graph.connector.LockFailedException;
31  import org.modeshape.graph.connector.UuidAlreadyExistsException;
32  import org.modeshape.graph.property.Name;
33  import org.modeshape.graph.property.Path;
34  import org.modeshape.graph.property.PathFactory;
35  import org.modeshape.graph.property.Property;
36  import org.modeshape.graph.query.QueryResults;
37  import org.modeshape.graph.request.AccessQueryRequest;
38  import org.modeshape.graph.request.LockBranchRequest.LockScope;
39  
40  /**
41   * The {@code MapWorkspace} defines the required methods for workspaces in a {@link MapRepository map repository}. By default, a
42   * map repository supports multiple workspaces, each equating logically to a map of UUIDs to {@link MapNode map nodes}.
43   * <p>
44   * As each map node (except the root-node for the workspace) has a non-null parent and a set of children, the {@link MapNode map
45   * nodes} naturally construct a tree within the workspace.
46   * </p>
47   */
48  public interface MapWorkspace {
49  
50      /**
51       * Returns the name of the workspace. There can only be one workspace with a given name per repository.
52       * 
53       * @return the name of the workspace
54       */
55      String getName();
56  
57      /**
58       * Returns the root node in the workspace. This returns a {@link MapNode map node} where {@code node.getParent() == null} and
59       * {@code node.getUuid() == repository.getRootNodeUuid()}.
60       * 
61       * @return the root node in the workspace
62       */
63      MapNode getRoot();
64  
65      /**
66       * Returns the node with the given UUID, if one exists or {@code null} if no {@MapNode node} with the given UUID
67       * exists in the workspace.
68       * <p>
69       * That is, {@code node == null || node.getUuid().equals(uuid)} for the returned node.
70       * </p>
71       * 
72       * @param uuid the UUID of the node to be retrieved; may not be null
73       * @return the node with the given UUID, if one exists or {@code null} if no {@MapNode node} with the given UUID
74       *         exists in the workspace.
75       */
76      MapNode getNode( UUID uuid );
77  
78      /**
79       * Returns the node at the given path, if one exists of {@code null} if no {@MapNode node} exists at the given path.
80       * 
81       * @param path the path of the node to retrieve; may not be null
82       * @return the node at the given path, if one exists of {@code null} if no {@MapNode node} exists at the given path.
83       */
84      MapNode getNode( Path path );
85  
86      /**
87       * Removes the given node. This method will return false if the given node does not exist in this workspace.
88       * 
89       * @param context the current execution context; may not be null
90       * @param node the node to be removed; may not be null
91       * @return whether a node was removed as a result of this operation
92       */
93      boolean removeNode( ExecutionContext context,
94                          MapNode node );
95  
96      /**
97       * Create a node at the supplied path. The parent of the new node must already exist.
98       * 
99       * @param context the environment; may not be null
100      * @param pathToNewNode the path to the new node; may not be null
101      * @param properties the properties for the new node
102      * @return the new node (or root if the path specified the root)
103      */
104     MapNode createNode( ExecutionContext context,
105                         String pathToNewNode,
106                         Iterable<Property> properties );
107 
108     /**
109      * Create a new node with the supplied name, as a child of the supplied parent.
110      * 
111      * @param context the execution context
112      * @param parentNode the parent node; may not be null
113      * @param name the name; may not be null
114      * @param uuid the UUID of the node, or null if the UUID is to be generated
115      * @param properties the properties for the new node
116      * @return the new node
117      */
118     MapNode createNode( ExecutionContext context,
119                         MapNode parentNode,
120                         Name name,
121                         UUID uuid,
122                         Iterable<Property> properties );
123 
124     /**
125      * Move the supplied node to the new parent. This method automatically removes the node from its existing parent, and also
126      * correctly adjusts the {@link Path.Segment#getIndex() index} to be correct in the new parent.
127      * 
128      * @param context
129      * @param node the node to be moved; may not be the {@link MapWorkspace#getRoot() root}
130      * @param desiredNewName the new name for the node, if it is to be changed; may be null
131      * @param newWorkspace the workspace containing the new parent node
132      * @param newParent the new parent; may not be the {@link MapWorkspace#getRoot() root}
133      * @param beforeNode the node before which this new node should be placed
134      */
135     void moveNode( ExecutionContext context,
136                    MapNode node,
137                    Name desiredNewName,
138                    MapWorkspace newWorkspace,
139                    MapNode newParent,
140                    MapNode beforeNode );
141 
142     /**
143      * This should copy the subgraph given by the original node and place the new copy under the supplied new parent. Note that
144      * internal references between nodes within the original subgraph must be reflected as internal nodes within the new subgraph.
145      * 
146      * @param context the context; may not be null
147      * @param original the node to be copied; may not be null
148      * @param newWorkspace the workspace containing the new parent node; may not be null
149      * @param newParent the parent where the copy is to be placed; may not be null
150      * @param desiredName the desired name for the node; if null, the name will be obtained from the original node
151      * @param recursive true if the copy should be recursive
152      * @return the new node, which is the top of the new subgraph
153      */
154     MapNode copyNode( ExecutionContext context,
155                       MapNode original,
156                       MapWorkspace newWorkspace,
157                       MapNode newParent,
158                       Name desiredName,
159                       boolean recursive );
160 
161     /**
162      * This should clone the subgraph given by the original node and place the cloned copy under the supplied new parent. Note
163      * that internal references between nodes within the original subgraph must be reflected as internal nodes within the new
164      * subgraph.
165      * 
166      * @param context the context; may not be null
167      * @param original the node to be cloned; may not be null
168      * @param newWorkspace the workspace containing the new parent node; may not be null
169      * @param newParent the parent where the clone is to be placed; may not be null
170      * @param desiredName the desired name for the node; if null, the name will be calculated from {@code desiredSegment}; Exactly
171      *        one of {@code desiredSegment} and {@code desiredName} must be non-null
172      * @param desiredSegment the exact segment at which the clone should be rooted; if null, the name will be inferred from
173      *        {@code desiredName}; Exactly one of {@code desiredSegment} and {@code desiredName} must be non-null
174      * @param removeExisting true if existing nodes in the new workspace with the same UUIDs as nodes in the branch rooted at
175      *        {@code original} should be removed; if false, a UuidAlreadyExistsException will be thrown if a UUID conflict is
176      *        detected
177      * @param removedExistingNodes the set into which should be placed all of the existing nodes that were removed as a result of
178      *        this clone operation, or null if these nodes need not be collected
179      * @return the new node, which is the top of the new subgraph
180      * @throws UuidAlreadyExistsException if {@code removeExisting} is true and and a UUID in the source tree already exists in
181      *         the new workspace
182      */
183     MapNode cloneNode( ExecutionContext context,
184                        MapNode original,
185                        MapWorkspace newWorkspace,
186                        MapNode newParent,
187                        Name desiredName,
188                        Path.Segment desiredSegment,
189                        boolean removeExisting,
190                        Set<Location> removedExistingNodes ) throws UuidAlreadyExistsException;
191 
192     /**
193      * Attempts to lock the given node with the given timeout. If the lock attempt fails, a {@link LockFailedException} will be
194      * thrown.
195      * 
196      * @param node the node to be locked; may not be null
197      * @param lockScope the scope of the lock (i.e., whether descendants of {@code node} should be included in the lock
198      * @param lockTimeoutInMillis the maximum lifetime of the lock in milliseconds; zero (0) indicates that the connector default
199      *        should be used
200      * @throws LockFailedException if the implementing connector supports locking but the lock could not be acquired.
201      */
202     void lockNode( MapNode node,
203                    LockScope lockScope,
204                    long lockTimeoutInMillis ) throws LockFailedException;
205 
206     /**
207      * Attempts to unlock the given node.
208      * 
209      * @param node the node to be unlocked; may not be null
210      */
211     void unlockNode( MapNode node );
212 
213     /**
214      * Find the lowest existing node along the path.
215      * 
216      * @param path the path to the node; may not be null
217      * @return the lowest existing node along the path, or the root node if no node exists on the path
218      */
219     Path getLowestExistingPath( Path path );
220 
221     /**
222      * Returns the path for the given node with this workspace if one exists, or a {@code null} if no node exists at the given
223      * path.
224      * 
225      * @param pathFactory the path factory to use to construct the path; may not be null
226      * @param node the node for which the path should be retrieved; may not be null
227      * @return the path for the given node with this workspace if one exists or null if the node does not exist in this workspace
228      */
229     Path pathFor( PathFactory pathFactory,
230                   MapNode node );
231 
232     /**
233      * Perform a query of this workspace.
234      * 
235      * @param context the context in which the query is to be executed; may not be null
236      * @param accessQuery the access query; may not be null
237      * @return the query results, or null if the query is not supported
238      */
239     QueryResults query( ExecutionContext context,
240                         AccessQueryRequest accessQuery );
241 
242     /**
243      * Perform a full-text search of this workspace.
244      * 
245      * @param context the context in which the query is to be executed; may not be null
246      * @param fullTextSearchExpression the full-text search expression; may not be null
247      * @return the query results, or null if the query is not supported
248      */
249     QueryResults search( ExecutionContext context,
250                          String fullTextSearchExpression );
251 }