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 * Unless otherwise indicated, all code in ModeShape is licensed
10 * 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.request;
25
26 import org.modeshape.common.util.CheckArg;
27 import org.modeshape.common.util.HashCode;
28 import org.modeshape.graph.Location;
29 import org.modeshape.graph.property.Path;
30 import org.modeshape.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
31
32 /**
33 * Request that an existing workspace be cloned into a target workspace with the supplied name. If the target workspace exists,
34 * the {@link #targetConflictBehavior() target conflict behavior} defines the behavior to be followed. If the workspace being
35 * cloned does not exist, the {@link #cloneConflictBehavior() clone conflict behavior} defines the behavior to be followed.
36 */
37 public final class CloneWorkspaceRequest extends ChangeRequest {
38
39 private static final long serialVersionUID = 1L;
40
41 /**
42 * The options for the behavior when a request specifies the name of the workspace to clone, but the cloned workspace does not
43 * exist.
44 */
45 public enum CloneConflictBehavior {
46 /** Do not perform the clone, and record as an {@link Request#setError(Throwable) error} on the request. */
47 DO_NOT_CLONE,
48
49 /** The clone operation is skipped quietly, resulting in an empty new workspace. */
50 SKIP_CLONE,
51 }
52
53 /**
54 * The default {@link CloneConflictBehavior} that will be used if it is unspecified.
55 */
56 public static final CloneConflictBehavior DEFAULT_CLONE_CONFLICT_BEHAVIOR = CloneConflictBehavior.DO_NOT_CLONE;
57
58 /**
59 * The default {@link CreateConflictBehavior} that will be used if it is unspecified.
60 */
61 public static final CreateConflictBehavior DEFAULT_CREATE_CONFLICT_BEHAVIOR = CreateConflictBehavior.DO_NOT_CREATE;
62
63 private final String nameOfWorkspaceToBeCloned;
64 private final String desiredNameOfTargetWorkspace;
65 private final CreateConflictBehavior createConflictBehavior;
66 private final CloneConflictBehavior cloneConflictBehavior;
67 private String actualWorkspaceName;
68 private Location actualLocationOfRoot;
69
70 /**
71 * Create a request to clone an existing workspace to create a new workspace, and specify the behavior should a workspace
72 * already exists with a name that matches the desired name for the new workspace.
73 *
74 * @param nameOfWorkspaceToBeCloned the name of the existing workspace that is to be cloned
75 * @param desiredNameOfTargetWorkspace the desired name of the target workspace
76 * @param createConflictBehavior the behavior if a workspace already exists with the same name
77 * @param cloneConflictBehavior the behavior if the workspace to be cloned does not exist
78 * @throws IllegalArgumentException if the either workspace name is null
79 */
80 public CloneWorkspaceRequest( String nameOfWorkspaceToBeCloned,
81 String desiredNameOfTargetWorkspace,
82 CreateConflictBehavior createConflictBehavior,
83 CloneConflictBehavior cloneConflictBehavior ) {
84 CheckArg.isNotNull(nameOfWorkspaceToBeCloned, "nameOfWorkspaceToBeCloned");
85 CheckArg.isNotNull(desiredNameOfTargetWorkspace, "desiredNameOfTargetWorkspace");
86 this.nameOfWorkspaceToBeCloned = nameOfWorkspaceToBeCloned;
87 this.desiredNameOfTargetWorkspace = desiredNameOfTargetWorkspace;
88 this.createConflictBehavior = createConflictBehavior != null ? createConflictBehavior : DEFAULT_CREATE_CONFLICT_BEHAVIOR;
89 this.cloneConflictBehavior = cloneConflictBehavior != null ? cloneConflictBehavior : DEFAULT_CLONE_CONFLICT_BEHAVIOR;
90 }
91
92 /**
93 * Get the name of the existing workspace that is to be cloned into the new workspace.
94 *
95 * @return the name of the existing workspace that is to be cloned; never null
96 */
97 public String nameOfWorkspaceToBeCloned() {
98 return nameOfWorkspaceToBeCloned;
99 }
100
101 /**
102 * Get the desired name for the target workspace.
103 *
104 * @return the desired name for the new workspace; never null
105 */
106 public String desiredNameOfTargetWorkspace() {
107 return desiredNameOfTargetWorkspace;
108 }
109
110 /**
111 * Get the desired behavior if a workspace already exists with the {@link #desiredNameOfTargetWorkspace() desired workspace
112 * name} .
113 *
114 * @return the desired behavior; never null
115 */
116 public CreateConflictBehavior targetConflictBehavior() {
117 return createConflictBehavior;
118 }
119
120 /**
121 * Get the desired behavior if the {@link #nameOfWorkspaceToBeCloned() cloned workspace} does not exist.
122 *
123 * @return the desired behavior; never null
124 */
125 public CloneConflictBehavior cloneConflictBehavior() {
126 return cloneConflictBehavior;
127 }
128
129 /**
130 * Get the actual name of the workspace that was created. This will be the same as the {@link #desiredNameOfTargetWorkspace()
131 * desired target name} unless there was a conflict and the {@link #targetConflictBehavior() desired behavior} was to
132 * {@link CreateConflictBehavior#CREATE_WITH_ADJUSTED_NAME alter the name}.
133 *
134 * @return the actual name of the workspace that was created, or null if a workspace was not created (yet)
135 */
136 public String getActualWorkspaceName() {
137 return actualWorkspaceName;
138 }
139
140 /**
141 * Set the actual name of the workspace that was created. This should be the same as the
142 * {@link #desiredNameOfTargetWorkspace() desired target name} unless there was a conflict and the
143 * {@link #targetConflictBehavior() desired behavior} was to {@link CreateConflictBehavior#CREATE_WITH_ADJUSTED_NAME alter the
144 * name}.
145 *
146 * @param actualWorkspaceName the actual name of the workspace that was created, or null if a workspace was not created
147 * @throws IllegalStateException if the request is frozen
148 */
149 public void setActualWorkspaceName( String actualWorkspaceName ) {
150 checkNotFrozen();
151 this.actualWorkspaceName = actualWorkspaceName;
152 }
153
154 /**
155 * Get the actual location of the root node in the new workspace, or null if the workspace was not (yet) created.
156 *
157 * @return the actual location of the root node in the new workspace, or null if the workspace was not (yet) created
158 */
159 public Location getActualLocationOfRoot() {
160 return actualLocationOfRoot;
161 }
162
163 /**
164 * Set the actual location of the root node in the new workspace.
165 *
166 * @param actualLocationOfRoot the actual location of the workspace's root node.
167 * @throws IllegalStateException if the request is frozen
168 */
169 public void setActualRootLocation( Location actualLocationOfRoot ) {
170 checkNotFrozen();
171 this.actualLocationOfRoot = actualLocationOfRoot;
172 }
173
174 /**
175 * {@inheritDoc}
176 *
177 * @see org.modeshape.graph.request.Request#isReadOnly()
178 */
179 @Override
180 public boolean isReadOnly() {
181 return false;
182 }
183
184 /**
185 * {@inheritDoc}
186 *
187 * @see org.modeshape.graph.request.Request#cancel()
188 */
189 @Override
190 public void cancel() {
191 super.cancel();
192 this.actualLocationOfRoot = null;
193 this.actualWorkspaceName = null;
194 }
195
196 /**
197 * {@inheritDoc}
198 *
199 * @see java.lang.Object#hashCode()
200 */
201 @Override
202 public int hashCode() {
203 return HashCode.compute(nameOfWorkspaceToBeCloned, desiredNameOfTargetWorkspace);
204 }
205
206 /**
207 * {@inheritDoc}
208 *
209 * @see java.lang.Object#equals(java.lang.Object)
210 */
211 @Override
212 public boolean equals( Object obj ) {
213 if (obj == this) return true;
214 if (this.getClass().isInstance(obj)) {
215 CloneWorkspaceRequest that = (CloneWorkspaceRequest)obj;
216 if (!this.nameOfWorkspaceToBeCloned.equals(that.nameOfWorkspaceToBeCloned())) return false;
217 if (!this.desiredNameOfTargetWorkspace.equals(that.desiredNameOfTargetWorkspace())) return false;
218 return true;
219 }
220 return false;
221 }
222
223 /**
224 * {@inheritDoc}
225 *
226 * @see java.lang.Object#toString()
227 */
228 @Override
229 public String toString() {
230 return "clone workspace \"" + nameOfWorkspaceToBeCloned() + "\" as workspace \"" + desiredNameOfTargetWorkspace() + "\"";
231 }
232
233 /**
234 * {@inheritDoc}
235 *
236 * @see org.modeshape.graph.request.ChangeRequest#changedLocation()
237 */
238 @Override
239 public Location changedLocation() {
240 return actualLocationOfRoot;
241 }
242
243 /**
244 * {@inheritDoc}
245 *
246 * @see org.modeshape.graph.request.ChangeRequest#changedWorkspace()
247 */
248 @Override
249 public String changedWorkspace() {
250 return actualWorkspaceName;
251 }
252
253 /**
254 * {@inheritDoc}
255 *
256 * @see org.modeshape.graph.request.ChangeRequest#changes(java.lang.String, org.modeshape.graph.property.Path)
257 */
258 @Override
259 public boolean changes( String workspace,
260 Path path ) {
261 return actualWorkspaceName != null && actualWorkspaceName.equals(workspace);
262 }
263
264 /**
265 * {@inheritDoc}
266 * <p>
267 * This method does not clone the results.
268 * </p>
269 *
270 * @see org.modeshape.graph.request.ChangeRequest#clone()
271 */
272 @Override
273 public CloneWorkspaceRequest clone() {
274 CloneWorkspaceRequest request = new CloneWorkspaceRequest(
275 nameOfWorkspaceToBeCloned,
276 actualWorkspaceName != null ? actualWorkspaceName : desiredNameOfTargetWorkspace,
277 createConflictBehavior, cloneConflictBehavior);
278 request.setActualRootLocation(actualLocationOfRoot);
279 request.setActualWorkspaceName(actualWorkspaceName);
280 return request;
281 }
282
283 @Override
284 public RequestType getType() {
285 return RequestType.CLONE_WORKSPACE;
286 }
287 }