View Javadoc

1   /**
2    * This file Copyright (c) 2003-2014 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.cms.util;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.core.HierarchyManager;
38  import info.magnolia.cms.core.NodeData;
39  import info.magnolia.cms.i18n.Messages;
40  import info.magnolia.cms.i18n.MessagesManager;
41  import info.magnolia.cms.i18n.MessagesUtil;
42  import info.magnolia.cms.security.AccessDeniedException;
43  import info.magnolia.context.MgnlContext;
44  import info.magnolia.jcr.util.PropertyUtil;
45  import info.magnolia.repository.RepositoryConstants;
46  
47  import java.io.InputStream;
48  import java.util.Calendar;
49  import java.util.Date;
50  import java.util.List;
51  
52  import javax.jcr.PropertyType;
53  import javax.jcr.RepositoryException;
54  import javax.jcr.Value;
55  import javax.jcr.ValueFactory;
56  
57  import org.apache.commons.lang.StringUtils;
58  import org.slf4j.Logger;
59  import org.slf4j.LoggerFactory;
60  
61  /**
62   * Util to work with {@link NodeData}.
63   * @author Sameer Charles
64   * @version $Revision$ ($Author$)
65   */
66  public class NodeDataUtil {
67      private static final Logger log = LoggerFactory.getLogger(NodeDataUtil.class);
68  
69      /**
70       * Same as getValueString(nd, dateFormat) but using the users short date format.
71       */
72      public static String getValueString(NodeData nodeData) {
73          String dateFormat = null;
74          if(nodeData.getType() == PropertyType.DATE){
75              dateFormat = PropertyUtil.getDateFormat();
76          }
77          return getValueString(nodeData, dateFormat);
78      }
79  
80      /**
81       * Returns a String representation of the value. In case of a binary the path including filename and extension is returned
82       * @param nodeData
83       * @param dateFormat date format to use in the case it is a date
84       * @return
85       */
86      public static String getValueString(NodeData nodeData, String dateFormat) {
87          // we can't use FileProperties since this class is in the GUI package
88          if(nodeData.getType()==PropertyType.BINARY){
89              String filename = nodeData.getAttribute("fileName");
90              String ext = nodeData.getAttribute("extension");
91              String fullName = filename;
92              String fullExt = StringUtils.EMPTY;
93              if (StringUtils.isNotEmpty(ext)) {
94                  fullExt = "." + ext;
95                  fullName += fullExt;
96              }
97              return nodeData.getHandle() + "/" + fullName;
98          }
99          else if (nodeData.isMultiValue() == NodeData.MULTIVALUE_TRUE){
100             return StringUtils.join(getValuesStringList(nodeData.getValues()), ",");
101         } else {
102             return getValueString(nodeData.getValue(), dateFormat);
103         }
104     }
105 
106     /**
107      * Same as value.getString(), but using custom date format.
108      */
109     public static String getValueString(Value value, String dateFormat) {
110         try{
111             switch (value.getType()) {
112             case (PropertyType.STRING):
113                 return value.getString();
114             case (PropertyType.DOUBLE):
115                 return Double.toString(value.getDouble());
116             case (PropertyType.LONG):
117                 return Long.toString(value.getLong());
118             case (PropertyType.BOOLEAN):
119                 return Boolean.toString(value.getBoolean());
120             case (PropertyType.DATE):
121                 Date valueDate = value.getDate().getTime();
122             return DateUtil.format(valueDate, dateFormat);
123             case (PropertyType.BINARY):
124                 // ???
125             default:
126                 return StringUtils.EMPTY;
127             }
128         }
129         catch (Exception e) {
130             log.debug("Exception caught: " + e.getMessage(), e); //$NON-NLS-1$
131         }
132         return StringUtils.EMPTY;
133     }
134 
135     /**
136      * Inherit a value. Uses the string value. The "inherit" means that the method will look for the value in the content itself and if not found
137      * it will go up in the tree and try to locate value in one of the parents of the content until reaching the root. The first value found while
138      * traversing the tree way up is the one that will be returned.
139      * @param node Node expected to define or inherit the searched node value.
140      * @param name Name of the nodeData.
141      */
142     public static String inheritString(Content node, String name) throws RepositoryException{
143         String value = "";
144 
145         if (node.hasNodeData(name)) {
146             value = NodeDataUtil.getString(node, name);
147         }
148         if(StringUtils.isEmpty(value) && node.getLevel() > 0){
149             value = inheritString(node.getParent(), name);
150         }
151         return value;
152     }
153 
154     /**
155      * Inherit a value. You can provide a default value if not found
156      */
157     public static String inheritString(Content node, String name, String dflt) throws RepositoryException{
158         String value = inheritString(node, name);
159         if(StringUtils.isEmpty(value)){
160             return dflt;
161         }
162         return value;
163     }
164 
165     /**
166      * Inherit a value. Uses the string value
167      */
168     public static Object inherit(Content node, String name) throws RepositoryException{
169         Object value = null;
170 
171         if (node.hasNodeData(name)) {
172             value = NodeDataUtil.getValueObject(node.getNodeData(name));
173         }
174         if(value == null && node.getLevel() > 0){
175             value = inherit(node.getParent(), name);
176         }
177         return value;
178     }
179 
180     /**
181      * Inherit a value. You can provide a default value if not found
182      */
183     public static Object inherit(Content node, String name, Object dflt) throws RepositoryException{
184         Object value = inherit(node, name);
185         if(value == null){
186             return dflt;
187         }
188         return value;
189     }
190 
191     /**
192      * Returns the value as an Object.
193      * @return Object
194      */
195     public static Object getValueObject(NodeData nd) {
196         try {
197             switch (nd.getType()) {
198             case (PropertyType.STRING):
199                 return nd.getString();
200             case (PropertyType.DOUBLE):
201                 return Double.valueOf(nd.getDouble());
202             case (PropertyType.LONG):
203                 return Long.valueOf(nd.getLong());
204             case (PropertyType.BOOLEAN):
205                 return Boolean.valueOf(nd.getBoolean());
206             case (PropertyType.DATE):
207                 return nd.getDate().getTime();
208             case (PropertyType.BINARY):
209                 return null;
210             default:
211                 return null;
212             }
213         }
214         catch (Exception e) {
215             log.debug("Exception caught: " + e.getMessage(), e); //$NON-NLS-1$
216         }
217         return null;
218     }
219 
220     /**
221      * Calls the correct setValue method based on object type. If the value is null an empty string is set.
222      */
223     public static NodeData setValue(NodeData nodeData, Object valueObj) throws AccessDeniedException, RepositoryException{
224         if(valueObj == null){
225             nodeData.setValue(StringUtils.EMPTY);
226         }
227         else{
228             switch (PropertyUtil.getJCRPropertyType(valueObj)) {
229             case PropertyType.STRING:
230                 nodeData.setValue((String)valueObj);
231                 break;
232             case PropertyType.BOOLEAN:
233                 nodeData.setValue(((Boolean)valueObj).booleanValue());
234                 break;
235             case PropertyType.DATE:
236                 nodeData.setValue((Calendar)valueObj);
237                 break;
238             case PropertyType.LONG:
239                 // can either be a Long or Integer - see #getJCRPropertyType(Object)
240                 long longToSet = (valueObj instanceof Integer) ? ((Integer) valueObj).longValue() : ((Long) valueObj).longValue();
241                 nodeData.setValue(longToSet);
242                 break;
243             case PropertyType.DOUBLE:
244                 // can either be a Double or Float - see #getJCRPropertyType(Object)
245                 double doubleToSet = (valueObj instanceof Float) ? ((Float) valueObj).doubleValue() : ((Double) valueObj).doubleValue();
246                 nodeData.setValue(doubleToSet);
247                 break;
248             case PropertyType.BINARY:
249                 nodeData.setValue((InputStream)valueObj);
250                 break;
251             case PropertyType.REFERENCE:
252                 nodeData.setValue((Content)valueObj);
253                 break;
254             default:
255                 nodeData.setValue(valueObj.toString());
256             }
257         }
258         return nodeData;
259     }
260 
261 
262     /**
263      * String representation of the jcr property type.
264      */
265     public static String getTypeName(NodeData nd) {
266         return PropertyType.nameFromValue(nd.getType());
267     }
268 
269     /**
270      * Simple method to get strings like configuration informations.
271      */
272     public static String getString(String repository, String path) {
273         return getString(repository, path, null);
274     }
275 
276     /**
277      * Get the string or the empty string if not existing.
278      */
279     public static String getString(Content node, String name) {
280         return getString(node, name, "");
281     }
282 
283     /**
284      * You can define a default value if not found.
285      */
286     public static String getString(String repository, String path, String defaultValue) {
287         try {
288             String name = StringUtils.substringAfterLast(path, "/");
289             String nodeHandle = StringUtils.substringBeforeLast(path, "/");
290             Content node = MgnlContext.getHierarchyManager(repository).getContent(nodeHandle);
291             return getString(node, name);
292         }
293         catch (Exception e) {
294             return defaultValue;
295         }
296     }
297 
298     /**
299      * You can define a default value if not found.
300      */
301     public static String getString(Content node, String name, String defaultValue) {
302         try {
303             if (node.hasNodeData(name)) {
304                 return getValueString(node.getNodeData(name));
305             }
306 
307             return defaultValue;
308         }
309         catch (Exception e) {
310             return defaultValue;
311         }
312     }
313 
314     public static long getLong(Content node, String name, long defaultValue) {
315         try {
316             if(node.hasNodeData(name)){
317                 return node.getNodeData(name).getLong();
318             }
319         }
320         // should not happen
321         catch (RepositoryException e) {
322             log.error("can't read value will return default value", e);
323         }
324         return defaultValue;
325     }
326 
327     public static Calendar getDate(Content node, String name, Calendar defaultValue) {
328         try {
329             if(node.hasNodeData(name)){
330                 return node.getNodeData(name).getDate();
331             }
332         }
333         // should not happen
334         catch (RepositoryException e) {
335             log.error("can't read value will return default value", e);
336         }
337         return defaultValue;
338     }
339 
340     public static boolean getBoolean(Content node, String name, boolean defaultValue) {
341         try {
342             if(node.hasNodeData(name)){
343                 return node.getNodeData(name).getBoolean();
344             }
345         }
346         // should not happen
347         catch (RepositoryException e) {
348             log.error("can't read value will return default value", e);
349         }
350         return defaultValue;
351     }
352 
353     /**
354      * If the NodeData does not exist yet, just create it.
355      * @param node
356      * @param name
357      * @return the found or created NodeData
358      * @throws AccessDeniedException
359      * @throws RepositoryException
360      */
361     public static NodeData getOrCreate(Content node, String name) throws AccessDeniedException, RepositoryException {
362         return getOrCreate(node, name, PropertyType.STRING);
363     }
364 
365     /**
366      * If the NodeData does not exist yet, just create it.
367      * @param node
368      * @param name
369      * @return the found or created NodeData
370      * @throws AccessDeniedException
371      * @throws RepositoryException
372      */
373     public static NodeData getOrCreate(Content node, String name, int type) throws AccessDeniedException,
374     RepositoryException {
375         if (node.hasNodeData(name)) {
376             return node.getNodeData(name);
377         }
378 
379         return node.createNodeData(name, type);
380     }
381 
382     public static NodeData getOrCreate(Content node, String name, Object obj) throws AccessDeniedException,
383     RepositoryException {
384 
385         return getOrCreate(node, name, PropertyUtil.getJCRPropertyType(obj));
386     }
387 
388 
389     public static NodeData getOrCreateAndSet(Content node, String name, Object obj) throws AccessDeniedException, RepositoryException {
390         // TODO we should not use the jcr node
391         ValueFactory valueFactory = node.getJCRNode().getSession().getValueFactory();
392         NodeData nd = getOrCreate(node, name, PropertyUtil.getJCRPropertyType(obj));
393         nd.setValue(createValue(obj, valueFactory));
394         return nd;
395     }
396 
397     public static NodeData getOrCreateAndSet(Content node, String name, long value) throws AccessDeniedException, RepositoryException {
398         return getOrCreateAndSet(node, name, Long.valueOf(value));
399     }
400 
401     public static NodeData getOrCreateAndSet(Content node, String name, Value[] value) throws AccessDeniedException, RepositoryException {
402         if (node.hasNodeData(name)) {
403             node.setNodeData(name, value);
404             return node.getNodeData(name);
405         }
406 
407         return node.createNodeData(name, value);
408 
409     }
410 
411     public static NodeData getOrCreateAndSet(Content node, String name, int value) throws AccessDeniedException, RepositoryException {
412         return getOrCreateAndSet(node, name, Long.valueOf(value));
413     }
414 
415     public static NodeData getOrCreateAndSet(Content node, String name, boolean value) throws AccessDeniedException, RepositoryException {
416         return getOrCreateAndSet(node, name, Boolean.valueOf(value));
417     }
418 
419     /**
420      * Uses the i18n mechanism to translate the message if the resulting string is a key.
421      */
422     public static String getI18NString(Content node, String str) {
423         Messages msgs = MessagesManager.getMessages();
424         String key = getString(node, str);
425         String i18nBasename = null;
426         try {
427             i18nBasename = NodeDataUtil.inheritString(node, "i18nBasename");
428         }
429         catch (RepositoryException e) {
430             log.error("can't read i18nBasename value, will default back", e);
431         }
432 
433         if (StringUtils.isNotEmpty(i18nBasename)) {
434             msgs = MessagesUtil.chainWithDefault(i18nBasename);
435         }
436 
437         return msgs.getWithDefault(key, key);
438     }
439 
440     /**
441      * Uses the i18n mechanism to translate the message if the resulting string is a key.
442      */
443     public static String getI18NString(Content node, String str, String basename) {
444         String key = getString(node, str);
445         return MessagesManager.getMessages(basename).getWithDefault(key, key);
446     }
447 
448     /**
449      * Uses the default value factory.
450      */
451     public static Value createValue(String valueStr, int type) throws RepositoryException {
452         HierarchyManager hm = MgnlContext.getSystemContext().getHierarchyManager(RepositoryConstants.CONFIG);
453         ValueFactory valueFactory = hm.getWorkspace().getSession().getValueFactory();
454         return createValue(valueStr, type, valueFactory);
455     }
456 
457     /**
458      * @deprecated since 4.5 - use {@link PropertyUtil#createValue(Object, ValueFactory)} instead
459      */
460     @Deprecated
461     public static Value createValue(Object obj, ValueFactory valueFactory) throws RepositoryException {
462         return PropertyUtil.createValue(obj, valueFactory);
463     }
464 
465     /**
466      * Transforms a string to a jcr value object.
467      *
468      * @deprecated since 4.5 - directly use {@link PropertyUtil#createValue(String, int, ValueFactory)} instead.
469      */
470     @Deprecated
471     public static Value createValue(String valueStr, int type, ValueFactory valueFactory) {
472         return PropertyUtil.createValue(valueStr, type, valueFactory);
473     }
474 
475     /**
476      * @deprecated since 4.5 - use {@link PropertyUtil#getJCRPropertyType(Object)} instead
477      */
478     @Deprecated
479     public static int getJCRPropertyType(Object obj) {
480         return PropertyUtil.getJCRPropertyType(obj);
481     }
482 
483     /**
484      * @deprecated since 4.5  - use {@link PropertyUtil#getValuesStringList(Value[])} instead
485      */
486     @Deprecated
487     public static List<String> getValuesStringList(Value[] values) {
488         return PropertyUtil.getValuesStringList(values);
489     }
490 
491     /**
492      * @deprecated since 4.5 - use {@link PropertyUtil#getDateFormat()} instead
493      */
494     @Deprecated
495     public static String getDateFormat() {
496         return PropertyUtil.getDateFormat();
497     }
498 }