View Javadoc
1   /**
2    * This file Copyright (c) 2008-2015 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       * @param node Content node
73       * @param handle Parent page handle or other prefix for links.
74       */
75      public NodeMapWrapper(Content node, String handle) {
76          super(node);
77          this.handle = handle;
78      }
79  
80      @Override
81      protected Content wrap(Content node) {
82          return new NodeMapWrapper(node, handle);
83      }
84  
85      /**
86       * @see java.util.Map#size()
87       */
88      @Override
89      public int size() {
90          return getWrappedContent().getNodeDataCollection().size();
91      }
92  
93      /**
94       * @see java.util.Map#isEmpty()
95       */
96      @Override
97      public boolean isEmpty() {
98          return getWrappedContent().getNodeDataCollection().isEmpty();
99      }
100 
101     /**
102      * @see java.util.Map#containsKey(java.lang.Object)
103      */
104     @Override
105     public boolean containsKey(Object key) {
106         return this.getWrappedContent().getNodeData((String) key).isExist() || hasProperty(key);
107     }
108 
109     /**
110      * @see java.util.Map#containsValue(java.lang.Object)
111      */
112     @Override
113     public boolean containsValue(Object value) {
114         // not implemented, only get() is needed
115         return false;
116     }
117 
118     /**
119      * Shortcut for Content.getNodeData(name).getString() or Content.getNodeData(name).getName().
120      * @see java.util.Map#get(Object)
121      */
122     @Override
123     public Object get(Object key) {
124         try {
125             if (!getWrappedContent().hasNodeData((String) key)) {
126                 // support the old lower case value
127                 if ("uuid".equalsIgnoreCase((String) key)) {
128                     key = "UUID";
129                 }
130                 if (hasProperty(key)) {
131                     try {
132                         return PropertyUtils.getProperty(this.getWrappedContent(), (String) key);
133                     }
134                     catch (Exception e) {
135                         log.error("can't read property " + key + " from the node " + this.getWrappedContent(), e);
136                     }
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         }
151         else if (type == PropertyType.BINARY) {
152             // only file path is supported
153             FileProperties props = new FileProperties(getWrappedContent(), (String) key);
154             value = props.getProperty(FileProperties.PATH);
155         }
156         else if (nodeData.isMultiValue() == NodeData.MULTIVALUE_TRUE) {
157 
158             Value[] values = nodeData.getValues();
159 
160             String[] valueStrings = new String[values.length];
161 
162             for (int j = 0; j < values.length; j++) {
163                 try {
164                     valueStrings[j] = values[j].getString();
165                 }
166                 catch (RepositoryException e) {
167                     log.debug(e.getMessage());
168                 }
169             }
170 
171             value = valueStrings;
172         }
173         else {
174             try {
175                 value = info.magnolia.link.LinkUtil.convertLinksFromUUIDPattern(nodeData.getString(), LinkTransformerManager.getInstance().getBrowserLink(handle));
176             }
177             catch (LinkException e) {
178                 log.warn("Failed to parse links with from " + nodeData.getName(), e);
179                 value = nodeData.getString();
180             }
181         }
182         return value;
183     }
184 
185     protected boolean hasProperty(Object key) {
186         try {
187             return PropertyUtils.getPropertyDescriptor(this.getWrappedContent(), (String) key) != null;
188         }
189         catch (Exception e) {
190             return false;
191         }
192     }
193 
194     /**
195      * @see java.util.Map#put(java.lang.Object, java.lang.Object)
196      */
197     @Override
198     public Object put(Object arg0, Object arg1) {
199         // not implemented, only get() is needed
200         return null;
201     }
202 
203     /**
204      * @see java.util.Map#remove(java.lang.Object)
205      */
206     @Override
207     public Object remove(Object key) {
208         // not implemented, only get() is needed
209         return null;
210     }
211 
212     /**
213      * @see java.util.Map#putAll(java.util.Map)
214      */
215     @Override
216     public void putAll(Map t) {
217         // not implemented, only get() is needed
218     }
219 
220     /**
221      * @see java.util.Map#clear()
222      */
223     @Override
224     public void clear() {
225         // not implemented, only get() is needed
226     }
227 
228     /**
229      * @see java.util.Map#keySet()
230      */
231     @Override
232     public Set<String> keySet() {
233         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
234         Set<String> keys = new HashSet<String>();
235         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext();) {
236             keys.add(iter.next().getName());
237         }
238 
239         return keys;
240     }
241 
242     /**
243      * @see java.util.Map#values()
244      */
245     @Override
246     public Collection<String> values() {
247         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
248         Collection<String> values = new ArrayList<String>();
249         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext();) {
250             values.add((iter.next()).getString());
251         }
252 
253         return values;
254     }
255 
256     /**
257      * @see java.util.Map#entrySet()
258      */
259     @Override
260     public Set entrySet() {
261         Collection<NodeData> nodeDataCollection = getWrappedContent().getNodeDataCollection();
262         Set<Map.Entry> keys = new HashSet<Map.Entry>();
263         for (Iterator<NodeData> iter = nodeDataCollection.iterator(); iter.hasNext();) {
264             NodeData nd = iter.next();
265             final String key = nd.getName();
266             final String value = nd.getString();
267             keys.add(new Map.Entry() {
268 
269                 @Override
270                 public Object getKey() {
271                     return key;
272                 }
273 
274                 @Override
275                 public Object getValue() {
276                     return value;
277                 }
278 
279                 @Override
280                 public Object setValue(Object value) {
281                     return value;
282                 }
283             });
284         }
285 
286         return keys;
287     }
288 }