View Javadoc
1   /*
2    * #%L
3    * Nuiton Decorator
4    * %%
5    * Copyright (C) 2011 CodeLutin, Tony Chemit
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  package org.nuiton.decorator;
23  
24  import org.apache.commons.jxpath.DynamicPropertyHandler;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import java.util.Collection;
29  import java.util.Iterator;
30  import java.util.Map;
31  import java.util.Set;
32  
33  /**
34   * A extended handler to deal with map in JXPath contexts.
35   * <p/>
36   * The basic one in JXPath api only deals with map keys as string.
37   * <p/>
38   * We offers a hook in method {@link #getKey(Object)} to obtain a string
39   * representation of a real object in map (key or value).
40   * <p/>
41   * More over, you can also access directly to a key or a value, using this
42   * syntax :
43   * <p/>
44   * <pre>context.getValue(".[@name='key:programme2']")</pre>
45   * <pre>context.getValue(".[@name='value:programme2']")</pre>
46   * <p/>
47   * If the values are iterable, then will scan inot it when looking for a direct
48   * value.
49   *
50   * @author tchemit <chemit@codelutin.com>
51   * @see DynamicPropertyHandler
52   * @since 2.3
53   */
54  public class MapPropertyHandler implements DynamicPropertyHandler {
55  
56      /** Logger */
57      private static final Log log =
58              LogFactory.getLog(MapPropertyHandler.class);
59  
60      @Override
61      public String[] getPropertyNames(Object object) {
62          Map<?, ?> map = (Map<?, ?>) object;
63          Set<?> set = map.keySet();
64          String[] names = new String[set.size()];
65          Iterator<?> it = set.iterator();
66          for (int i = 0; i < names.length; i++) {
67              Object o = it.next();
68              names[i] = getKey(o);
69          }
70          return names;
71      }
72  
73      @Override
74      public Object getProperty(Object object, String propertyName) {
75          Map<?, ?> map = (Map<?, ?>) object;
76          boolean getKey = false;
77          Object property0;
78          if (propertyName.startsWith("value:")) {
79              propertyName = propertyName.substring(6);
80              if (log.isDebugEnabled()) {
81                  log.debug("property value name " + propertyName);
82              }
83              property0 = getPropertyValue(map, propertyName);
84              if (log.isDebugEnabled()) {
85                  log.debug("property value = " + property0);
86              }
87              return property0;
88          }
89          if (propertyName.startsWith("key:")) {
90              propertyName = propertyName.substring(4);
91              getKey = true;
92          }
93          property0 = getPropertyKey(map, propertyName);
94          Object result = null;
95          if (property0 != null) {
96              if (getKey) {
97                  result = property0;
98              } else {
99                  result = map.get(property0);
100             }
101         }
102         return result;
103     }
104 
105     @Override
106     public void setProperty(Object object, String propertyName, Object value) {
107         Map map = (Map) object;
108         Object property0 = getPropertyKey(map, propertyName);
109         if (property0 != null) {
110             map.put(property0, value);
111         }
112     }
113 
114     /**
115      * Obtain the key from the map keys which matches the given {@code key}.
116      * <p/>
117      * To compare object ot string, please refers to the method {@link
118      * #getKey(Object)}.
119      *
120      * @param map the map to scan
121      * @param key the string representation of the required key as object
122      * @return the found key, or {@code null} if not found.
123      */
124     public Object getPropertyKey(Map<?, ?> map, String key) {
125         Set<?> set = map.keySet();
126         for (Object o : set) {
127             String k = getKey(o);
128             if (key.equals(k)) {
129                 return o;
130             }
131         }
132         return null;
133     }
134 
135     /**
136      * Obtain the value from the map values which matches the given {@code
137      * value}.
138      * <p/>
139      * To compare object to string, please refer to the method {@link
140      * #getKey(Object)}.
141      *
142      * @param map   the map to scan
143      * @param value the string representation of the value
144      * @return the found value, or {@code null} if not found.}
145      */
146     public Object getPropertyValue(Map<?, ?> map, String value) {
147         Collection<?> set = map.values();
148         for (Object o : set) {
149             if (o instanceof Iterable<?>) {
150                 Iterable<?> c = (Iterable<?>) o;
151                 for (Object oo : c) {
152                     String k = getKey(oo);
153                     if (value.equals(k)) {
154                         return oo;
155                     }
156                 }
157                 continue;
158             }
159             String k = getKey(o);
160             if (value.equals(k)) {
161                 return o;
162             }
163         }
164         return null;
165     }
166 
167     /**
168      * Obtain a string representation of an object.
169      *
170      * @param o the object to decorate
171      * @return the string representation of the object
172      */
173     protected String getKey(Object o) {
174         String k = String.valueOf(o);
175         return k;
176     }
177 }