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.core;
35  
36  import info.magnolia.cms.security.AccessManager;
37  import info.magnolia.jcr.util.PropertyUtil;
38  import info.magnolia.repository.RepositoryConstants;
39  
40  import java.util.Calendar;
41  import java.util.GregorianCalendar;
42  import java.util.TimeZone;
43  
44  import javax.jcr.Node;
45  import javax.jcr.PathNotFoundException;
46  import javax.jcr.Property;
47  import javax.jcr.RepositoryException;
48  
49  import org.apache.commons.lang.StringUtils;
50  import org.apache.commons.lang.builder.ToStringBuilder;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  /**
55   * Meta data of a content like creation date, modification date, assigned template, ...
56   *
57   * @version $Id$
58   */
59  public class MetaData {
60      private static final Logger log = LoggerFactory.getLogger(MetaData.class);
61  
62      /**
63       * Top level atoms viewed as metadata of the specified content these must be set by the authoring system itself, but
64       * could be changed via custom templates if necessary.
65       */
66      public static final String TITLE = "title";
67  
68      public static final String CREATION_DATE = "creationdate";
69  
70      public static final String LAST_MODIFIED = "lastmodified";
71  
72      public static final String LAST_ACTION = "lastaction";
73  
74      public static final String AUTHOR_ID = "authorid";
75  
76      public static final String ACTIVATOR_ID = "activatorid";
77  
78      public static final String TEMPLATE = "template";
79  
80      public static final String TEMPLATE_TYPE = "templatetype";
81  
82      public static final String ACTIVATED = "activated";
83  
84      /**
85       * Name of the Node hosting the MetaData.
86       */
87      public static final String DEFAULT_META_NODE = "MetaData";
88  
89      public static final int ACTIVATION_STATUS_NOT_ACTIVATED = 0;
90  
91      public static final int ACTIVATION_STATUS_MODIFIED = 1;
92  
93      public static final int ACTIVATION_STATUS_ACTIVATED = 2;
94  
95      /**
96       * meta data node.
97       */
98      private Node node;
99  
100     /**
101      * @param workingNode
102      *            current <code>Node</code> on which <code>MetaData</code> is requested
103      * @param ignoredAccessManager
104      *            no longer required hence use other constructor.
105      *
106      * @deprecated since 4.5 use MetaData(Node) instead.
107      */
108     protected MetaData(Node workingNode, AccessManager ignoredAccessManager) {
109         this(workingNode);
110     }
111 
112     /**
113      * @param workingNode
114      *            current <code>Node</code> on which <code>MetaData</code> is requested
115      */
116     public MetaData(Node workingNode) {
117         try {
118             this.node = workingNode.getNode(DEFAULT_META_NODE);
119         } catch (PathNotFoundException e) {
120             try {
121                 log.debug("{} does not support MetaData, check node type definition of {}", workingNode.getPath(),
122                         workingNode.getPrimaryNodeType().getName());
123             } catch (RepositoryException re) {
124                 // should never come here
125             }
126         } catch (RepositoryException re) {
127             log.error(re.getMessage(), re);
128         }
129     }
130 
131     public String getHandle() throws RepositoryException {
132         return this.node.getPath();
133     }
134 
135     /**
136      * Part of metadata, same as name of actual storage node. This value is unique at the hierarchy level context.
137      *
138      * @return String value of the requested metadata
139      */
140     public String getLabel() {
141         if (node == null) {
142             if (log.isDebugEnabled()) {
143                 log.debug("MetaData has not been created or this node does not support MetaData");
144             }
145         } else {
146             try {
147                 return this.node.getName();
148             } catch (RepositoryException e) {
149                 log.error(e.getMessage(), e);
150             }
151         }
152         return StringUtils.EMPTY;
153     }
154 
155     /**
156      * get property name with the prefix.
157      *
158      * @return name with namespace prefix
159      */
160     private String getInternalPropertyName(String name) {
161         if (StringUtils.indexOf(name, RepositoryConstants.NAMESPACE_PREFIX + ":") != 0) {
162             return RepositoryConstants.NAMESPACE_PREFIX + ":" + name;
163         }
164         return name;
165     }
166 
167     /**
168      * Part of metadata , could be used as html header.
169      *
170      * @return String value of the requested metadata
171      */
172     public String getTitle() {
173         return getStringProperty(TITLE);
174     }
175 
176     /**
177      * Part of metadata, could be used as html header.
178      *
179      * @param value
180      */
181     public void setTitle(String value) {
182         setProperty(TITLE, value);
183     }
184 
185     /**
186      * Part of metadata, adds creation date of the current node.
187      */
188     public void setCreationDate() {
189         Calendar value = new GregorianCalendar(TimeZone.getDefault());
190         setProperty(CREATION_DATE, value);
191     }
192 
193     /**
194      * Part of metadata, get creation date of the current node.
195      *
196      * @return Calendar
197      */
198     public Calendar getCreationDate() {
199         return this.getDateProperty(CREATION_DATE);
200     }
201 
202     /**
203      * Part of metadata, adds activated status of the current node.
204      */
205     public void setActivated() {
206         setProperty(ACTIVATED, true);
207     }
208 
209     /**
210      * Part of metadata, adds activated status of the current node.
211      */
212     public void setUnActivated() {
213         setProperty(ACTIVATED, false);
214     }
215 
216     /**
217      * Part of metadata, get last activated status of the current node.
218      *
219      * @return Calendar
220      */
221     public boolean getIsActivated() {
222         return getBooleanProperty(ACTIVATED);
223     }
224 
225     /**
226      * Returns one of the ACTIVATION_STATUS_* constants.
227      */
228     public int getActivationStatus() {
229         if (getIsActivated()) {
230             if (getModificationDate() != null && getModificationDate().after(getLastActionDate())) {
231                 // node has been modified after last activation
232                 return ACTIVATION_STATUS_MODIFIED;
233             }
234             // activated and not modified ever since
235             return ACTIVATION_STATUS_ACTIVATED;
236         }
237         // never activated or deactivated
238         return ACTIVATION_STATUS_NOT_ACTIVATED;
239     }
240 
241     /**
242      * Part of metadata, adds activated date of the current node.
243      */
244     public void setLastActivationActionDate() {
245         Calendar value = new GregorianCalendar(TimeZone.getDefault());
246         setProperty(LAST_ACTION, value);
247     }
248 
249     /**
250      * Part of metadata, get last activated/de- date of the current node.
251      *
252      * @return Calendar
253      */
254     public Calendar getLastActionDate() {
255         return getDateProperty(LAST_ACTION);
256     }
257 
258     /**
259      * Part of metadata, adds modification date of the current node.
260      */
261     public void setModificationDate() {
262         Calendar value = new GregorianCalendar(TimeZone.getDefault());
263         setProperty(LAST_MODIFIED, value);
264     }
265 
266     /**
267      * Get last modified date of the node to which this meta data belongs or creation date in case content was not
268      * modified since.
269      *
270      * @return Calendar when last modification date can't be found.
271      */
272     public Calendar getModificationDate() {
273         Calendar modDate = getDateProperty(LAST_MODIFIED);
274         if (modDate == null) {
275             modDate = getCreationDate();
276         }
277         return modDate;
278     }
279 
280     /**
281      * Part of metadata, last known author of this node.
282      *
283      * @return String value of the requested metadata
284      */
285     public String getAuthorId() {
286         return getStringProperty(AUTHOR_ID);
287     }
288 
289     /**
290      * Part of metadata, current logged-in author who did some action on this page.
291      *
292      * @param value
293      */
294     public void setAuthorId(String value) {
295         setProperty(AUTHOR_ID, value);
296     }
297 
298     /**
299      * Part of metadata, last known activator of this node.
300      *
301      * @return String value of the requested metadata
302      */
303     public String getActivatorId() {
304         return getStringProperty(ACTIVATOR_ID);
305     }
306 
307     /**
308      * Part of metadata, current logged-in author who last activated this page.
309      *
310      * @param value
311      */
312     public void setActivatorId(String value) {
313         setProperty(ACTIVATOR_ID, value);
314     }
315 
316     /**
317      * Part of metadata, template which will be used to render content of this node.
318      *
319      * @return String value of the requested metadata
320      */
321     public String getTemplate() {
322         return getStringProperty(TEMPLATE);
323     }
324 
325     /**
326      * Part of metadata, template which will be used to render content of this node.
327      *
328      * @param value
329      */
330     public void setTemplate(String value) {
331         setProperty(TEMPLATE, value);
332     }
333 
334     public void setProperty(String name, String value) {
335         setJCRProperty(name, value);
336     }
337 
338     public void setProperty(String name, long value) {
339         setJCRProperty(name, value);
340     }
341 
342     public void setProperty(String name, double value) {
343         setJCRProperty(name, value);
344     }
345 
346     public void setProperty(String name, boolean value) {
347         setJCRProperty(name, value);
348     }
349 
350     public void setProperty(String name, Calendar value) {
351         setJCRProperty(name, value);
352     }
353 
354     private void setJCRProperty(String name, Object value) {
355         final String propName = this.getInternalPropertyName(name);
356         if (node == null) {
357             log.debug("MetaData has not been created or this node does not support MetaData. Cannot set property {}",
358                     propName);
359         } else {
360             try {
361                 PropertyUtil.setProperty(node, propName, value);
362             } catch (RepositoryException re) {
363                 log.error(re.getMessage(), re);
364             }
365         }
366     }
367 
368     public boolean getBooleanProperty(String name) {
369         try {
370             final Property property = getJCRProperty(name);
371             if (property != null) {
372                 return property.getBoolean();
373             }
374         } catch (RepositoryException re) {
375             log.error(re.getMessage(), re);
376         }
377         return false;
378     }
379 
380     public double getDoubleProperty(String name) {
381         try {
382             final Property property = getJCRProperty(name);
383             if (property != null) {
384                 return property.getDouble();
385             }
386         } catch (RepositoryException re) {
387             log.error(re.getMessage(), re);
388         }
389         return 0d;
390     }
391 
392     public long getLongProperty(String name) {
393         try {
394             final Property property = getJCRProperty(name);
395             if (property != null) {
396                 return property.getLong();
397             }
398         } catch (RepositoryException re) {
399             log.error(re.getMessage(), re);
400         }
401         return 0L;
402     }
403 
404     public String getStringProperty(String name) {
405         try {
406             final Property property = getJCRProperty(name);
407             if (property != null) {
408                 return property.getString();
409             }
410         } catch (RepositoryException re) {
411             log.error(re.getMessage(), re);
412         }
413         return StringUtils.EMPTY;
414     }
415 
416     public Calendar getDateProperty(String name) {
417         try {
418             final Property property = getJCRProperty(name);
419             if (property != null) {
420                 return property.getDate();
421             }
422         } catch (RepositoryException re) {
423             log.error(re.getMessage(), re);
424         }
425         return null;
426     }
427 
428     /**
429      * remove specified property.
430      *
431      * @param name
432      *            of the property to be removed
433      * @throws PathNotFoundException
434      *             if property does not exist
435      * @throws RepositoryException
436      *             if unable to remove
437      */
438     public void removeProperty(String name) throws PathNotFoundException, RepositoryException {
439         this.node.getProperty(this.getInternalPropertyName(name)).remove();
440     }
441 
442     private Property getJCRProperty(String name) throws RepositoryException {
443         final String propName = this.getInternalPropertyName(name);
444         if (node == null) {
445             log.debug("MetaData has not been created or this node does not support MetaData. Cannot get property {}",
446                     propName);
447         } else {
448             try {
449                 return node.getProperty(propName);
450             } catch (PathNotFoundException re) {
451                 log.debug("PathNotFoundException for property [{}] in node {}", propName, node);
452             }
453         }
454         return null;
455     }
456 
457     /**
458      * check if property exists.
459      *
460      * @param name
461      * @return true if the specified property exist
462      *
463      * @deprecated since 4.0 - not used
464      */
465     @Deprecated
466     public boolean hasProperty(String name) {
467         try {
468             return this.node.hasProperty(this.getInternalPropertyName(name));
469         } catch (RepositoryException re) {
470             log.error(re.getMessage(), re);
471         }
472         return false;
473     }
474 
475     @Override
476     public String toString() {
477         return new ToStringBuilder(this).append("title", this.getTitle()).append("template", this.getTemplate())
478                 .append("authorId", this.getAuthorId()).append("label", this.getLabel())
479                 .append("activatorId", this.getActivatorId()).append("isActivated", this.getIsActivated())
480                 .append("creationDate", this.getCreationDate()).append("lastActionDate", this.getLastActionDate())
481                 .append("modificationDate", this.getModificationDate()).toString();
482     }
483 }