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 }