View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.request;
25  
26  import java.util.Collection;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.LinkedList;
30  import java.util.List;
31  import java.util.Map;
32  import org.modeshape.common.util.CheckArg;
33  import org.modeshape.common.util.HashCode;
34  import org.modeshape.graph.GraphI18n;
35  import org.modeshape.graph.Location;
36  import org.modeshape.graph.connector.RepositoryConnection;
37  import org.modeshape.graph.property.Name;
38  import org.modeshape.graph.property.Path;
39  import org.modeshape.graph.property.Property;
40  
41  /**
42   * Instruction to read the properties and children of the node at the specifed location.
43   */
44  public class ReadNodeRequest extends CacheableRequest implements Iterable<Location> {
45  
46      private static final long serialVersionUID = 1L;
47  
48      private final Location at;
49      private final String workspaceName;
50      private final Map<Name, Property> properties = new HashMap<Name, Property>();
51      private final List<Location> children = new LinkedList<Location>();
52      private Location actualLocation;
53  
54      /**
55       * Create a request to read the properties and number of children of a node at the supplied location.
56       * 
57       * @param at the location of the node to be read
58       * @param workspaceName the name of the workspace containing the node
59       * @throws IllegalArgumentException if the location or workspace name is null
60       */
61      public ReadNodeRequest( Location at,
62                              String workspaceName ) {
63          CheckArg.isNotNull(at, "at");
64          CheckArg.isNotNull(workspaceName, "workspaceName");
65          this.workspaceName = workspaceName;
66          this.at = at;
67      }
68  
69      /**
70       * {@inheritDoc}
71       * 
72       * @see org.modeshape.graph.request.Request#isReadOnly()
73       */
74      @Override
75      public boolean isReadOnly() {
76          return true;
77      }
78  
79      /**
80       * Get the location defining the node that is to be read.
81       * 
82       * @return the location of the node; never null
83       */
84      public Location at() {
85          return at;
86      }
87  
88      /**
89       * Get the name of the workspace in which the node exists.
90       * 
91       * @return the name of the workspace; never null
92       */
93      public String inWorkspace() {
94          return workspaceName;
95      }
96  
97      /**
98       * Get the properties that were read from the {@link RepositoryConnection}.
99       * 
100      * @return the properties, as a map of property name to property; never null
101      */
102     public Map<Name, Property> getPropertiesByName() {
103         return properties;
104     }
105 
106     /**
107      * Get the properties that were read from the {@link RepositoryConnection}.
108      * 
109      * @return the collection of properties; never null
110      */
111     public Collection<Property> getProperties() {
112         return properties.values();
113     }
114 
115     /**
116      * Add a property that was read from the {@link RepositoryConnection}
117      * 
118      * @param property the property that was read
119      * @return the previous property that had the same name, or null if there was no previously-recorded property with the same
120      *         name
121      * @throws IllegalArgumentException if the property is null
122      * @throws IllegalStateException if the request is frozen
123      */
124     public Property addProperty( Property property ) {
125         checkNotFrozen();
126         return this.properties.put(property.getName(), property);
127     }
128 
129     /**
130      * Add a property that was read from the {@link RepositoryConnection}
131      * 
132      * @param properties the properties that were read
133      * @throws IllegalArgumentException if the properties array is null
134      * @throws IllegalStateException if the request is frozen
135      */
136     public void addProperties( Property... properties ) {
137         checkNotFrozen();
138         CheckArg.isNotNull(properties, "properties");
139         for (Property property : properties) {
140             this.properties.put(property.getName(), property);
141         }
142     }
143 
144     /**
145      * Add a property that was read from the {@link RepositoryConnection}
146      * 
147      * @param properties the properties that were read
148      * @throws IllegalArgumentException if the iterable reference is null
149      * @throws IllegalStateException if the request is frozen
150      */
151     public void addProperties( Iterable<Property> properties ) {
152         checkNotFrozen();
153         CheckArg.isNotNull(properties, "properties");
154         for (Property property : properties) {
155             this.properties.put(property.getName(), property);
156         }
157     }
158 
159     /**
160      * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
161      * represented by a location.
162      * 
163      * @return the children that were read; never null
164      */
165     public List<Location> getChildren() {
166         return children;
167     }
168 
169     /**
170      * {@inheritDoc}
171      * 
172      * @see java.lang.Iterable#iterator()
173      */
174     public Iterator<Location> iterator() {
175         return children.iterator();
176     }
177 
178     /**
179      * Add to the list of children that has been read the supplied children with the given path and identification properties. The
180      * children are added in order.
181      * 
182      * @param children the locations of the children that were read
183      * @throws IllegalArgumentException if the parameter is null
184      * @throws IllegalStateException if the request is frozen
185      * @see #addChild(Location)
186      * @see #addChild(Path, Property)
187      * @see #addChild(Path, Property, Property...)
188      */
189     public void addChildren( Iterable<Location> children ) {
190         checkNotFrozen();
191         CheckArg.isNotNull(children, "children");
192         for (Location child : children) {
193             if (child != null) this.children.add(child);
194         }
195     }
196 
197     /**
198      * Add to the list of children that has been read the child with the given path and identification properties. The children
199      * should be added in order.
200      * 
201      * @param child the location of the child that was read
202      * @throws IllegalArgumentException if the location is null
203      * @throws IllegalStateException if the request is frozen
204      * @see #addChild(Path, Property)
205      * @see #addChild(Path, Property, Property...)
206      */
207     public void addChild( Location child ) {
208         checkNotFrozen();
209         CheckArg.isNotNull(child, "child");
210         this.children.add(child);
211     }
212 
213     /**
214      * Add to the list of children that has been read the child with the given path and identification properties. The children
215      * should be added in order.
216      * 
217      * @param pathToChild the path of the child that was just read
218      * @param firstIdProperty the first identification property of the child that was just read
219      * @param remainingIdProperties the remaining identification properties of the child that was just read
220      * @throws IllegalArgumentException if the path or identification properties are null
221      * @throws IllegalStateException if the request is frozen
222      * @see #addChild(Location)
223      * @see #addChild(Path, Property)
224      */
225     public void addChild( Path pathToChild,
226                           Property firstIdProperty,
227                           Property... remainingIdProperties ) {
228         checkNotFrozen();
229         Location child = Location.create(pathToChild, firstIdProperty, remainingIdProperties);
230         this.children.add(child);
231     }
232 
233     /**
234      * Add to the list of children that has been read the child with the given path and identification property. The children
235      * should be added in order.
236      * 
237      * @param pathToChild the path of the child that was just read
238      * @param idProperty the identification property of the child that was just read
239      * @throws IllegalArgumentException if the path or identification properties are null
240      * @throws IllegalStateException if the request is frozen
241      * @see #addChild(Location)
242      * @see #addChild(Path, Property, Property...)
243      */
244     public void addChild( Path pathToChild,
245                           Property idProperty ) {
246         checkNotFrozen();
247         Location child = Location.create(pathToChild, idProperty);
248         this.children.add(child);
249     }
250 
251     /**
252      * Sets the actual and complete location of the node whose children and properties have been read. This method must be called
253      * when processing the request, and the actual location must have a {@link Location#getPath() path}.
254      * 
255      * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
256      * @throws IllegalArgumentException if the actual location is null or does not have a path.
257      * @throws IllegalStateException if the request is frozen
258      */
259     public void setActualLocationOfNode( Location actual ) {
260         checkNotFrozen();
261         CheckArg.isNotNull(actual, "actual");
262         if (!actual.hasPath()) {
263             throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
264         }
265         this.actualLocation = actual;
266     }
267 
268     /**
269      * Get the actual location of the node whose children and properties were read.
270      * 
271      * @return the actual location, or null if the actual location was not set
272      */
273     public Location getActualLocationOfNode() {
274         return actualLocation;
275     }
276 
277     /**
278      * {@inheritDoc}
279      * 
280      * @see org.modeshape.graph.request.Request#cancel()
281      */
282     @Override
283     public void cancel() {
284         super.cancel();
285         this.actualLocation = null;
286         this.children.clear();
287         this.properties.clear();
288     }
289 
290     /**
291      * {@inheritDoc}
292      * 
293      * @see java.lang.Object#hashCode()
294      */
295     @Override
296     public int hashCode() {
297         return HashCode.compute(at, workspaceName);
298     }
299 
300     /**
301      * {@inheritDoc}
302      * 
303      * @see java.lang.Object#equals(java.lang.Object)
304      */
305     @Override
306     public boolean equals( Object obj ) {
307         if (obj == this) return true;
308         if (this.getClass().isInstance(obj)) {
309             ReadNodeRequest that = (ReadNodeRequest)obj;
310             if (!this.at().isSame(that.at())) return false;
311             if (!this.inWorkspace().equals(that.inWorkspace())) return false;
312             return true;
313         }
314         return false;
315     }
316 
317     /**
318      * {@inheritDoc}
319      * 
320      * @see java.lang.Object#toString()
321      */
322     @Override
323     public String toString() {
324         return "read node at " + at() + " in the \"" + workspaceName + "\" workspace";
325     }
326 
327     @Override
328     public RequestType getType() {
329         return RequestType.READ_NODE;
330     }
331 }