View Javadoc

1   /**
2    * This file Copyright (c) 2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.jcr.util;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.util.DateUtil;
38  import info.magnolia.context.MgnlContext;
39  
40  import java.io.InputStream;
41  import java.math.BigDecimal;
42  import java.util.ArrayList;
43  import java.util.Calendar;
44  import java.util.Date;
45  import java.util.GregorianCalendar;
46  import java.util.List;
47  import java.util.TimeZone;
48  
49  import javax.jcr.Binary;
50  import javax.jcr.Node;
51  import javax.jcr.PathNotFoundException;
52  import javax.jcr.Property;
53  import javax.jcr.PropertyType;
54  import javax.jcr.RepositoryException;
55  import javax.jcr.Value;
56  import javax.jcr.ValueFactory;
57  
58  import org.apache.commons.lang.BooleanUtils;
59  import org.apache.commons.lang.StringUtils;
60  import org.apache.commons.lang.time.FastDateFormat;
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  /**
65   * Property-related utility methods.
66   *
67   * @version $Id$
68   */
69  public class PropertyUtil {
70  
71      private static final Logger log = LoggerFactory.getLogger(PropertyUtil.class);
72  
73      public static void renameProperty(Property property, String newName) throws RepositoryException {
74          Node node = property.getParent();
75          node.setProperty(newName, property.getValue());
76          property.remove();
77      }
78  
79      /**
80       * Allows setting a Node's property from an object.
81       */
82      public static void setProperty(Node node, String propertyName, Object propertyValue) throws RepositoryException {
83          if (node == null) {
84              throw new IllegalArgumentException("Cannot set a property on a null-node!");
85          }
86          if (propertyName == null) {
87              throw new IllegalArgumentException("Cannot set a property without a provided name");
88          }
89  
90          // let's find out what type of value we got
91          if (propertyValue instanceof Value) {
92              node.setProperty(propertyName, (Value) propertyValue);
93          } else if (propertyValue instanceof Node) {
94              node.setProperty(propertyName, (Node) propertyValue);
95          } else if (propertyValue instanceof Binary) {
96              node.setProperty(propertyName, (Binary) propertyValue);
97          } else if (propertyValue instanceof Calendar) {
98              node.setProperty(propertyName, (Calendar) propertyValue);
99          } else if (propertyValue instanceof BigDecimal) {
100             node.setProperty(propertyName, (BigDecimal) propertyValue);
101         } else if (propertyValue instanceof String) {
102             node.setProperty(propertyName, (String) propertyValue);
103         } else if (propertyValue instanceof Long) {
104             node.setProperty(propertyName, ((Long) propertyValue).longValue());
105         } else if (propertyValue instanceof Double) {
106             node.setProperty(propertyName, (Double) propertyValue);
107         } else if (propertyValue instanceof Boolean) {
108             node.setProperty(propertyName, (Boolean) propertyValue);
109         } else if (propertyValue instanceof InputStream) {
110             node.setProperty(propertyName, (InputStream) propertyValue);
111         } else {
112             // TODO dlipp: verify if this is desired default-behavior: NodeDataUtil#setValue sets propertyValue.toString() as default!
113             throw new IllegalArgumentException("Cannot set property to a value of type " + propertyValue.getClass());
114         }
115     }
116 
117     /**
118      * Transforms a string to a jcr value object.
119      */
120     public static Value createValue(String valueStr, int type, ValueFactory valueFactory) {
121         Value value = null;
122         if (type == PropertyType.STRING) {
123             value = valueFactory.createValue(valueStr);
124         } else if (type == PropertyType.BOOLEAN) {
125             value = valueFactory.createValue(BooleanUtils.toBoolean(valueStr));
126         } else if (type == PropertyType.DOUBLE) {
127             try {
128                 value = valueFactory.createValue(Double.parseDouble(valueStr));
129             } catch (NumberFormatException e) {
130                 value = valueFactory.createValue(0d);
131             }
132         } else if (type == PropertyType.LONG) {
133             try {
134                 value = valueFactory.createValue(Long.parseLong(valueStr));
135             } catch (NumberFormatException e) {
136                 value = valueFactory.createValue(0L);
137             }
138         } else if (type == PropertyType.DATE) {
139             try {
140                 Calendar date = new GregorianCalendar();
141                 try {
142                     String newDateAndTime = valueStr;
143                     String[] dateAndTimeTokens = newDateAndTime.split("T");
144                     String newDate = dateAndTimeTokens[0];
145                     String[] dateTokens = newDate.split("-");
146                     int hour = 0;
147                     int minute = 0;
148                     int second = 0;
149                     int year = Integer.parseInt(dateTokens[0]);
150                     int month = Integer.parseInt(dateTokens[1]) - 1;
151                     int day = Integer.parseInt(dateTokens[2]);
152                     if (dateAndTimeTokens.length > 1) {
153                         String newTime = dateAndTimeTokens[1];
154                         String[] timeTokens = newTime.split(":");
155                         hour = Integer.parseInt(timeTokens[0]);
156                         minute = Integer.parseInt(timeTokens[1]);
157                         second = Integer.parseInt(timeTokens[2]);
158                     }
159                     date.set(year, month, day, hour, minute, second);
160                     // this is used in the searching
161                     date.set(Calendar.MILLISECOND, 0);
162                     date.setTimeZone(TimeZone.getTimeZone("GMT"));
163                 }
164                 // todo time zone??
165                 catch (Exception e) {
166                     // ignore, it sets the current date / time
167                 }
168                 value = valueFactory.createValue(date);
169             } catch (Exception e) {
170                 log.debug("Exception caught: " + e.getMessage(), e);
171             }
172         }
173 
174         return value;
175 
176     }
177 
178     /**
179      * @return JCR-PropertyType corresponding to provided Object.
180      */
181     public static int getJCRPropertyType(Object obj) {
182         if (obj instanceof String) {
183             return PropertyType.STRING;
184         }
185         if (obj instanceof Double) {
186             return PropertyType.DOUBLE;
187         }
188         if (obj instanceof Float) {
189             return PropertyType.DOUBLE;
190         }
191         if (obj instanceof Long) {
192             return PropertyType.LONG;
193         }
194         if (obj instanceof Integer) {
195             return PropertyType.LONG;
196         }
197         if (obj instanceof Boolean) {
198             return PropertyType.BOOLEAN;
199         }
200         if (obj instanceof Calendar) {
201             return PropertyType.DATE;
202         }
203         if (obj instanceof Binary) {
204             return PropertyType.BINARY;
205         }
206         if (obj instanceof InputStream) {
207             return PropertyType.BINARY;
208         }
209         if (obj instanceof Content) {
210             return PropertyType.REFERENCE;
211         }
212         return PropertyType.UNDEFINED;
213     }
214 
215     /**
216      * Updates existing property or creates a new one if it doesn't exist already.
217      */
218     public static void updateOrCreate(Node node, String string, GregorianCalendar gregorianCalendar) throws RepositoryException {
219         if (node.hasProperty(string)) {
220             node.getProperty(string).setValue(gregorianCalendar);
221         } else {
222             node.setProperty(string, gregorianCalendar);
223         }
224     }
225 
226     public static String getDateFormat() {
227         try {
228             return FastDateFormat.getDateInstance(
229                     FastDateFormat.SHORT,
230                     MgnlContext.getLocale()).getPattern();
231         } catch (IllegalStateException e) {
232             // this happens if the context is not (yet) set
233             return DateUtil.YYYY_MM_DD;
234         }
235     }
236 
237     public static List<String> getValuesStringList(Value[] values) {
238         ArrayList<String> list = new ArrayList<String>();
239         try {
240             for (Value value : values) {
241                 switch (value.getType()) {
242                     case (PropertyType.STRING):
243                         list.add(value.getString());
244                         break;
245                     case (PropertyType.DOUBLE):
246                         list.add(Double.toString(value.getDouble()));
247                         break;
248                     case (PropertyType.LONG):
249                         list.add(Long.toString(value.getLong()));
250                         break;
251                     case (PropertyType.BOOLEAN):
252                         list.add(Boolean.toString(value.getBoolean()));
253                         break;
254                     case (PropertyType.DATE):
255                         Date valueDate = value.getDate().getTime();
256                         list.add(DateUtil.format(valueDate, PropertyUtil.getDateFormat()));
257                         break;
258                     case (PropertyType.BINARY):
259                         // for lack of better solution, fall through to the default - empty string
260                     default:
261                         list.add(StringUtils.EMPTY);
262                 }
263             }
264         } catch (RepositoryException e) {
265             log.debug("RepositoryException caught: " + e.getMessage(), e);
266         }
267         return list;
268     }
269 
270     public static Value createValue(Object obj, ValueFactory valueFactory) throws RepositoryException {
271         switch (PropertyUtil.getJCRPropertyType(obj)) {
272             case PropertyType.STRING:
273                 return valueFactory.createValue((String) obj);
274             case PropertyType.BOOLEAN:
275                 return valueFactory.createValue((Boolean) obj);
276             case PropertyType.DATE:
277                 return valueFactory.createValue((Calendar) obj);
278             case PropertyType.LONG:
279                 return obj instanceof Long ? valueFactory.createValue(((Long) obj).longValue()) : valueFactory.createValue(((Integer) obj).longValue());
280             case PropertyType.DOUBLE:
281                 return obj instanceof Double ? valueFactory.createValue((Double) obj) : valueFactory.createValue(((Float) obj).doubleValue());
282             case PropertyType.BINARY:
283                 return valueFactory.createValue((InputStream) obj);
284             case PropertyType.REFERENCE:
285                 return valueFactory.createValue(((Content) obj).getJCRNode());
286             default:
287                 return (obj != null ? valueFactory.createValue(obj.toString()) : valueFactory.createValue(StringUtils.EMPTY));
288         }
289     }
290 
291     /**
292      * Return the Calendar representing the node property value.
293      * If the Node did not contain such a Property,
294      * then return <b>null</b>.
295      */
296     public static Calendar getDate(Node node, String name) {
297         return getDate(node, name, null);
298     }
299 
300     /**
301      * Return the Calendar representing the node property value.
302      * If the Node did not contain such a Property,
303      * then return the default value.
304      */
305     public static Calendar getDate(Node node, String name, Calendar defaultValue) {
306         try {
307             if (node.hasProperty(name)) {
308                 return node.getProperty(name).getDate();
309             }
310         } catch (RepositoryException e) {
311             log.error("can't read value '" + name + "' of the Node '" + node.toString() + "' will return default value", e);
312         }
313         return defaultValue;
314     }
315 
316     /**
317      * Return the String representing the node property value.
318      * If the Node did not contain such a Property,
319      * then return <b>null</b>.
320      */
321     public static String getString(Node node, String name) {
322         return getString(node, name, null);
323     }
324 
325     /**
326      * Return the String representing the node property value.
327      * If the Node did not contain such a Property,
328      * then return the default value.
329      */
330     public static String getString(Node node, String name, String defaultValue) {
331         try {
332             if (node.hasProperty(name)) {
333                 return node.getProperty(name).getString();
334             }
335         } catch (RepositoryException e) {
336             log.error("can't read value '" + name + "' of the Node '" + node.toString() + "' will return default value", e);
337         }
338         return defaultValue;
339     }
340 
341     /**
342      * Return the boolean representing the node property value.
343      * If the Node did not contain such a Property,
344      * then return the default value.
345      */
346     public static boolean getBoolean(Node node, String name, boolean defaultValue) {
347         try {
348             if (node.hasProperty(name)) {
349                 return node.getProperty(name).getBoolean();
350             }
351         } catch (RepositoryException e) {
352             log.error("can't read value '" + name + "' of the Node '" + node.toString() + "' will return default value", e);
353         }
354         return defaultValue;
355     }
356 
357     /**
358      * Return the Property relative to the Node.
359      * Return null in case of Exception.
360      */
361     public static Property getProperty(Node node, String relativePath) {
362         try {
363             return node.getProperty(relativePath);
364         }
365         catch (PathNotFoundException e) {
366             log.error("Property Access Exception ",e);
367         }
368         catch (RepositoryException e) {
369             log.error("Property Access Exception ",e);
370         }
371         return null;
372     }
373 
374 
375 }