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