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.freemarker.models;
35  
36  import info.magnolia.jcr.util.ContentMap;
37  import info.magnolia.jcr.util.NodeUtil;
38  
39  import java.util.ArrayList;
40  import java.util.Collection;
41  
42  import javax.jcr.Node;
43  import javax.jcr.RepositoryException;
44  
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  
48  import freemarker.template.AdapterTemplateModel;
49  import freemarker.template.ObjectWrapper;
50  import freemarker.template.SimpleCollection;
51  import freemarker.template.TemplateCollectionModel;
52  import freemarker.template.TemplateHashModelEx;
53  import freemarker.template.TemplateModel;
54  import freemarker.template.TemplateModelException;
55  import freemarker.template.TemplateNodeModel;
56  import freemarker.template.TemplateScalarModel;
57  import freemarker.template.TemplateSequenceModel;
58  
59  /**
60   * A wrapper for Content nodes. Exposes properties using an HashModel (.property, ?size, ...) a hierarchy (TemplateNodeModel: ?children, ?parent, ...) and as a scalar (returns the node name)
61   *
62   * @author Chris Miner
63   * @author gjoseph
64   * @version $Revision: $ ($Author: $)
65   */
66  public class ContentMapModel implements TemplateHashModelEx, TemplateNodeModel, TemplateScalarModel, AdapterTemplateModel {
67  
68      private static final Logger log = LoggerFactory.getLogger(ContentMapModel.class);
69  
70      static final MagnoliaModelFactory FACTORY = new MagnoliaModelFactory() {
71          @Override
72          public Class factoryFor() {
73              return ContentMap.class;
74          }
75  
76          @Override
77          public AdapterTemplateModel create(Object object, ObjectWrapper wrapper) {
78              return new ContentMapModel((ContentMap) object, (MagnoliaObjectWrapper) wrapper);
79          }
80      };
81  
82      private final ContentMap content;
83      private final MagnoliaObjectWrapper wrapper;
84  
85      ContentMapModel(ContentMap content, MagnoliaObjectWrapper wrapper) {
86          this.content = content;
87          this.wrapper = wrapper;
88      }
89  
90      @Override
91      public String getAsString() {
92          return (String) content.get("@name");
93      }
94  
95      @Override
96      public TemplateModel get(String key) throws TemplateModelException {
97          return wrapper.wrap(content.get(key));
98      }
99  
100     @Override
101     public boolean isEmpty() throws TemplateModelException {
102         return (size() == 0);
103     }
104 
105     @Override
106     public int size() throws TemplateModelException {
107         return content.size();
108     }
109 
110     @Override
111     public TemplateCollectionModel keys() throws TemplateModelException {
112         return new SimpleCollection(content.keySet().iterator());
113     }
114 
115     @Override
116     public TemplateCollectionModel values() throws TemplateModelException {
117         return (TemplateCollectionModel) wrapper.wrap(content.values().iterator());
118     }
119 
120     @Override
121     public TemplateNodeModel getParentNode() throws TemplateModelException {
122         try {
123             // todo : check if this is the root?
124             // content.getLevel() == 0;
125             final ContentMap parent = new ContentMap(content.getJCRNode().getParent());
126             return (TemplateNodeModel) wrapper.wrap(parent);
127         } catch (RepositoryException e) {
128             throw new TemplateModelException("Can't get parent of " + content + ":" + e.getMessage(), e);
129         }
130     }
131 
132     /**
133      * This returns all children, except nodes or jcr: types and mgnl:metaData.
134      */
135     @Override
136     public TemplateSequenceModel getChildNodes() throws TemplateModelException {
137         Collection<Node> children;
138         try {
139             children = NodeUtil.asList(NodeUtil.getNodes(content.getJCRNode()));
140         } catch (RepositoryException e) {
141             log.error("Failed to read children of " + content.getJCRNode(), e);
142             children = new ArrayList<Node>();
143         }
144         return (TemplateSequenceModel) wrapper.wrap(children);
145     }
146 
147     @Override
148     public String getNodeName() throws TemplateModelException {
149         return (String) content.get("@name");
150     }
151 
152     @Override
153     public String getNodeType() throws TemplateModelException {
154         return content.get("@nodeType").toString();
155     }
156 
157     @Override
158     public String getNodeNamespace() throws TemplateModelException {
159         return null; // non XML implementation
160     }
161 
162     @Override
163     public Object getAdaptedObject(Class hint) {
164         return this.content;
165     }
166 
167     public Node getJCRNode() {
168         return content.getJCRNode();
169     }
170 }