View Javadoc
1   /**
2    * This file Copyright (c) 2008-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.cms.util;
35  
36  import info.magnolia.cms.beans.runtime.FileProperties;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.cms.core.NodeData;
39  import info.magnolia.link.LinkException;
40  import info.magnolia.link.LinkTransformerManager;
41  
42  import java.util.ArrayList;
43  import java.util.Collection;
44  import java.util.HashSet;
45  import java.util.Iterator;
46  import java.util.Map;
47  import java.util.Set;
48  
49  import javax.jcr.PropertyType;
50  import javax.jcr.RepositoryException;
51  import javax.jcr.Value;
52  
53  import org.apache.commons.beanutils.PropertyUtils;
54  import org.slf4j.Logger;
55  import org.slf4j.LoggerFactory;
56  
57  
58  /**
59   * Wrapper for a content Node which exposes a Map interface, used to access its content using jstl.
60   */
61  public class NodeMapWrapper extends ContentWrapper implements Map {
62  
63      private static final Logger log = LoggerFactory.getLogger(NodeMapWrapper.class);
64  
65      /**
66       * Handle used to construct links.
67       */
68      private final String handle;
69  
70      /**
71       * Instantiates a new NodeMapWrapper for the given node.
72       *
73       * @param node Content node
74       * @param handle Parent page handle or other prefix for links.
75       */
76      public NodeMapWrapper(Content node, String handle) {
77          super(node);
78          this.handle = handle;
79      }
80  
81      @Override
82      protected Content wrap(Content node) {
83          return new NodeMapWrapper(node, handle);
84      }
85  
86      /**
87       * @see java.util.Map#size()
88       */
89      @Override
90      public int size() {
91          return getWrappedContent().getNodeDataCollection().size();
92      }
93  
94      /**
95       * @see java.util.Map#isEmpty()
96       */
97      @Override
98      public boolean isEmpty() {
99          return getWrappedContent().getNodeDataCollection().isEmpty();
100     }
101 
102     /**
103      * @see java.util.Map#containsKey(java.lang.Object)
104      */
105     @Override
106     public boolean containsKey(Object key) {
107         return this.getWrappedContent().getNodeData((String) key).isExist() || hasProperty(key);
108     }
109 
110     /**
111      * @see java.util.Map#containsValue(java.lang.Object)
112      */
113     @Override
114     public boolean containsValue(Object value) {
115         // not implemented, only get() is needed
116         return false;
117     }
118 
119     /**
120      * Shortcut for Content.getNodeData(name).getString() or Content.getNodeData(name).getName().
121      *
122      * @see java.util.Map#get(Object)
123      */
124     @Override
125     public Object get(Object key) {
126         try {
127             if (!getWrappedContent().hasNodeData((String) key)) {
128                 // support the old lower case value
129                 if ("uuid".equalsIgnoreCase((String) key)) {
130                     key = "UUID";
131                 }
132                 if (hasProperty(key)) {
133                     try {
134                         return PropertyUtils.getProperty(this.getWrappedContent(), (String) key);
135                     } catch (Exception e) {
136                         log.error("can't read property {} from the node {}", key, this.getWrappedContent(), e);
137                     }
138                 }
139             }
140         } catch (RepositoryException e) {
141             // should really not happen
142             log.error("can't check for node data {{}}", key, e);
143         }
144 
145         NodeData nodeData = getWrappedContent().getNodeData((String) key);
146         Object value;
147         int type = nodeData.getType();
148         if (type == PropertyType.DATE) {
149             value = nodeData.getDate();
150         } else if (type == PropertyType.BINARY) {
151             // only file path is supported
152             FileProperties props = new FileProperties(getWrappedContent(), (String) key);
153             value = props.getProperty(FileProperties.PATH);
154         } else if (nodeData.isMultiValue() == NodeData.MULTIVALUE_TRUE) {
155 
156             Value[] values = nodeData.getValues();
157 
158             String[] valueStrings = new String[values.length];
159 
160             for (int j = 0; j < values.length; j++) {
161                 try {
162                     valueStrings[j] = values[j].getString();
163                 } catch (RepositoryException e) {
164                     log.debug(e.getMessage());
165                 }
166             }
167 
168             value = valueStrings;
169         } else {
170             try {
171                 value = info.magnolia.link.LinkUtil.convertLinksFromUUIDPattern(nodeData.getString(), LinkTransformerManager.getInstance().getBrowserLink(handle));
172             } catch (LinkException e) {
173                 log.warn("Failed to parse links with from {}", nodeData.getName(), e);
174                 value = nodeData.getString();
175             }
176         }
177         return value;
178     }
179 
180     protected boolean hasProperty(Object key) {
181         try {
182             return PropertyUtils.getPropertyDescriptor(this.getWrappedContent(), (String) key) != null;
183         } catch (Exception e) {
184             return false;
185         }
186     }
187 
188     /**
189      * @see java.util.Map#put(java.lang.Object, java.lang.Object)
190      */
191     @Override
192     public Object put(Object arg0, Object arg1) {
193         // not implemented, only get() is needed
194         return null;
195     }
196 
197     /**
198      * @see java.util.Map#remove(java.lang.Object)
199      */
200     @Override
201     public Object remove(Object key) {
202         // not implemented, only get() is needed
203         return null;
204     }
205 
206     /**
207      * @see java.util.Map#putAll(java.util.Map)
208      */
209     @Override
210     public void putAll(Map t) {
211         // not implemented, only get() is needed
212     }
213 
214     /**
215      * @see java.util.Map#clear()
216      */
217     @Override
218     public void clear() {
219         // not implemented, only get() is needed
220     }
221 
222     /**
223      * @see java.util.Map#keySet()
224      */
225     @Override
226     public Set<String> keySet() {
227         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
228         Set<String> keys = new HashSet<String>();
229         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext(); ) {
230             keys.add(iter.next().getName());
231         }
232 
233         return keys;
234     }
235 
236     /**
237      * @see java.util.Map#values()
238      */
239     @Override
240     public Collection<String> values() {
241         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
242         Collection<String> values = new ArrayList<String>();
243         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext(); ) {
244             values.add((iter.next()).getString());
245         }
246 
247         return values;
248     }
249 
250     /**
251      * @see java.util.Map#entrySet()
252      */
253     @Override
254     public Set entrySet() {
255         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
256         Set<Map.Entry> keys = new HashSet<Map.Entry>();
257         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext(); ) {
258             NodeData nd = iter.next();
259             final String key = nd.getName();
260             final String value = nd.getString();
261             keys.add(new Map.Entry() {
262 
263                 @Override
264                 public Object getKey() {
265                     return key;
266                 }
267 
268                 @Override
269                 public Object getValue() {
270                     return value;
271                 }
272 
273                 @Override
274                 public Object setValue(Object value) {
275                     return value;
276                 }
277             });
278         }
279 
280         return keys;
281     }
282 }