1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.jcr.util;
35
36 import info.magnolia.cms.util.DateUtil;
37 import info.magnolia.context.MgnlContext;
38
39 import java.io.ByteArrayInputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.math.BigDecimal;
43 import java.net.URI;
44 import java.util.ArrayList;
45 import java.util.Calendar;
46 import java.util.Collection;
47 import java.util.Date;
48 import java.util.GregorianCalendar;
49 import java.util.LinkedList;
50 import java.util.List;
51 import java.util.TimeZone;
52
53 import javax.jcr.Binary;
54 import javax.jcr.Node;
55 import javax.jcr.Property;
56 import javax.jcr.PropertyType;
57 import javax.jcr.RepositoryException;
58 import javax.jcr.Value;
59 import javax.jcr.ValueFactory;
60
61 import org.apache.commons.lang3.BooleanUtils;
62 import org.apache.commons.lang3.StringUtils;
63 import org.apache.commons.lang3.time.FastDateFormat;
64 import org.apache.jackrabbit.value.BinaryImpl;
65 import org.apache.jackrabbit.value.ValueFactoryImpl;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69
70
71
72 public class PropertyUtil {
73
74 private static final Logger log = LoggerFactory.getLogger(PropertyUtil.class);
75
76 public static Property renameProperty(Property property, String newName) throws RepositoryException {
77
78 if (property.getName().equals(newName)) {
79 return property;
80 }
81 Node node = property.getParent();
82 Property newProperty = node.setProperty(newName, property.getValue());
83 property.remove();
84 return newProperty;
85 }
86
87
88
89
90 public static void setProperty(Node node, String propertyName, Object propertyValue) throws RepositoryException {
91 if (node == null) {
92 throw new IllegalArgumentException("Cannot set a property " + (StringUtils.isNotEmpty(propertyName) ? ("[" + propertyName + "]") : "") + " on a null-node!");
93 }
94 if (propertyName == null) {
95 throw new IllegalArgumentException("Cannot set a property without a provided name");
96 }
97
98
99
100 Property property = getPropertyOrNull(node, propertyName);
101 if (property != null && property.isMultiple() != propertyValue instanceof Collection) {
102 property.remove();
103 }
104
105 if (propertyValue == null) {
106 node.setProperty(propertyName, (Value) null);
107 } else if (propertyValue instanceof Value) {
108 node.setProperty(propertyName, (Value) propertyValue);
109 } else if (propertyValue instanceof Node) {
110 node.setProperty(propertyName, (Node) propertyValue);
111 } else if (propertyValue instanceof Binary) {
112 node.setProperty(propertyName, (Binary) propertyValue);
113 } else if (propertyValue instanceof Calendar) {
114 node.setProperty(propertyName, (Calendar) propertyValue);
115 } else if (propertyValue instanceof Date) {
116 Calendar cal = Calendar.getInstance();
117 cal.setTime((Date) propertyValue);
118 node.setProperty(propertyName, cal);
119 } else if (propertyValue instanceof BigDecimal) {
120 node.setProperty(propertyName, (BigDecimal) propertyValue);
121 } else if (propertyValue instanceof String) {
122 node.setProperty(propertyName, (String) propertyValue);
123 } else if (propertyValue instanceof Integer) {
124 node.setProperty(propertyName, ((Integer) propertyValue));
125 } else if (propertyValue instanceof Long) {
126 node.setProperty(propertyName, ((Long) propertyValue));
127 } else if (propertyValue instanceof Double) {
128 node.setProperty(propertyName, (Double) propertyValue);
129 } else if (propertyValue instanceof Boolean) {
130 node.setProperty(propertyName, (Boolean) propertyValue);
131 } else if (propertyValue instanceof InputStream) {
132 node.setProperty(propertyName, createBinaryFromInputStream((InputStream) propertyValue));
133 } else if (propertyValue instanceof byte[]) {
134 final Binary binary = node.getSession().getValueFactory().createBinary(new ByteArrayInputStream((byte[]) propertyValue));
135 Value value = node.getSession().getValueFactory().createValue(binary);
136 node.setProperty(propertyName, value);
137 } else if (propertyValue instanceof Collection) {
138 ArrayList<Value> values = new ArrayList<>();
139 for (Object value : (Collection) propertyValue) {
140 values.add(value instanceof Value ? (Value) value : createValue(value, node.getSession().getValueFactory()));
141 }
142 node.setProperty(propertyName, values.toArray(new Value[values.size()]));
143 } else {
144
145 throw new IllegalArgumentException("Cannot set property to a value of type " + propertyValue.getClass());
146 }
147 }
148
149
150
151
152 public static Value createValue(String valueStr, int type, ValueFactory valueFactory) {
153 Value value = null;
154 if (type == PropertyType.STRING) {
155 value = valueFactory.createValue(valueStr);
156 } else if (type == PropertyType.BOOLEAN) {
157 value = valueFactory.createValue(BooleanUtils.toBoolean(valueStr));
158 } else if (type == PropertyType.DOUBLE) {
159 try {
160 value = valueFactory.createValue(Double.parseDouble(valueStr));
161 } catch (NumberFormatException e) {
162 value = valueFactory.createValue(0d);
163 }
164 } else if (type == PropertyType.LONG) {
165 try {
166 value = valueFactory.createValue(Long.parseLong(valueStr));
167 } catch (NumberFormatException e) {
168 value = valueFactory.createValue(0L);
169 }
170 } else if (type == PropertyType.DATE) {
171 try {
172 Calendar date = new GregorianCalendar();
173 try {
174 String newDateAndTime = valueStr;
175 String[] dateAndTimeTokens = newDateAndTime.split("T");
176 String newDate = dateAndTimeTokens[0];
177 String[] dateTokens = newDate.split("-");
178 int hour = 0;
179 int minute = 0;
180 int second = 0;
181 int year = Integer.parseInt(dateTokens[0]);
182 int month = Integer.parseInt(dateTokens[1]) - 1;
183 int day = Integer.parseInt(dateTokens[2]);
184 if (dateAndTimeTokens.length > 1) {
185 String newTime = dateAndTimeTokens[1];
186 String[] timeTokens = newTime.split(":");
187 hour = Integer.parseInt(timeTokens[0]);
188 minute = Integer.parseInt(timeTokens[1]);
189 second = Integer.parseInt(timeTokens[2]);
190 }
191 date.set(year, month, day, hour, minute, second);
192
193 date.set(Calendar.MILLISECOND, 0);
194 date.setTimeZone(TimeZone.getTimeZone("GMT"));
195 }
196
197 catch (Exception e) {
198
199 }
200 value = valueFactory.createValue(date);
201 } catch (Exception e) {
202 log.debug("Exception caught: {}", e.getMessage(), e);
203 }
204 }
205
206 return value;
207
208 }
209
210
211
212
213 public static int getJCRPropertyType(Object obj) {
214 if (obj instanceof String) {
215 return PropertyType.STRING;
216 }
217 if (obj instanceof Double) {
218 return PropertyType.DOUBLE;
219 }
220 if (obj instanceof Float) {
221 return PropertyType.DOUBLE;
222 }
223 if (obj instanceof Long) {
224 return PropertyType.LONG;
225 }
226 if (obj instanceof Integer) {
227 return PropertyType.LONG;
228 }
229 if (obj instanceof Boolean) {
230 return PropertyType.BOOLEAN;
231 }
232 if (obj instanceof Calendar) {
233 return PropertyType.DATE;
234 }
235 if (obj instanceof Date) {
236 return PropertyType.DATE;
237 }
238 if (obj instanceof Binary) {
239 return PropertyType.BINARY;
240 }
241 if (obj instanceof InputStream) {
242 return PropertyType.BINARY;
243 }
244 if (obj instanceof Node) {
245 return PropertyType.REFERENCE;
246 }
247 if (obj instanceof URI) {
248 return PropertyType.URI;
249 }
250 return PropertyType.UNDEFINED;
251 }
252
253
254
255
256 public static void updateOrCreate(Node node, String string, GregorianCalendar gregorianCalendar) throws RepositoryException {
257 if (node.hasProperty(string)) {
258 node.getProperty(string).setValue(gregorianCalendar);
259 } else {
260 node.setProperty(string, gregorianCalendar);
261 }
262 }
263
264 public static String getDateFormat() {
265 try {
266 return FastDateFormat.getDateInstance(
267 FastDateFormat.SHORT,
268 MgnlContext.getLocale()).getPattern();
269 } catch (IllegalStateException e) {
270
271 return DateUtil.YYYY_MM_DD;
272 }
273 }
274
275 public static List<String> getValuesStringList(Value[] values) {
276 ArrayList<String> list = new ArrayList<String>();
277 for (Value value : values) {
278 list.add(getValueString(value));
279 }
280 return list;
281 }
282
283
284
285
286 public static String getValueString(Property property) {
287 try {
288 return getValueString(property.getValue());
289 } catch (RepositoryException e) {
290 log.debug("RepositoryException caught: {}", e.getMessage(), e);
291 return null;
292 }
293 }
294
295
296
297
298 public static String getValueString(Value value) {
299 try {
300 switch (value.getType()) {
301 case (PropertyType.STRING):
302 return value.getString();
303 case (PropertyType.DOUBLE):
304 return Double.toString(value.getDouble());
305 case (PropertyType.LONG):
306 return Long.toString(value.getLong());
307 case (PropertyType.BOOLEAN):
308 return Boolean.toString(value.getBoolean());
309 case (PropertyType.DATE):
310 Date valueDate = value.getDate().getTime();
311 return DateUtil.format(valueDate, PropertyUtil.getDateFormat());
312 case (PropertyType.BINARY):
313
314 default:
315 return StringUtils.EMPTY;
316 }
317 } catch (RepositoryException e) {
318 log.debug("RepositoryException caught: {}", e.getMessage(), e);
319 }
320 return null;
321
322 }
323
324 public static Value createValue(Object obj, ValueFactory valueFactory) throws RepositoryException {
325 switch (PropertyUtil.getJCRPropertyType(obj)) {
326 case PropertyType.STRING:
327 return valueFactory.createValue((String) obj);
328 case PropertyType.BOOLEAN:
329 return valueFactory.createValue((Boolean) obj);
330 case PropertyType.DATE:
331 if (obj instanceof Calendar) {
332 return valueFactory.createValue((Calendar) obj);
333 } else {
334 Calendar cal = Calendar.getInstance();
335 cal.setTime((Date) obj);
336 return valueFactory.createValue(cal);
337 }
338 case PropertyType.LONG:
339 return obj instanceof Long ? valueFactory.createValue(((Long) obj).longValue()) : valueFactory.createValue(((Integer) obj).longValue());
340 case PropertyType.DOUBLE:
341 return obj instanceof Double ? valueFactory.createValue((Double) obj) : valueFactory.createValue(((Float) obj).doubleValue());
342 case PropertyType.BINARY:
343 return valueFactory.createValue(createBinaryFromInputStream((InputStream) obj));
344 case PropertyType.REFERENCE:
345 return valueFactory.createValue(((Node) obj));
346 default:
347 return (obj != null ? valueFactory.createValue(obj.toString()) : valueFactory.createValue(StringUtils.EMPTY));
348 }
349 }
350
351
352
353
354
355
356 public static Calendar getDate(Node node, String name) {
357 return getDate(node, name, null);
358 }
359
360
361
362
363
364
365 public static Calendar getDate(Node node, String name, Calendar defaultValue) {
366 if (node != null) {
367 try {
368 if (node.hasProperty(name)) {
369 return node.getProperty(name).getDate();
370 }
371 } catch (RepositoryException e) {
372 log.error("can't read value '{}' of the Node '{}' will return default value", name, node.toString(), e);
373 }
374 }
375 return defaultValue;
376 }
377
378
379
380
381
382
383 public static String getString(Node node, String name) {
384 return getString(node, name, null);
385 }
386
387
388
389
390
391
392 public static String getString(Node node, String name, String defaultValue) {
393 if (node != null) {
394 try {
395 if (node.hasProperty(name)) {
396 return node.getProperty(name).getString();
397 }
398 } catch (RepositoryException e) {
399 log.error("can't read value '{}' of the Node '{}' will return default value", name, node.toString(), e);
400 }
401 }
402 return defaultValue;
403 }
404
405 public static Long getLong(Node node, String name) {
406 return getLong(node, name, null);
407 }
408
409 public static Long getLong(Node node, String name, Long defaultValue) {
410 if (node != null) {
411 try {
412 if (node.hasProperty(name)) {
413 return node.getProperty(name).getLong();
414 }
415 } catch (RepositoryException e) {
416 log.error("can't read value '{}' of the Node '{}' will return default value", name, node.toString(), e);
417 }
418 }
419 return defaultValue;
420 }
421
422
423
424
425
426
427 public static boolean getBoolean(Node node, String name, boolean defaultValue) {
428 if (node != null) {
429 try {
430 if (node.hasProperty(name)) {
431 return node.getProperty(name).getBoolean();
432 }
433 } catch (RepositoryException e) {
434 log.error("can't read value '{}' of the Node '{}' will return default value", name, node.toString(), e);
435 }
436 }
437 return defaultValue;
438 }
439
440
441
442
443
444 public static Property getPropertyOrNull(Node node, String relativePath) {
445 try {
446 return node.hasProperty(relativePath) ? node.getProperty(relativePath) : null;
447 } catch (RepositoryException e) {
448 log.debug("Could not retrieve property {}", relativePath, e);
449 }
450 return null;
451 }
452
453
454
455
456 @Deprecated
457 public static Property getProperty(Node node, String relativePath) {
458 return getPropertyOrNull(node, relativePath);
459 }
460
461
462
463
464
465
466
467 public static Object getPropertyValueObject(Node node, String relativePath) {
468 final Property property = getPropertyOrNull(node, relativePath);
469 if (property != null) {
470 try {
471
472 if (property.isMultiple()) {
473 Value[] values = property.getValues();
474 List<Object> res = new LinkedList<Object>();
475 for (Value value : values) {
476 res.add(getValueObject(value));
477 }
478 return res;
479 } else {
480 return getValueObject(property.getValue());
481 }
482
483 } catch (Exception e) {
484 log.warn("Exception during casting the property value", e);
485 }
486 }
487 return null;
488 }
489
490
491
492
493
494 public static Object getValueObject(Value value) {
495 try {
496 switch (value.getType()) {
497 case (PropertyType.DECIMAL):
498 return value.getDecimal();
499 case (PropertyType.STRING):
500 return value.getString();
501 case (PropertyType.DOUBLE):
502 return Double.valueOf(value.getDouble());
503 case (PropertyType.LONG):
504 return Long.valueOf(value.getLong());
505 case (PropertyType.BOOLEAN):
506 return Boolean.valueOf(value.getBoolean());
507 case (PropertyType.DATE):
508 return value.getDate().getTime();
509 case (PropertyType.URI):
510 return new URI(value.getString());
511 case (PropertyType.BINARY):
512 return ValueFactoryImpl.getInstance().createBinary(value.getBinary().getStream());
513 default:
514 return value.getString();
515 }
516 } catch (Exception e) {
517 log.warn("Exception during casting the property value", e);
518 }
519 return null;
520 }
521
522
523
524
525
526
527 private static Binary createBinaryFromInputStream(InputStream in) throws RepositoryException {
528 try {
529 return new BinaryImpl(in);
530 } catch (IOException ioe) {
531 log.warn("Could not create a Binary Object from the property input Stream.");
532 throw new RepositoryException(ioe);
533 }
534 }
535
536 }