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.request; 025 026 import org.jboss.dna.common.util.CheckArg; 027 import org.jboss.dna.common.util.HashCode; 028 import org.jboss.dna.graph.GraphI18n; 029 import org.jboss.dna.graph.Location; 030 import org.jboss.dna.graph.NodeConflictBehavior; 031 import org.jboss.dna.graph.property.Name; 032 import org.jboss.dna.graph.property.Path; 033 034 /** 035 * Instruction that a branch be copied from one location into another. This request can copy a branch in one workspace into 036 * another workspace, or it can copy a branch in the same workspace. 037 * 038 * @author Randall Hauch 039 */ 040 public class CopyBranchRequest extends ChangeRequest { 041 042 private static final long serialVersionUID = 1L; 043 044 public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND; 045 046 private final Location from; 047 private final Location into; 048 private final String fromWorkspace; 049 private final String intoWorkspace; 050 private final Name desiredNameForCopy; 051 private final NodeConflictBehavior conflictBehavior; 052 private Location actualFromLocation; 053 private Location actualIntoLocation; 054 055 /** 056 * Create a request to copy a branch to another. 057 * 058 * @param from the location of the top node in the existing branch that is to be copied 059 * @param fromWorkspace the name of the workspace where the <code>from</code> node exists 060 * @param into the location of the existing node into which the copy should be placed 061 * @param intoWorkspace the name of the workspace where the <code>into</code> node is to be copied, or null if the source's 062 * default workspace is to be used 063 * @throws IllegalArgumentException if any of the parameters are null 064 */ 065 public CopyBranchRequest( Location from, 066 String fromWorkspace, 067 Location into, 068 String intoWorkspace ) { 069 this(from, fromWorkspace, into, intoWorkspace, null, DEFAULT_CONFLICT_BEHAVIOR); 070 } 071 072 /** 073 * Create a request to copy a branch to another. 074 * 075 * @param from the location of the top node in the existing branch that is to be copied 076 * @param fromWorkspace the name of the workspace where the <code>from</code> node exists 077 * @param into the location of the existing node into which the copy should be placed 078 * @param intoWorkspace the name of the workspace where the <code>into</code> node is to be copied 079 * @param nameForCopy the desired name for the node that results from the copy, or null if the name of the original should be 080 * used 081 * @throws IllegalArgumentException if any of the parameters are null 082 */ 083 public CopyBranchRequest( Location from, 084 String fromWorkspace, 085 Location into, 086 String intoWorkspace, 087 Name nameForCopy ) { 088 this(from, fromWorkspace, into, intoWorkspace, nameForCopy, DEFAULT_CONFLICT_BEHAVIOR); 089 } 090 091 /** 092 * Create a request to copy a branch to another. 093 * 094 * @param from the location of the top node in the existing branch that is to be copied 095 * @param fromWorkspace the name of the workspace where the <code>from</code> node exists 096 * @param into the location of the existing node into which the copy should be placed 097 * @param intoWorkspace the name of the workspace where the <code>into</code> node is to be copied 098 * @param nameForCopy the desired name for the node that results from the copy, or null if the name of the original should be 099 * used 100 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 101 * location 102 * @throws IllegalArgumentException if any of the parameters are null 103 */ 104 public CopyBranchRequest( Location from, 105 String fromWorkspace, 106 Location into, 107 String intoWorkspace, 108 Name nameForCopy, 109 NodeConflictBehavior conflictBehavior ) { 110 CheckArg.isNotNull(from, "from"); 111 CheckArg.isNotNull(into, "into"); 112 CheckArg.isNotNull(fromWorkspace, "fromWorkspace"); 113 CheckArg.isNotNull(intoWorkspace, "intoWorkspace"); 114 CheckArg.isNotNull(conflictBehavior, "conflictBehavior"); 115 this.from = from; 116 this.into = into; 117 this.fromWorkspace = fromWorkspace; 118 this.intoWorkspace = intoWorkspace; 119 this.desiredNameForCopy = nameForCopy; 120 this.conflictBehavior = conflictBehavior; 121 } 122 123 /** 124 * Get the location defining the top of the branch to be copied 125 * 126 * @return the from location; never null 127 */ 128 public Location from() { 129 return from; 130 } 131 132 /** 133 * Get the location defining the parent where the new copy is to be placed 134 * 135 * @return the to location; never null 136 */ 137 public Location into() { 138 return into; 139 } 140 141 /** 142 * Get the name of the workspace containing the branch to be copied. 143 * 144 * @return the name of the workspace containing the branch to be copied; never null 145 */ 146 public String fromWorkspace() { 147 return fromWorkspace; 148 } 149 150 /** 151 * Get the name of the workspace where the copy is to be placed 152 * 153 * @return the name of the workspace where the copy is to be placed; never null 154 */ 155 public String intoWorkspace() { 156 return intoWorkspace; 157 } 158 159 /** 160 * Determine whether this copy operation is within the same workspace. 161 * 162 * @return true if this operation is to be performed within the same workspace, or false if the workspace of the 163 * {@link #from() original} is different than that of the {@link #into() copy} 164 */ 165 public boolean isSameWorkspace() { 166 return fromWorkspace.equals(intoWorkspace); 167 } 168 169 /** 170 * Get the name of the copy if it is to be different than that of the original. 171 * 172 * @return the desired name of the copy, or null if the name of the original is to be used 173 */ 174 public Name desiredName() { 175 return desiredNameForCopy; 176 } 177 178 /** 179 * {@inheritDoc} 180 * 181 * @see org.jboss.dna.graph.request.Request#isReadOnly() 182 */ 183 @Override 184 public boolean isReadOnly() { 185 return false; 186 } 187 188 /** 189 * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same 190 * name. 191 * 192 * @return the behavior specification 193 */ 194 public NodeConflictBehavior conflictBehavior() { 195 return conflictBehavior; 196 } 197 198 /** 199 * Sets the actual and complete location of the node being renamed and its new location. This method must be called when 200 * processing the request, and the actual location must have a {@link Location#getPath() path}. 201 * 202 * @param fromLocation the actual location of the node being copied 203 * @param intoLocation the actual location of the new copy of the node 204 * @throws IllegalArgumentException if the either location is null; if the old location does not represent the 205 * {@link Location#isSame(Location) same location} as the {@link #from() from location}; if the new location does not 206 * represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}; if the either 207 * location does not have a path 208 * @throws IllegalStateException if the request is frozen 209 */ 210 public void setActualLocations( Location fromLocation, 211 Location intoLocation ) { 212 checkNotFrozen(); 213 if (!from.isSame(fromLocation)) { // not same if actual is null 214 throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(fromLocation, from)); 215 } 216 CheckArg.isNotNull(intoLocation, "intoLocation"); 217 assert fromLocation != null; 218 assert intoLocation != null; 219 if (!fromLocation.hasPath()) { 220 throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(fromLocation)); 221 } 222 if (!intoLocation.hasPath()) { 223 throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(intoLocation)); 224 } 225 // The 'into' should be the parent of the 'newLocation' ... 226 if (into.hasPath() && !intoLocation.getPath().getParent().equals(into.getPath())) { 227 throw new IllegalArgumentException(GraphI18n.actualLocationIsNotChildOfInputLocation.text(intoLocation, into)); 228 } 229 this.actualFromLocation = fromLocation; 230 this.actualIntoLocation = intoLocation; 231 } 232 233 /** 234 * Get the actual location of the node before being copied. 235 * 236 * @return the actual location of the node before being moved, or null if the actual location was not set 237 */ 238 public Location getActualLocationBefore() { 239 return actualFromLocation; 240 } 241 242 /** 243 * Get the actual location of the node after being copied. 244 * 245 * @return the actual location of the node after being copied, or null if the actual location was not set 246 */ 247 public Location getActualLocationAfter() { 248 return actualIntoLocation; 249 } 250 251 /** 252 * {@inheritDoc} 253 * 254 * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path) 255 */ 256 @Override 257 public boolean changes( String workspace, 258 Path path ) { 259 return this.intoWorkspace.equals(workspace) && into.hasPath() && into.getPath().isAtOrBelow(path); 260 } 261 262 /** 263 * {@inheritDoc} 264 * 265 * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation() 266 */ 267 @Override 268 public Location changedLocation() { 269 return into; 270 } 271 272 /** 273 * {@inheritDoc} 274 * 275 * @see org.jboss.dna.graph.request.ChangeRequest#changedWorkspace() 276 */ 277 @Override 278 public String changedWorkspace() { 279 return intoWorkspace(); 280 } 281 282 /** 283 * {@inheritDoc} 284 * 285 * @see java.lang.Object#hashCode() 286 */ 287 @Override 288 public int hashCode() { 289 return HashCode.compute(from, fromWorkspace, into, intoWorkspace); 290 } 291 292 /** 293 * {@inheritDoc} 294 * 295 * @see org.jboss.dna.graph.request.Request#cancel() 296 */ 297 @Override 298 public void cancel() { 299 super.cancel(); 300 this.actualFromLocation = null; 301 this.actualIntoLocation = null; 302 } 303 304 /** 305 * {@inheritDoc} 306 * 307 * @see java.lang.Object#equals(java.lang.Object) 308 */ 309 @Override 310 public boolean equals( Object obj ) { 311 if (obj == this) return true; 312 if (this.getClass().isInstance(obj)) { 313 CopyBranchRequest that = (CopyBranchRequest)obj; 314 if (!this.from().equals(that.from())) return false; 315 if (!this.into().equals(that.into())) return false; 316 if (!this.conflictBehavior().equals(that.conflictBehavior())) return false; 317 if (!this.fromWorkspace.equals(that.fromWorkspace)) return false; 318 if (!this.intoWorkspace.equals(that.intoWorkspace)) return false; 319 return true; 320 } 321 return false; 322 } 323 324 /** 325 * {@inheritDoc} 326 * 327 * @see java.lang.Object#toString() 328 */ 329 @Override 330 public String toString() { 331 if (fromWorkspace.equals(intoWorkspace)) { 332 if (desiredNameForCopy != null) { 333 return "copy branch " + from() + " in the \"" + fromWorkspace + "\" workspace into " + into() + " with name " 334 + desiredNameForCopy; 335 } 336 return "copy branch " + from() + " in the \"" + fromWorkspace + "\" workspace into " + into(); 337 } 338 if (desiredNameForCopy != null) { 339 return "copy branch " + from() + " in the \"" + fromWorkspace + "\" workspace into " + into() + " with name " 340 + desiredNameForCopy + " in the \"" + intoWorkspace + "\" workspace"; 341 } 342 return "copy branch " + from() + " in the \"" + fromWorkspace + "\" workspace into " + into() + " in the \"" 343 + intoWorkspace + "\" workspace"; 344 } 345 }