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 java.util.Collection; 027 import java.util.HashMap; 028 import java.util.Iterator; 029 import java.util.LinkedList; 030 import java.util.List; 031 import java.util.Map; 032 import org.jboss.dna.common.util.CheckArg; 033 import org.jboss.dna.graph.GraphI18n; 034 import org.jboss.dna.graph.Location; 035 import org.jboss.dna.graph.connector.RepositoryConnection; 036 import org.jboss.dna.graph.property.Name; 037 import org.jboss.dna.graph.property.Path; 038 import org.jboss.dna.graph.property.Property; 039 040 /** 041 * Instruction to read the properties and children of the node at the specifed location. 042 * 043 * @author Randall Hauch 044 */ 045 public class ReadNodeRequest extends CacheableRequest implements Iterable<Location> { 046 047 private static final long serialVersionUID = 1L; 048 049 private final Location at; 050 private final String workspaceName; 051 private final Map<Name, Property> properties = new HashMap<Name, Property>(); 052 private final List<Location> children = new LinkedList<Location>(); 053 private Location actualLocation; 054 055 /** 056 * Create a request to read the properties and number of children of a node at the supplied location. 057 * 058 * @param at the location of the node to be read 059 * @param workspaceName the name of the workspace containing the node 060 * @throws IllegalArgumentException if the location or workspace name is null 061 */ 062 public ReadNodeRequest( Location at, 063 String workspaceName ) { 064 CheckArg.isNotNull(at, "at"); 065 CheckArg.isNotNull(workspaceName, "workspaceName"); 066 this.workspaceName = workspaceName; 067 this.at = at; 068 } 069 070 /** 071 * {@inheritDoc} 072 * 073 * @see org.jboss.dna.graph.request.Request#isReadOnly() 074 */ 075 @Override 076 public boolean isReadOnly() { 077 return true; 078 } 079 080 /** 081 * Get the location defining the node that is to be read. 082 * 083 * @return the location of the node; never null 084 */ 085 public Location at() { 086 return at; 087 } 088 089 /** 090 * Get the name of the workspace in which the node exists. 091 * 092 * @return the name of the workspace; never null 093 */ 094 public String inWorkspace() { 095 return workspaceName; 096 } 097 098 /** 099 * Get the properties that were read from the {@link RepositoryConnection}. 100 * 101 * @return the properties, as a map of property name to property; never null 102 */ 103 public Map<Name, Property> getPropertiesByName() { 104 return properties; 105 } 106 107 /** 108 * Get the properties that were read from the {@link RepositoryConnection}. 109 * 110 * @return the collection of properties; never null 111 */ 112 public Collection<Property> getProperties() { 113 return properties.values(); 114 } 115 116 /** 117 * Add a property that was read from the {@link RepositoryConnection} 118 * 119 * @param property the property that was read 120 * @return the previous property that had the same name, or null if there was no previously-recorded property with the same 121 * name 122 * @throws IllegalArgumentException if the property is null 123 */ 124 public Property addProperty( Property property ) { 125 return this.properties.put(property.getName(), property); 126 } 127 128 /** 129 * Add a property that was read from the {@link RepositoryConnection} 130 * 131 * @param properties the properties that were read 132 * @throws IllegalArgumentException if the property is null 133 */ 134 public void addProperties( Property... properties ) { 135 for (Property property : properties) { 136 this.properties.put(property.getName(), property); 137 } 138 } 139 140 /** 141 * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is 142 * represented by a location. 143 * 144 * @return the children that were read; never null 145 */ 146 public List<Location> getChildren() { 147 return children; 148 } 149 150 /** 151 * {@inheritDoc} 152 * 153 * @see java.lang.Iterable#iterator() 154 */ 155 public Iterator<Location> iterator() { 156 return children.iterator(); 157 } 158 159 /** 160 * Add to the list of children that has been read the child with the given path and identification properties. The children 161 * should be added in order. 162 * 163 * @param child the location of the child that was read 164 * @throws IllegalArgumentException if the location is null 165 * @see #addChild(Path, Property) 166 * @see #addChild(Path, Property, Property...) 167 */ 168 public void addChild( Location child ) { 169 CheckArg.isNotNull(child, "child"); 170 this.children.add(child); 171 } 172 173 /** 174 * Add to the list of children that has been read the child with the given path and identification properties. The children 175 * should be added in order. 176 * 177 * @param pathToChild the path of the child that was just read 178 * @param firstIdProperty the first identification property of the child that was just read 179 * @param remainingIdProperties the remaining identification properties of the child that was just read 180 * @throws IllegalArgumentException if the path or identification properties are null 181 * @see #addChild(Location) 182 * @see #addChild(Path, Property) 183 */ 184 public void addChild( Path pathToChild, 185 Property firstIdProperty, 186 Property... remainingIdProperties ) { 187 Location child = Location.create(pathToChild, firstIdProperty, remainingIdProperties); 188 this.children.add(child); 189 } 190 191 /** 192 * Add to the list of children that has been read the child with the given path and identification property. The children 193 * should be added in order. 194 * 195 * @param pathToChild the path of the child that was just read 196 * @param idProperty the identification property of the child that was just read 197 * @throws IllegalArgumentException if the path or identification properties are null 198 * @see #addChild(Location) 199 * @see #addChild(Path, Property, Property...) 200 */ 201 public void addChild( Path pathToChild, 202 Property idProperty ) { 203 Location child = Location.create(pathToChild, idProperty); 204 this.children.add(child); 205 } 206 207 /** 208 * Sets the actual and complete location of the node whose children and properties have been read. This method must be called 209 * when processing the request, and the actual location must have a {@link Location#getPath() path}. 210 * 211 * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used 212 * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same 213 * location} as the {@link #at() current location}, or if the actual location does not have a path. 214 */ 215 public void setActualLocationOfNode( Location actual ) { 216 if (!at.isSame(actual)) { // not same if actual is null 217 throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at)); 218 } 219 assert actual != null; 220 if (!actual.hasPath()) { 221 throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual)); 222 } 223 this.actualLocation = actual; 224 } 225 226 /** 227 * Get the actual location of the node whose children and properties were read. 228 * 229 * @return the actual location, or null if the actual location was not set 230 */ 231 public Location getActualLocationOfNode() { 232 return actualLocation; 233 } 234 235 /** 236 * {@inheritDoc} 237 * 238 * @see java.lang.Object#equals(java.lang.Object) 239 */ 240 @Override 241 public boolean equals( Object obj ) { 242 if (obj == this) return true; 243 if (this.getClass().isInstance(obj)) { 244 ReadNodeRequest that = (ReadNodeRequest)obj; 245 if (!this.at().equals(that.at())) return false; 246 if (!this.inWorkspace().equals(that.inWorkspace())) return false; 247 return true; 248 } 249 return false; 250 } 251 252 /** 253 * {@inheritDoc} 254 * 255 * @see java.lang.Object#toString() 256 */ 257 @Override 258 public String toString() { 259 return "read node at " + at() + " in the \"" + workspaceName + "\" workspace"; 260 } 261 262 }