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) return;
77 properties = new ArrayList<PropertyValue>();
78 this.data.put(nodePath, properties);
79 }
80 if (values == null || values.length == 0) {
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 public void setProperty( String nodePath,
94 String property,
95 Object... values ) {
96 CheckArg.isNotEmpty(nodePath, "nodePath");
97 CheckArg.isNotEmpty(property, "property");
98 Path path = this.factories.getPathFactory().create(nodePath);
99 Name propertyName = this.factories.getNameFactory().create(property);
100 setProperty(path, propertyName, values);
101 }
102
103
104
105
106 public void setReference( String nodePath,
107 String propertyName,
108 String... paths ) {
109 PathFactory pathFactory = this.factories.getPathFactory();
110 Path path = pathFactory.create(nodePath);
111 Name name = this.factories.getNameFactory().create(propertyName);
112 Object[] values = null;
113 if (paths != null && paths.length != 0) {
114 values = new Path[paths.length];
115 for (int i = 0, len = paths.length; i != len; ++i) {
116 String pathValue = paths[i];
117 values[i] = pathFactory.create(pathValue);
118 }
119 }
120 setProperty(path, name, values);
121 }
122
123
124
125
126
127
128 public int size() {
129 return this.data.size();
130 }
131
132
133
134
135
136
137 public boolean isEmpty() {
138 return this.data.isEmpty();
139 }
140
141 protected List<PropertyValue> removeProperties( Path nodePath ) {
142 return this.data.remove(nodePath);
143 }
144
145
146
147
148
149
150
151 protected List<PropertyValue> getProperties( Path nodePath ) {
152 return data.get(nodePath);
153 }
154
155
156
157
158
159
160 public Iterator<Entry> iterator() {
161 LinkedList<Path> paths = new LinkedList<Path>(data.keySet());
162 Collections.sort(paths);
163 sortValues();
164 return new EntryIterator(paths.iterator());
165 }
166
167 protected void sortValues() {
168 if (!valuesSorted) {
169 for (List<PropertyValue> values : this.data.values()) {
170 if (values.size() > 1) Collections.sort(values);
171 }
172 valuesSorted = true;
173 }
174 }
175
176
177
178
179 @Override
180 public String toString() {
181 return this.data.toString();
182 }
183
184
185
186
187
188
189
190 @Immutable
191 public class PropertyValue implements Comparable<PropertyValue> {
192
193 private final Name name;
194 private final Object value;
195
196 protected PropertyValue( Name propertyName,
197 Object value ) {
198 this.name = propertyName;
199 this.value = value;
200 }
201
202
203
204
205
206
207 public Name getName() {
208 return this.name;
209 }
210
211
212
213
214
215
216 public Object getValue() {
217 return this.value;
218 }
219
220
221
222
223 public int compareTo( PropertyValue that ) {
224 if (this == that) return 0;
225 if (this.name.equals(JcrLexicon.PRIMARY_TYPE)) return -1;
226 if (that.name.equals(JcrLexicon.PRIMARY_TYPE)) return 1;
227 return this.name.compareTo(that.name);
228 }
229
230
231
232
233 @Override
234 public int hashCode() {
235 return this.name.hashCode();
236 }
237
238
239
240
241 @Override
242 public boolean equals( Object obj ) {
243 if (obj == this) return true;
244 if (obj instanceof PropertyValue) {
245 PropertyValue that = (PropertyValue)obj;
246 if (!this.getName().equals(that.getName())) return false;
247 return true;
248 }
249 return false;
250 }
251
252
253
254
255 @Override
256 public String toString() {
257 return "[" + this.name + "=" + value + "]";
258 }
259 }
260
261
262
263
264
265
266
267 @Immutable
268 public class Entry {
269
270 private final Path path;
271 private final Name primaryType;
272 private final List<PropertyValue> properties;
273
274 protected Entry( Path path,
275 List<PropertyValue> properties ) {
276 assert path != null;
277 assert properties != null;
278 this.path = path;
279 this.properties = properties;
280 if (this.properties.size() > 0 && this.properties.get(0).getName().equals("jcr:primaryType")) {
281 PropertyValue primaryTypeProperty = this.properties.remove(0);
282 this.primaryType = getFactories().getNameFactory().create(primaryTypeProperty.getValue());
283 } else {
284 this.primaryType = null;
285 }
286 }
287
288
289
290
291 public Path getPath() {
292 return this.path;
293 }
294
295
296
297
298
299
300 public Name getPrimaryTypeValue() {
301 return this.primaryType;
302 }
303
304
305
306
307
308
309 public List<PropertyValue> getPropertyValues() {
310 return getProperties(path);
311 }
312 }
313
314 protected class EntryIterator implements Iterator<Entry> {
315
316 private Path last;
317 private final Iterator<Path> iter;
318
319 protected EntryIterator( Iterator<Path> iter ) {
320 this.iter = iter;
321 }
322
323
324
325
326 public boolean hasNext() {
327 return iter.hasNext();
328 }
329
330
331
332
333 public Entry next() {
334 this.last = iter.next();
335 return new Entry(last, getProperties(last));
336 }
337
338
339
340
341 public void remove() {
342 if (last == null) throw new IllegalStateException();
343 try {
344 removeProperties(last);
345 } finally {
346 last = null;
347 }
348 }
349 }
350
351 }