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 not {@link Location#equals(Object) equal to} the {@link #at()
257      *         current location}, or if the actual location does not have a path.
258      * @throws IllegalStateException if the request is frozen
259      */
260     public void setActualLocationOfNode( Location actual ) {
261         checkNotFrozen();
262         if (!at.equals(actual)) { // not same if actual is null
263             throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(actual, at));
264         }
265         assert actual != null;
266         if (!actual.hasPath()) {
267             throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
268         }
269         this.actualLocation = actual;
270     }
271 
272     /**
273      * Get the actual location of the node whose children and properties were read.
274      * 
275      * @return the actual location, or null if the actual location was not set
276      */
277     public Location getActualLocationOfNode() {
278         return actualLocation;
279     }
280 
281     /**
282      * {@inheritDoc}
283      * 
284      * @see org.modeshape.graph.request.Request#cancel()
285      */
286     @Override
287     public void cancel() {
288         super.cancel();
289         this.actualLocation = null;
290         this.children.clear();
291         this.properties.clear();
292     }
293 
294     /**
295      * {@inheritDoc}
296      * 
297      * @see java.lang.Object#hashCode()
298      */
299     @Override
300     public int hashCode() {
301         return HashCode.compute(at, workspaceName);
302     }
303 
304     /**
305      * {@inheritDoc}
306      * 
307      * @see java.lang.Object#equals(java.lang.Object)
308      */
309     @Override
310     public boolean equals( Object obj ) {
311         if (obj == this) return true;
312         if (this.getClass().isInstance(obj)) {
313             ReadNodeRequest that = (ReadNodeRequest)obj;
314             if (!this.at().isSame(that.at())) return false;
315             if (!this.inWorkspace().equals(that.inWorkspace())) return false;
316             return true;
317         }
318         return false;
319     }
320 
321     /**
322      * {@inheritDoc}
323      * 
324      * @see java.lang.Object#toString()
325      */
326     @Override
327     public String toString() {
328         return "read node at " + at() + " in the \"" + workspaceName + "\" workspace";
329     }
330 
331 }