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