1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.graph.request;
25
26 import java.util.Arrays;
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 java.util.NoSuchElementException;
33 import net.jcip.annotations.NotThreadSafe;
34 import org.modeshape.common.util.CheckArg;
35 import org.modeshape.common.util.HashCode;
36 import org.modeshape.graph.GraphI18n;
37 import org.modeshape.graph.Location;
38 import org.modeshape.graph.connector.RepositoryConnection;
39 import org.modeshape.graph.property.Name;
40 import org.modeshape.graph.property.Path;
41 import org.modeshape.graph.property.Property;
42
43
44
45
46
47 @NotThreadSafe
48 public class ReadBranchRequest extends CacheableRequest implements Iterable<Location> {
49
50 private static final long serialVersionUID = 1L;
51
52 public static final int DEFAULT_MAXIMUM_DEPTH = 2;
53 public static final int NO_MAXIMUM_DEPTH = Integer.MAX_VALUE;
54
55 private static class Node {
56 private final Location location;
57 private final Map<Name, Property> properties = new HashMap<Name, Property>();
58 private List<Location> children;
59
60 protected Node( Location location ) {
61 assert location != null;
62 this.location = location;
63 }
64
65 protected Location getLocation() {
66 return location;
67 }
68
69 protected Map<Name, Property> getProperties() {
70 return properties;
71 }
72
73 protected List<Location> getChildren() {
74 return children;
75 }
76
77 protected void setChildren( List<Location> children ) {
78 this.children = children;
79 }
80 }
81
82 private final Location at;
83 private final String workspaceName;
84 private final int maxDepth;
85 private final Map<Path, Node> nodes = new HashMap<Path, Node>();
86 private Location actualLocation;
87
88
89
90
91
92
93
94
95 public ReadBranchRequest( Location at,
96 String workspaceName ) {
97 CheckArg.isNotNull(at, "at");
98 CheckArg.isNotNull(workspaceName, "workspaceName");
99 this.workspaceName = workspaceName;
100 this.at = at;
101 this.maxDepth = DEFAULT_MAXIMUM_DEPTH;
102 }
103
104
105
106
107
108
109
110
111
112 public ReadBranchRequest( Location at,
113 String workspaceName,
114 int maxDepth ) {
115 CheckArg.isNotNull(at, "at");
116 CheckArg.isPositive(maxDepth, "maxDepth");
117 CheckArg.isNotNull(workspaceName, "workspaceName");
118 this.workspaceName = workspaceName;
119 this.at = at;
120 this.maxDepth = maxDepth;
121 }
122
123
124
125
126
127
128 @Override
129 public boolean isReadOnly() {
130 return true;
131 }
132
133
134
135
136
137
138 public Location at() {
139 return at;
140 }
141
142
143
144
145
146
147 public String inWorkspace() {
148 return workspaceName;
149 }
150
151
152
153
154
155
156 public int maximumDepth() {
157 return maxDepth;
158 }
159
160
161
162
163
164
165
166 public boolean includes( Location location ) {
167 if (location == null || !location.hasPath()) return false;
168 return this.nodes.containsKey(location.getPath());
169 }
170
171
172
173
174
175
176
177 public boolean includes( Path path ) {
178 if (path == null) return false;
179 return this.nodes.containsKey(path);
180 }
181
182
183
184
185
186
187
188 public Location getLocationFor( Path path ) {
189 Node node = nodes.get(path);
190 return node != null ? node.getLocation() : null;
191 }
192
193
194
195
196
197
198
199
200
201
202 public void setProperties( Location node,
203 Property... properties ) {
204 checkNotFrozen();
205 CheckArg.isNotNull(node, "node");
206 assert node.hasPath();
207 Node nodeObj = nodes.get(node.getPath());
208 if (nodeObj == null) {
209 nodeObj = new Node(node);
210 nodes.put(node.getPath(), nodeObj);
211 }
212 Map<Name, Property> propertiesMap = nodeObj.getProperties();
213 for (Property property : properties) {
214 propertiesMap.put(property.getName(), property);
215 }
216 }
217
218
219
220
221
222
223
224
225
226
227 public void setProperties( Location node,
228 Iterable<Property> properties ) {
229 checkNotFrozen();
230 CheckArg.isNotNull(node, "node");
231 assert node.hasPath();
232 Node nodeObj = nodes.get(node.getPath());
233 if (nodeObj == null) {
234 nodeObj = new Node(node);
235 nodes.put(node.getPath(), nodeObj);
236 }
237 Map<Name, Property> propertiesMap = nodeObj.getProperties();
238 for (Property property : properties) {
239 propertiesMap.put(property.getName(), property);
240 }
241 }
242
243
244
245
246
247
248
249
250 public void setChildren( Location parent,
251 Location... children ) {
252 checkNotFrozen();
253 CheckArg.isNotNull(parent, "parent");
254 CheckArg.isNotNull(children, "children");
255 assert parent.hasPath();
256 Node nodeObj = nodes.get(parent.getPath());
257 if (nodeObj == null) {
258 nodeObj = new Node(parent);
259 nodes.put(parent.getPath(), nodeObj);
260 }
261 nodeObj.setChildren(Arrays.asList(children));
262 }
263
264
265
266
267
268
269
270
271 public void setChildren( Location parent,
272 List<Location> children ) {
273 checkNotFrozen();
274 CheckArg.isNotNull(parent, "parent");
275 CheckArg.isNotNull(children, "children");
276 assert parent.hasPath();
277 Node nodeObj = nodes.get(parent.getPath());
278 if (nodeObj == null) {
279 nodeObj = new Node(parent);
280 nodes.put(parent.getPath(), nodeObj);
281 }
282 nodeObj.setChildren(children);
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 public Map<Name, Property> getPropertiesFor( Location location ) {
306 if (location == null || !location.hasPath()) return null;
307 Node node = nodes.get(location.getPath());
308 return node != null ? node.getProperties() : null;
309 }
310
311
312
313
314
315
316
317 public List<Location> getChildren( Location parent ) {
318 if (parent == null || !parent.hasPath()) return null;
319 Node node = nodes.get(parent.getPath());
320 return node != null ? node.getChildren() : null;
321 }
322
323
324
325
326
327
328
329
330
331 public Iterator<Location> iterator() {
332 final LinkedList<Location> queue = new LinkedList<Location>();
333 if (getActualLocationOfNode() != null) {
334 Location actual = getActualLocationOfNode();
335 if (actual != null) queue.addFirst(getActualLocationOfNode());
336 }
337 return new Iterator<Location>() {
338 public boolean hasNext() {
339 return queue.peek() != null;
340 }
341
342 public Location next() {
343
344 Location next = queue.poll();
345 if (next == null) throw new NoSuchElementException();
346 List<Location> children = getChildren(next);
347 if (children != null && children.size() > 0) {
348
349 Location firstChild = children.get(0);
350 if (includes(firstChild)) queue.addAll(0, children);
351 }
352 return next;
353 }
354
355 public void remove() {
356 throw new UnsupportedOperationException();
357 }
358 };
359 }
360
361
362
363
364
365
366
367
368 public void setActualLocationOfNode( Location actual ) {
369 checkNotFrozen();
370 CheckArg.isNotNull(actual, "actual");
371 if (!actual.hasPath()) {
372 throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
373 }
374 this.actualLocation = actual;
375 }
376
377
378
379
380
381
382 public Location getActualLocationOfNode() {
383 return actualLocation;
384 }
385
386
387
388
389
390
391 @Override
392 public void cancel() {
393 super.cancel();
394 this.actualLocation = null;
395 this.nodes.clear();
396 }
397
398
399
400
401
402
403 @Override
404 public int hashCode() {
405 return HashCode.compute(at, workspaceName);
406 }
407
408
409
410
411
412
413 @Override
414 public boolean equals( Object obj ) {
415 if (obj == this) return true;
416 if (this.getClass().isInstance(obj)) {
417 ReadBranchRequest that = (ReadBranchRequest)obj;
418 if (!this.at().isSame(that.at())) return false;
419 if (this.maximumDepth() != that.maximumDepth()) return false;
420 if (!this.inWorkspace().equals(that.inWorkspace())) return false;
421 return true;
422 }
423 return false;
424 }
425
426
427
428
429
430
431 @Override
432 public String toString() {
433 return "read branch " + at() + " in the \"" + workspaceName + "\" workspace to depth " + maximumDepth();
434 }
435
436 @Override
437 public RequestType getType() {
438 return RequestType.READ_BRANCH;
439 }
440
441
442
443
444
445
446
447
448 public ReadBranchRequest withMaximumDepth( int maxDepth ) {
449 return new ReadBranchRequest(at, workspaceName, maxDepth);
450 }
451 }