View Javadoc
1   /**
2    * This file Copyright (c) 2003-2018 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  public class ContentMapModel implements TemplateHashModelEx, TemplateNodeModel, TemplateScalarModel, AdapterTemplateModel {
63  
64      private static final Logger log = LoggerFactory.getLogger(ContentMapModel.class);
65  
66      static final MagnoliaModelFactory FACTORY = new MagnoliaModelFactory() {
67          @Override
68          public Class factoryFor() {
69              return ContentMap.class;
70          }
71  
72          @Override
73          public AdapterTemplateModel create(Object object, ObjectWrapper wrapper) {
74              return new ContentMapModel((ContentMap) object, (MagnoliaObjectWrapper) wrapper);
75          }
76      };
77  
78      private final ContentMap content;
79      private final MagnoliaObjectWrapper wrapper;
80  
81      ContentMapModel(ContentMap content, MagnoliaObjectWrapper wrapper) {
82          this.content = content;
83          this.wrapper = wrapper;
84      }
85  
86      @Override
87      public String getAsString() {
88          return (String) content.get("@name");
89      }
90  
91      @Override
92      public TemplateModel get(String key) throws TemplateModelException {
93          return wrapper.wrap(content.get(key));
94      }
95  
96      @Override
97      public boolean isEmpty() throws TemplateModelException {
98          return (size() == 0);
99      }
100 
101     @Override
102     public int size() throws TemplateModelException {
103         return content.size();
104     }
105 
106     @Override
107     public TemplateCollectionModel keys() throws TemplateModelException {
108         return new SimpleCollection(content.keySet().iterator());
109     }
110 
111     @Override
112     public TemplateCollectionModel values() throws TemplateModelException {
113         return (TemplateCollectionModel) wrapper.wrap(content.values().iterator());
114     }
115 
116     @Override
117     public TemplateNodeModel getParentNode() throws TemplateModelException {
118         try {
119             // todo : check if this is the root?
120             // content.getLevel() == 0;
121             final ContentMap parent = new ContentMap(content.getJCRNode().getParent());
122             return (TemplateNodeModel) wrapper.wrap(parent);
123         } catch (RepositoryException e) {
124             throw new TemplateModelException("Can't get parent of " + content + ":" + e.getMessage(), e);
125         }
126     }
127 
128     /**
129      * This returns all children, except nodes or jcr: types and mgnl:metaData.
130      */
131     @Override
132     public TemplateSequenceModel getChildNodes() throws TemplateModelException {
133         Collection<Node> children;
134         try {
135             children = NodeUtil.asList(NodeUtil.getNodes(content.getJCRNode()));
136         } catch (RepositoryException e) {
137             log.error("Failed to read children of {}", content.getJCRNode(), e);
138             children = new ArrayList<Node>();
139         }
140         return (TemplateSequenceModel) wrapper.wrap(children);
141     }
142 
143     @Override
144     public String getNodeName() throws TemplateModelException {
145         return (String) content.get("@name");
146     }
147 
148     @Override
149     public String getNodeType() throws TemplateModelException {
150         return content.get("@nodeType").toString();
151     }
152 
153     @Override
154     public String getNodeNamespace() throws TemplateModelException {
155         return null; // non XML implementation
156     }
157 
158     @Override
159     public Object getAdaptedObject(Class hint) {
160         return this.content;
161     }
162 
163     public Node getJCRNode() {
164         return content.getJCRNode();
165     }
166 }