View Javadoc

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