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 }