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