001 /* 002 * JBoss, Home of Professional Open Source. 003 * Copyright 2008, Red Hat Middleware LLC, and individual contributors 004 * as indicated by the @author tags. See the copyright.txt file in the 005 * distribution for a full listing of individual contributors. 006 * 007 * This is free software; you can redistribute it and/or modify it 008 * under the terms of the GNU Lesser General Public License as 009 * published by the Free Software Foundation; either version 2.1 of 010 * the License, or (at your option) any later version. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022 package org.jboss.dna.graph.requests; 023 024 import java.util.ArrayList; 025 import java.util.Collection; 026 import java.util.Collections; 027 import java.util.Iterator; 028 import java.util.LinkedList; 029 import java.util.List; 030 import org.jboss.dna.common.util.CheckArg; 031 import org.jboss.dna.graph.GraphI18n; 032 import org.jboss.dna.graph.Location; 033 import org.jboss.dna.graph.NodeConflictBehavior; 034 import org.jboss.dna.graph.properties.Property; 035 036 /** 037 * Instruction to create the node at the specified location. This command will create the node and set the initial properties. 038 * 039 * @author Randall Hauch 040 */ 041 public class CreateNodeRequest extends Request implements Iterable<Property> { 042 043 private static final long serialVersionUID = 1L; 044 045 public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND; 046 047 private final Location at; 048 private final List<Property> properties; 049 private final NodeConflictBehavior conflictBehavior; 050 private Location actualLocation; 051 052 /** 053 * Create a request to create a node with the given properties at the supplied location. 054 * 055 * @param at the location of the node to be read 056 * @param properties the properties of the new node, which should not include the location's 057 * {@link Location#getIdProperties() identification properties} 058 * @throws IllegalArgumentException if the location is null 059 */ 060 public CreateNodeRequest( Location at, 061 Property... properties ) { 062 this(at, DEFAULT_CONFLICT_BEHAVIOR, properties); 063 } 064 065 /** 066 * Create a request to create a node with the given properties at the supplied location. 067 * 068 * @param at the location of the node to be read 069 * @param properties the properties of the new node, which should not include the location's 070 * {@link Location#getIdProperties() identification properties} 071 * @throws IllegalArgumentException if the location is null 072 */ 073 public CreateNodeRequest( Location at, 074 Iterable<Property> properties ) { 075 this(at, DEFAULT_CONFLICT_BEHAVIOR, properties); 076 } 077 078 /** 079 * Create a request to create a node with the given properties at the supplied location. 080 * 081 * @param at the location of the node to be read 082 * @param properties the properties of the new node, which should not include the location's 083 * {@link Location#getIdProperties() identification properties} 084 * @throws IllegalArgumentException if the location is null 085 */ 086 public CreateNodeRequest( Location at, 087 Iterator<Property> properties ) { 088 this(at, DEFAULT_CONFLICT_BEHAVIOR, properties); 089 } 090 091 /** 092 * Create a request to create a node with the given properties at the supplied location. 093 * 094 * @param at the location of the node to be read 095 * @param properties the properties of the new node, which should not include the location's 096 * {@link Location#getIdProperties() identification properties} 097 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 098 * location 099 * @throws IllegalArgumentException if the location or the conflict behavior is null 100 */ 101 public CreateNodeRequest( Location at, 102 NodeConflictBehavior conflictBehavior, 103 Property... properties ) { 104 CheckArg.isNotNull(at, "at"); 105 CheckArg.isNotNull(conflictBehavior, "conflictBehavior"); 106 this.at = at; 107 this.conflictBehavior = conflictBehavior; 108 int number = properties.length + (at.hasIdProperties() ? at.getIdProperties().size() : 0); 109 List<Property> props = new ArrayList<Property>(number); 110 for (Property property : properties) { 111 if (property != null) props.add(property); 112 } 113 // Add in the location properties ... 114 if (at.hasIdProperties()) { 115 for (Property property : at.getIdProperties()) { 116 if (property != null) props.add(property); 117 } 118 } 119 this.properties = Collections.unmodifiableList(props); 120 } 121 122 /** 123 * Create a request to create a node with the given properties at the supplied location. 124 * 125 * @param at the location of the node to be read 126 * @param properties the properties of the new node, which should not include the location's 127 * {@link Location#getIdProperties() identification properties} 128 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 129 * location 130 * @throws IllegalArgumentException if the location or the conflict behavior is null 131 */ 132 public CreateNodeRequest( Location at, 133 NodeConflictBehavior conflictBehavior, 134 Iterable<Property> properties ) { 135 CheckArg.isNotNull(at, "at"); 136 CheckArg.isNotNull(conflictBehavior, "conflictBehavior"); 137 this.at = at; 138 this.conflictBehavior = conflictBehavior; 139 List<Property> props = new LinkedList<Property>(); 140 for (Property property : properties) { 141 if (property != null) props.add(property); 142 } 143 // Add in the location properties ... 144 if (at.hasIdProperties()) { 145 for (Property property : at.getIdProperties()) { 146 if (property != null) props.add(property); 147 } 148 } 149 this.properties = Collections.unmodifiableList(props); 150 } 151 152 /** 153 * Create a request to create a node with the given properties at the supplied location. 154 * 155 * @param at the location of the node to be read 156 * @param properties the properties of the new node, which should not include the location's 157 * {@link Location#getIdProperties() identification properties} 158 * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code> 159 * location 160 * @throws IllegalArgumentException if the location or the conflict behavior is null 161 */ 162 public CreateNodeRequest( Location at, 163 NodeConflictBehavior conflictBehavior, 164 Iterator<Property> properties ) { 165 CheckArg.isNotNull(at, "at"); 166 CheckArg.isNotNull(conflictBehavior, "conflictBehavior"); 167 this.at = at; 168 this.conflictBehavior = conflictBehavior; 169 List<Property> props = new LinkedList<Property>(); 170 while (properties.hasNext()) { 171 Property property = properties.next(); 172 if (property != null) props.add(property); 173 } 174 // Add in the location properties ... 175 if (at.hasIdProperties()) { 176 for (Property property : at.getIdProperties()) { 177 if (property != null) props.add(property); 178 } 179 } 180 this.properties = Collections.unmodifiableList(props); 181 } 182 183 /** 184 * Get the location defining the node that is to be created. 185 * 186 * @return the location of the node; never null 187 */ 188 public Location at() { 189 return at; 190 } 191 192 /** 193 * {@inheritDoc} 194 * 195 * @see java.lang.Iterable#iterator() 196 */ 197 public Iterator<Property> iterator() { 198 return this.properties.iterator(); 199 } 200 201 /** 202 * Get the properties for the node. If the node's {@link #at() location} has identification properties, the resulting 203 * properties will include the {@link Location#getIdProperties() identification properties}. 204 * 205 * @return the collection of properties; never null 206 */ 207 public Collection<Property> properties() { 208 return properties; 209 } 210 211 /** 212 * Get the expected behavior when copying the branch and the {@link #at() destination} already has a node with the same name. 213 * 214 * @return the behavior specification 215 */ 216 public NodeConflictBehavior conflictBehavior() { 217 return conflictBehavior; 218 } 219 220 /** 221 * {@inheritDoc} 222 * 223 * @see org.jboss.dna.graph.requests.Request#isReadOnly() 224 */ 225 @Override 226 public boolean isReadOnly() { 227 return false; 228 } 229 230 /** 231 * Sets the actual and complete location of the node being created. This method must be called when processing the request, 232 * and the actual location must have a {@link Location#getPath() path}. 233 * 234 * @param actual the actual location of the node being created, or null if the {@link #at() current location} should be used 235 * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same 236 * location} as the {@link #at() current location}, or if the actual location does not have a path. 237 */ 238 public void setActualLocationOfNode( Location actual ) { 239 if (!at.isSame(actual, false)) { // not same if actual is null 240 throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at)); 241 } 242 assert actual != null; 243 if (!actual.hasPath()) { 244 throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual)); 245 } 246 this.actualLocation = actual; 247 } 248 249 /** 250 * Get the actual location of the node that was created. 251 * 252 * @return the actual location, or null if the actual location was not set 253 */ 254 public Location getActualLocationOfNode() { 255 return actualLocation; 256 } 257 258 /** 259 * {@inheritDoc} 260 * 261 * @see java.lang.Object#equals(java.lang.Object) 262 */ 263 @Override 264 public boolean equals( Object obj ) { 265 if (this.getClass().isInstance(obj)) { 266 CreateNodeRequest that = (CreateNodeRequest)obj; 267 if (!this.at().equals(that.at())) return false; 268 if (!this.conflictBehavior().equals(that.conflictBehavior())) return false; 269 if (!this.properties().equals(that.properties())) return false; 270 return true; 271 } 272 return false; 273 } 274 275 /** 276 * {@inheritDoc} 277 * 278 * @see java.lang.Object#toString() 279 */ 280 @Override 281 public String toString() { 282 return "create node at " + at() + " with properties " + properties(); 283 } 284 285 }