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.property;
25
26 import java.math.BigDecimal;
27 import java.net.URI;
28 import java.util.Collections;
29 import java.util.Comparator;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.UUID;
34 import org.modeshape.common.util.Base64;
35 import org.modeshape.graph.query.model.TypeSystem;
36
37
38
39
40 public class ValueTypeSystem implements TypeSystem {
41
42 private final String defaultTypeName;
43 protected final ValueFactories valueFactories;
44 protected final ValueFactory<String> stringValueFactory;
45 private final Map<PropertyType, TypeFactory<?>> typeFactoriesByPropertyType;
46 private final Map<String, TypeFactory<?>> typeFactoriesByName;
47 private final Map<String, PropertyType> propertyTypeByName;
48 private final TypeFactory<String> stringFactory;
49 private final TypeFactory<Boolean> booleanFactory;
50 private final TypeFactory<Long> longFactory;
51 private final TypeFactory<Double> doubleFactory;
52 private final TypeFactory<BigDecimal> decimalFactory;
53 private final TypeFactory<?> dateFactory;
54 private final TypeFactory<?> pathFactory;
55 private final TypeFactory<?> referenceFactory;
56 private final TypeFactory<?> binaryFactory;
57
58
59
60
61
62
63
64 public ValueTypeSystem( ValueFactories valueFactories ) {
65 this.valueFactories = valueFactories;
66 this.defaultTypeName = PropertyType.STRING.getName().toUpperCase();
67 Map<PropertyType, TypeFactory<?>> factories = new HashMap<PropertyType, TypeFactory<?>>();
68 this.stringValueFactory = valueFactories.getStringFactory();
69 this.stringFactory = new Factory<String>(stringValueFactory) {
70
71
72
73
74
75 @Override
76 public String asString( Object value ) {
77 return stringValueFactory.create(value);
78 }
79
80
81
82
83
84
85 @Override
86 public String asReadableString( Object value ) {
87 return stringValueFactory.create(value);
88 }
89 };
90 this.booleanFactory = new Factory<Boolean>(valueFactories.getBooleanFactory());
91 this.longFactory = new Factory<Long>(valueFactories.getLongFactory());
92 this.doubleFactory = new Factory<Double>(valueFactories.getDoubleFactory());
93 this.decimalFactory = new Factory<BigDecimal>(valueFactories.getDecimalFactory());
94 this.dateFactory = new Factory<DateTime>(valueFactories.getDateFactory()) {
95
96
97
98
99
100
101 @Override
102 public DateTime create( String value ) throws ValueFormatException {
103 DateTime result = valueFactory.create(value);
104
105 return result.toUtcTimeZone();
106 }
107 };
108 this.pathFactory = new Factory<Path>(valueFactories.getPathFactory());
109 this.referenceFactory = new Factory<Reference>(valueFactories.getReferenceFactory());
110 this.binaryFactory = new Factory<Binary>(valueFactories.getBinaryFactory()) {
111
112
113
114
115
116 @Override
117 public String asReadableString( Object value ) {
118 Binary binary = this.valueFactory.create(value);
119
120 return "(Binary,length=" + binary.getSize() + ",SHA1=" + Base64.encodeBytes(binary.getHash()) + ")";
121 }
122
123
124
125
126
127
128 @Override
129 public long length( Object value ) {
130 Binary binary = this.valueFactory.create(value);
131 return binary != null ? binary.getSize() : 0;
132 }
133 };
134 factories.put(PropertyType.STRING, this.stringFactory);
135 factories.put(PropertyType.BOOLEAN, this.booleanFactory);
136 factories.put(PropertyType.DATE, this.dateFactory);
137 factories.put(PropertyType.DECIMAL, new Factory<BigDecimal>(valueFactories.getDecimalFactory()));
138 factories.put(PropertyType.DOUBLE, this.doubleFactory);
139 factories.put(PropertyType.LONG, this.longFactory);
140 factories.put(PropertyType.NAME, new Factory<Name>(valueFactories.getNameFactory()));
141 factories.put(PropertyType.OBJECT, new Factory<Object>(valueFactories.getObjectFactory()));
142 factories.put(PropertyType.PATH, this.pathFactory);
143 factories.put(PropertyType.REFERENCE, new Factory<Reference>(valueFactories.getReferenceFactory()));
144 factories.put(PropertyType.URI, new Factory<URI>(valueFactories.getUriFactory()));
145 factories.put(PropertyType.UUID, new Factory<UUID>(valueFactories.getUuidFactory()));
146 factories.put(PropertyType.BINARY, this.binaryFactory);
147 this.typeFactoriesByPropertyType = Collections.unmodifiableMap(factories);
148 Map<String, PropertyType> propertyTypeByName = new HashMap<String, PropertyType>();
149 for (Map.Entry<PropertyType, TypeFactory<?>> entry : this.typeFactoriesByPropertyType.entrySet()) {
150 propertyTypeByName.put(entry.getValue().getTypeName(), entry.getKey());
151 }
152 this.propertyTypeByName = Collections.unmodifiableMap(propertyTypeByName);
153 Map<String, TypeFactory<?>> byName = new HashMap<String, TypeFactory<?>>();
154 for (TypeFactory<?> factory : factories.values()) {
155 byName.put(factory.getTypeName(), factory);
156 }
157 this.typeFactoriesByName = Collections.unmodifiableMap(byName);
158 }
159
160
161
162
163
164
165 public String asString( Object value ) {
166 return stringValueFactory.create(value);
167 }
168
169
170
171
172
173
174 public TypeFactory<Boolean> getBooleanFactory() {
175 return booleanFactory;
176 }
177
178
179
180
181
182
183 public TypeFactory<String> getStringFactory() {
184 return this.stringFactory;
185 }
186
187
188
189
190
191
192 public TypeFactory<?> getDateTimeFactory() {
193 return dateFactory;
194 }
195
196
197
198
199
200
201 public String getDefaultType() {
202 return defaultTypeName;
203 }
204
205
206
207
208
209
210 @SuppressWarnings( "unchecked" )
211 public Comparator<Object> getDefaultComparator() {
212 return (Comparator<Object>)PropertyType.OBJECT.getComparator();
213 }
214
215
216
217
218
219
220 public TypeFactory<Double> getDoubleFactory() {
221 return doubleFactory;
222 }
223
224
225
226
227
228
229 public TypeFactory<BigDecimal> getDecimalFactory() {
230 return decimalFactory;
231 }
232
233
234
235
236
237
238 public TypeFactory<Long> getLongFactory() {
239 return longFactory;
240 }
241
242
243
244
245
246
247 public TypeFactory<?> getPathFactory() {
248 return pathFactory;
249 }
250
251
252
253
254
255
256 public TypeFactory<?> getReferenceFactory() {
257 return referenceFactory;
258 }
259
260
261
262
263
264
265 public TypeFactory<?> getBinaryFactory() {
266 return binaryFactory;
267 }
268
269
270
271
272
273
274 public TypeFactory<?> getTypeFactory( String typeName ) {
275 if (typeName == null) return null;
276 return typeFactoriesByName.get(typeName.toUpperCase());
277 }
278
279
280
281
282
283
284 public TypeFactory<?> getTypeFactory( Object prototype ) {
285 ValueFactory<?> valueFactory = valueFactories.getValueFactory(prototype);
286 if (valueFactory == null) return null;
287 PropertyType type = valueFactory.getPropertyType();
288 assert type != null;
289 return typeFactoriesByPropertyType.get(type);
290 }
291
292
293
294
295
296
297 public Set<String> getTypeNames() {
298 return typeFactoriesByName.keySet();
299 }
300
301
302
303
304
305
306 public String getCompatibleType( String type1,
307 String type2 ) {
308 if (type1 == null) {
309 return type2 != null ? type2 : getDefaultType();
310 }
311 if (type2 == null) return type1;
312 if (type1.equals(type2)) return type1;
313
314
315 PropertyType ptype1 = propertyTypeByName.get(type1);
316 PropertyType ptype2 = propertyTypeByName.get(type2);
317 assert ptype1 != null;
318 assert ptype2 != null;
319 if (ptype1 == PropertyType.STRING) return type1;
320 if (ptype2 == PropertyType.STRING) return type2;
321
322 if (ptype1 == PropertyType.LONG && ptype2 == PropertyType.DATE) return type1;
323 if (ptype1 == PropertyType.DATE && ptype2 == PropertyType.LONG) return type2;
324
325 if (ptype1 == PropertyType.LONG && ptype2 == PropertyType.BOOLEAN) return type1;
326 if (ptype1 == PropertyType.BOOLEAN && ptype2 == PropertyType.LONG) return type2;
327
328 if (ptype1 == PropertyType.DOUBLE && ptype2 == PropertyType.LONG) return type1;
329 if (ptype1 == PropertyType.LONG && ptype2 == PropertyType.DOUBLE) return type2;
330
331 if (ptype1 == PropertyType.PATH && ptype2 == PropertyType.NAME) return type1;
332 if (ptype1 == PropertyType.NAME && ptype2 == PropertyType.PATH) return type2;
333
334
335 return getDefaultType();
336 }
337
338 protected class Factory<T> implements TypeFactory<T> {
339 protected final PropertyType type;
340 protected final ValueFactory<T> valueFactory;
341 protected final String typeName;
342
343 protected Factory( ValueFactory<T> valueFactory ) {
344 this.valueFactory = valueFactory;
345 this.type = this.valueFactory.getPropertyType();
346 this.typeName = type.getName().toUpperCase();
347 }
348
349
350
351
352
353
354 public String asReadableString( Object value ) {
355 return asString(value);
356 }
357
358
359
360
361
362
363 public String asString( Object value ) {
364 if (value instanceof String) {
365
366 value = valueFactory.create((String)value);
367 }
368 return stringValueFactory.create(value);
369 }
370
371
372
373
374
375
376 public T create( String value ) throws ValueFormatException {
377 return valueFactory.create(value);
378 }
379
380
381
382
383
384
385 public T create( Object value ) throws ValueFormatException {
386 return valueFactory.create(value);
387 }
388
389
390
391
392
393
394 @SuppressWarnings( "unchecked" )
395 public Class<T> getType() {
396 return (Class<T>)type.getValueClass();
397 }
398
399
400
401
402
403
404 public long length( Object value ) {
405 String str = asString(valueFactory.create(value));
406 return str != null ? str.length() : 0;
407 }
408
409
410
411
412
413
414 @SuppressWarnings( "unchecked" )
415 public Comparator<T> getComparator() {
416 return (Comparator<T>)type.getComparator();
417 }
418
419
420
421
422
423
424 public String getTypeName() {
425 return typeName;
426 }
427
428 }
429 }