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.repository.sequencer;
25
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import net.jcip.annotations.Immutable;
34 import net.jcip.annotations.NotThreadSafe;
35 import org.modeshape.common.util.CheckArg;
36 import org.modeshape.graph.JcrLexicon;
37 import org.modeshape.graph.property.Name;
38 import org.modeshape.graph.property.Path;
39 import org.modeshape.graph.property.PathFactory;
40 import org.modeshape.graph.property.ValueFactories;
41 import org.modeshape.graph.sequencer.SequencerOutput;
42
43
44
45
46
47 @NotThreadSafe
48 public class SequencerOutputMap implements SequencerOutput, Iterable<SequencerOutputMap.Entry> {
49
50 private final Map<Path, List<PropertyValue>> data;
51 private transient boolean valuesSorted = true;
52 private final ValueFactories factories;
53
54 public SequencerOutputMap( ValueFactories factories ) {
55 CheckArg.isNotNull(factories, "factories");
56 this.data = new HashMap<Path, List<PropertyValue>>();
57 this.factories = factories;
58 }
59
60 ValueFactories getFactories() {
61 return this.factories;
62 }
63
64
65
66
67 public void setProperty( Path nodePath,
68 Name propertyName,
69 Object... values ) {
70 CheckArg.isNotNull(nodePath, "nodePath");
71 CheckArg.isNotNull(propertyName, "property");
72
73
74 List<PropertyValue> properties = this.data.get(nodePath);
75 if (properties == null) {
76 if (values == null || values.length == 0 || (values.length == 1 && values[0] == null)) return;
77 properties = new ArrayList<PropertyValue>();
78 this.data.put(nodePath, properties);
79 }
80 if (values == null || values.length == 0 || (values.length == 1 && values[0] == null)) {
81 properties.remove(new PropertyValue(propertyName, null));
82 } else {
83 Object propValue = values.length == 1 ? values[0] : values;
84 PropertyValue value = new PropertyValue(propertyName, propValue);
85 properties.add(value);
86 valuesSorted = false;
87 }
88 }
89
90
91
92
93
94
95
96
97
98 @Deprecated
99 public void setProperty( String nodePath,
100 String property,
101 Object... values ) {
102 CheckArg.isNotEmpty(nodePath, "nodePath");
103 CheckArg.isNotEmpty(property, "property");
104 Path path = this.factories.getPathFactory().create(nodePath);
105 Name propertyName = this.factories.getNameFactory().create(property);
106 setProperty(path, propertyName, values);
107 }
108
109
110
111
112
113
114
115
116
117 @Deprecated
118 public void setReference( String nodePath,
119 String propertyName,
120 String... paths ) {
121 PathFactory pathFactory = this.factories.getPathFactory();
122 Path path = pathFactory.create(nodePath);
123 Name name = this.factories.getNameFactory().create(propertyName);
124 Object[] values = null;
125 if (paths != null && paths.length != 0) {
126 values = new Path[paths.length];
127 for (int i = 0, len = paths.length; i != len; ++i) {
128 String pathValue = paths[i];
129 values[i] = pathFactory.create(pathValue);
130 }
131 }
132 setProperty(path, name, values);
133 }
134
135
136
137
138
139
140 public int size() {
141 return this.data.size();
142 }
143
144
145
146
147
148
149 public boolean isEmpty() {
150 return this.data.isEmpty();
151 }
152
153 protected List<PropertyValue> removeProperties( Path nodePath ) {
154 return this.data.remove(nodePath);
155 }
156
157
158
159
160
161
162
163 protected List<PropertyValue> getProperties( Path nodePath ) {
164 return data.get(nodePath);
165 }
166
167
168
169
170
171
172 public Iterator<Entry> iterator() {
173 LinkedList<Path> paths = new LinkedList<Path>(data.keySet());
174 Collections.sort(paths);
175 sortValues();
176 return new EntryIterator(paths.iterator());
177 }
178
179 protected void sortValues() {
180 if (!valuesSorted) {
181 for (List<PropertyValue> values : this.data.values()) {
182 if (values.size() > 1) Collections.sort(values);
183 }
184 valuesSorted = true;
185 }
186 }
187
188
189
190
191 @Override
192 public String toString() {
193 return this.data.toString();
194 }
195
196
197
198
199
200
201
202 @Immutable
203 public class PropertyValue implements Comparable<PropertyValue> {
204
205 private final Name name;
206 private final Object value;
207
208 protected PropertyValue( Name propertyName,
209 Object value ) {
210 this.name = propertyName;
211 this.value = value;
212 }
213
214
215
216
217
218
219 public Name getName() {
220 return this.name;
221 }
222
223
224
225
226
227
228 public Object getValue() {
229 return this.value;
230 }
231
232
233
234
235 public int compareTo( PropertyValue that ) {
236 if (this == that) return 0;
237 if (this.name.equals(JcrLexicon.PRIMARY_TYPE)) return -1;
238 if (that.name.equals(JcrLexicon.PRIMARY_TYPE)) return 1;
239 return this.name.compareTo(that.name);
240 }
241
242
243
244
245 @Override
246 public int hashCode() {
247 return this.name.hashCode();
248 }
249
250
251
252
253 @Override
254 public boolean equals( Object obj ) {
255 if (obj == this) return true;
256 if (obj instanceof PropertyValue) {
257 PropertyValue that = (PropertyValue)obj;
258 if (!this.getName().equals(that.getName())) return false;
259 return true;
260 }
261 return false;
262 }
263
264
265
266
267 @Override
268 public String toString() {
269 return "[" + this.name + "=" + value + "]";
270 }
271 }
272
273
274
275
276
277
278
279 @Immutable
280 public class Entry {
281
282 private final Path path;
283 private final Name primaryType;
284 private final List<PropertyValue> properties;
285
286 protected Entry( Path path,
287 List<PropertyValue> properties ) {
288 assert path != null;
289 assert properties != null;
290 this.path = path;
291 this.properties = properties;
292 if (this.properties.size() > 0 && this.properties.get(0).getName().equals("jcr:primaryType")) {
293 PropertyValue primaryTypeProperty = this.properties.remove(0);
294 this.primaryType = getFactories().getNameFactory().create(primaryTypeProperty.getValue());
295 } else {
296 this.primaryType = null;
297 }
298 }
299
300
301
302
303 public Path getPath() {
304 return this.path;
305 }
306
307
308
309
310
311
312 public Name getPrimaryTypeValue() {
313 return this.primaryType;
314 }
315
316
317
318
319
320
321 public List<PropertyValue> getPropertyValues() {
322 return getProperties(path);
323 }
324 }
325
326 protected class EntryIterator implements Iterator<Entry> {
327
328 private Path last;
329 private final Iterator<Path> iter;
330
331 protected EntryIterator( Iterator<Path> iter ) {
332 this.iter = iter;
333 }
334
335
336
337
338 public boolean hasNext() {
339 return iter.hasNext();
340 }
341
342
343
344
345 public Entry next() {
346 this.last = iter.next();
347 return new Entry(last, getProperties(last));
348 }
349
350
351
352
353 public void remove() {
354 if (last == null) throw new IllegalStateException();
355 try {
356 removeProperties(last);
357 } finally {
358 last = null;
359 }
360 }
361 }
362
363 }