View Javadoc

1   /**
2    * This file Copyright (c) 2010-2010 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.info/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.i18n.I18nContentSupportFactory;
37  import info.magnolia.cms.security.AccessDeniedException;
38  import info.magnolia.cms.util.NodeDataUtil;
39  import info.magnolia.cms.util.NodeTypeFilter;
40  import info.magnolia.context.MgnlContext;
41  import info.magnolia.logging.AuditLoggingUtil;
42  
43  import java.io.InputStream;
44  import java.util.ArrayList;
45  import java.util.Calendar;
46  import java.util.Collection;
47  import java.util.Comparator;
48  
49  import javax.jcr.PathNotFoundException;
50  import javax.jcr.PropertyType;
51  import javax.jcr.RepositoryException;
52  import javax.jcr.Value;
53  import javax.jcr.Workspace;
54  
55  import org.apache.commons.lang.StringUtils;
56  
57  /**
58   * A base class by implementing some default behavior.
59   * A subclass must carefully implement {@link #newNodeDataInstance(String, int, boolean)},
60   * {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, String, java.util.Comparator)} and
61   * {@link #getNodeDataCollection(String)}.
62   *
63   * @author pbaerfuss
64   * @version $Id$
65   */
66  public abstract class AbstractContent extends ContentHandler implements Content {
67      private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractContent.class);
68  
69      public Content createContent(String name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
70          return createContent(name, ItemType.CONTENT);
71      }
72  
73      public Content createContent(String name, ItemType contentType) throws PathNotFoundException, RepositoryException, AccessDeniedException {
74          return createContent(name, contentType.getSystemName());
75      }
76  
77      public NodeData createNodeData(String name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
78          return setNodeData(name, "");
79      }
80  
81      public NodeData createNodeData(String name, Value value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
82          return setNodeData(name, value);
83      }
84  
85      /**
86       * @deprecated
87       */
88      public NodeData createNodeData(String name, Value[] value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
89          return setNodeData(name, value);
90      }
91  
92      /**
93       * @deprecated 
94       */
95      public NodeData createNodeData(String name, int type) throws PathNotFoundException, RepositoryException, AccessDeniedException {
96          // set some default values to create the property
97          switch (type) {
98              case PropertyType.STRING:
99                  return setNodeData(name, StringUtils.EMPTY);
100             case PropertyType.BOOLEAN:
101                 return setNodeData(name, Boolean.FALSE);
102             case PropertyType.DATE:
103                 return setNodeData(name, Calendar.getInstance());
104             case PropertyType.LONG:
105                 return setNodeData(name, new Long(0));
106             case PropertyType.DOUBLE:
107                 return setNodeData(name, new Double(0.0));
108             default:
109                 return newNodeDataInstance(name, type, true);
110         }
111     }
112     
113     /**
114      * @deprecated
115      */
116     public NodeData createNodeData(String name, Object valueObj) throws RepositoryException {
117         return setNodeData(name, valueObj);
118     }
119     
120     /**
121      * {@inheritDoc}
122      * Delegates to {@link #newNodeDataInstance(String, int, boolean)} by setting the type to PropertyType.UNDEFINED. A subclass has to handle this by trying to determine the type if the node data exists. The reason for this is that implementations want to instantiate different node data classes per type
123      */
124     public NodeData getNodeData(String name) {
125         try {
126             // will try to determine the type if the node data exists, otherwise an non-mutable node data will be returned
127             return newNodeDataInstance(name, PropertyType.UNDEFINED, false);
128         }
129         catch(RepositoryException e){
130             throw new IllegalStateException("Can't instantiate node data " + name + " on node " + toString(), e);
131         }
132     }
133     
134     /**
135      * As defined in {@link Content#getNodeData(String)} this method always returns a node data object. If the type is {@link PropertyType#UNDEFINED} the implementation should check if the node data exists and determine the type to use.
136      * 
137      * @param createIfNotExisting if false an empty non-mutable node data will be returned if the node data doesn't exist otherwise a mutable nodedata object is returned (depending on the type)
138      */
139     abstract public NodeData newNodeDataInstance(String name, int type, boolean createIfNotExisting) throws AccessDeniedException, RepositoryException;
140 
141     /**
142      * Delegates to {@link NodeData#isExist()}.
143      */
144     public boolean hasNodeData(String name) throws RepositoryException {
145         return getNodeData(name).isExist();
146     }
147 
148     public NodeData setNodeData(String name, Value value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
149         NodeData nodeData = newNodeDataInstance(name, value.getType(), true);
150         nodeData.setValue(value);
151         return nodeData;
152     }
153 
154     public NodeData setNodeData(String name, Value[] value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
155         if(value.length == 0){
156             throw new IllegalArgumentException("Value array can't be empty");
157         }
158         NodeData nodeData = newNodeDataInstance(name, value[0].getType(), true);
159         nodeData.setValue(value);
160         return nodeData;
161     }
162     
163     public NodeData setNodeData(String name, boolean value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
164         NodeData nodeData = newNodeDataInstance(name, PropertyType.BOOLEAN, true);
165         nodeData.setValue(value);
166         return nodeData;
167     }
168     
169     public NodeData setNodeData(String name, long value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
170         NodeData nodeData = newNodeDataInstance(name, PropertyType.LONG, true);
171         nodeData.setValue(value);
172         return nodeData;
173     }
174     
175     public NodeData setNodeData(String name, double value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
176         NodeData nodeData = newNodeDataInstance(name, PropertyType.DOUBLE, true);
177         nodeData.setValue(value);
178         return nodeData;
179     }
180     
181     public NodeData setNodeData(String name, String value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
182         NodeData nodeData = newNodeDataInstance(name, PropertyType.STRING, true);
183         nodeData.setValue(value);
184         return nodeData;
185     }
186     
187     public NodeData setNodeData(String name, InputStream value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
188         NodeData nodeData = newNodeDataInstance(name, PropertyType.BINARY, true);
189         nodeData.setValue(value);
190         return nodeData;
191     }
192     
193     public NodeData setNodeData(String name, Calendar value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
194         NodeData nodeData = newNodeDataInstance(name, PropertyType.DATE, true);
195         nodeData.setValue(value);
196         return nodeData;
197     }
198     
199     public NodeData setNodeData(String name, Content value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
200         NodeData nodeData = newNodeDataInstance(name, PropertyType.STRING, true);
201         nodeData.setValue(value.getUUID());
202         return nodeData;
203     }
204     
205     /**
206      * Uses the {@link NodeDataUtil} to create and set the node data based on the object type.
207      */
208     public NodeData setNodeData(String name, Object value) throws PathNotFoundException, RepositoryException, AccessDeniedException {
209         NodeData nodeData = newNodeDataInstance(name, NodeDataUtil.getJCRPropertyType(value), true);
210         NodeDataUtil.setValue(nodeData, value);
211         return nodeData;
212     }
213     
214     public void deleteNodeData(String name) throws PathNotFoundException, RepositoryException {
215         getNodeData(name).delete();
216     }
217 
218     /**
219      * {@inheritDoc}
220      * Delegates to {@link #getChildren(ItemType)} passing the current node's type.
221      */
222     public Collection<Content> getChildren() {
223         String type = null;
224     
225         try {
226             type = this.getNodeTypeName();
227         }
228         catch (RepositoryException re) {
229             throw new RuntimeException("Can't read type of node [" + toString() + "]", re);
230     
231         }
232         // fix all getChildren calls from the root node
233         if ("rep:root".equalsIgnoreCase(type)) { //$NON-NLS-1$
234             type = ItemType.CONTENT.getSystemName();
235         }
236         // --------------------------------------------------
237         return this.getChildren(type);
238     }
239 
240     /**
241      * {@inheritDoc}
242      * Delegates to {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, java.util.Comparator).
243      */    
244     public Collection<Content> getChildren(ContentFilter filter) {
245         return getChildren(filter, null);
246     }
247 
248     /**
249      * {@inheritDoc}
250      * Delegates to {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, java.util.Comparator).
251      */    
252     public Collection<Content> getChildren(ItemType itemType) {
253         return getChildren(new NodeTypeFilter(itemType), null);
254     }
255 
256     /**
257      * {@inheritDoc}
258      * Delegates to {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, java.util.Comparator).
259      */
260     public Collection<Content> getChildren(String contentType) {
261         return getChildren(new NodeTypeFilter(contentType), null);
262     }
263 
264     /**
265      * {@inheritDoc}
266      * Delegates to {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, String, java.util.Comparator)}.
267      */    
268     public Collection<Content> getChildren(final String contentType, final String namePattern) {
269         return getChildren(new NodeTypeFilter(contentType), namePattern, null);
270     }
271 
272     /**
273      * {@inheritDoc}
274      * Delegates to {@link #getChildren(info.magnolia.cms.core.Content.ContentFilter, String, java.util.Comparator)}.
275      */
276     public Collection<Content> getChildren(ContentFilter filter, Comparator<Content> orderCriteria) {
277         return getChildren(filter, null, orderCriteria);
278     }
279 
280     /**
281      * @param namePattern ignored if null.
282      */
283     abstract public Collection<Content> getChildren(ContentFilter filter, String namePattern, Comparator<Content> orderCriteria);
284 
285     /**
286      * @deprecated
287      */
288     public Content getChildByName(String namePattern) {
289         Collection<Content> children = getChildren("nt:base", namePattern);;
290         if (!children.isEmpty()) {
291             return children.iterator().next();
292         }
293         return null;
294     }
295 
296     public Collection<NodeData> getNodeDataCollection() {
297         return getNodeDataCollection(null);
298     }
299 
300     protected Collection<NodeData> getBinaryNodeDatas(String namePattern) throws RepositoryException {
301         Collection<NodeData> nodeDatas = new ArrayList<NodeData>();
302         Collection<Content> binaryNodes = getChildren(ItemType.NT_RESOURCE, namePattern);
303         for (Content binaryNode : binaryNodes) {
304             nodeDatas.add(newNodeDataInstance(binaryNode.getName(), PropertyType.BINARY, false));
305         }
306         return nodeDatas;
307     }
308 
309 
310     public boolean hasChildren() {
311         return (this.getChildren().size() > 0);
312     }
313 
314     public boolean hasChildren(String contentType) {
315         return (this.getChildren(contentType).size() > 0);
316     }
317     
318     public void delete(String path) throws RepositoryException {
319         if(isNodeData(path)){
320             deleteNodeData(path);
321         }
322         else{
323             getContent(path).delete();
324         }
325     }
326 
327     public boolean isNodeData(String path) throws AccessDeniedException, RepositoryException {
328         return hasNodeData(path);
329     }
330 
331     public String getTemplate() {
332         return this.getMetaData().getTemplate();
333     }
334 
335     public String getTitle() {
336         return I18nContentSupportFactory.getI18nSupport().getNodeData(this, "title").getString();
337     }
338 
339     public void updateMetaData() throws RepositoryException, AccessDeniedException {
340         MetaData md = this.getMetaData();
341         md.setModificationDate();
342         md.setAuthorId(MgnlContext.getUser().getName());
343         AuditLoggingUtil.log( AuditLoggingUtil.ACTION_MODIFY, hierarchyManager.getName(),this.getItemType(), getHandle());
344     }
345 
346     public boolean isGranted(long permissions) {
347         return hierarchyManager.getAccessManager().isGranted(getHandle(), permissions);
348     }
349 
350     public Workspace getWorkspace() throws RepositoryException {
351         return getHierarchyManager().getWorkspace();
352     }
353     
354     public String toString() {
355         StringBuffer buffer = new StringBuffer();
356         buffer.append(getHierarchyManager() == null ? "null" : getHierarchyManager().getName());
357         buffer.append(":" + getHandle());
358         String type = "";
359         try {
360             type = getItemType().getSystemName();
361         }
362         catch (RepositoryException e) {
363             // ignore
364         }
365         buffer.append("[");
366         buffer.append(type);
367         buffer.append("]");
368 
369         return buffer.toString();
370     }
371 
372 
373 }