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