View Javadoc
1   package com.randomnoun.common;
2   
3   /* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
4    * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
5    */
6   
7   import java.util.*;
8   
9   
10  /**
11   * This class is used to convert the Maps and Lists returned by Spring DAO into
12   * camelCase versions, which can be used when dealing with some databases 
13   * that return all column names in upper case. 
14   * 
15   * <p>Maps and Lists passed to this object will be modified in-place.
16   *
17   * <p>This object should be considered thread-safe, i.e. many threads may use a
18   * single instance of this object at a time.
19   *
20   * @author knoxg
21   */
22  public class CamelCaser {
23      
24      
25  
26      /** Internal map whose keys are ALLUPPERCASE text strings, and values are camelCase versions */
27      private Map<String, String> namingMap;
28  
29      /**
30       * Create a new map renamer. The list supplied to this constructor contains
31       * a list of Strings that may be used as keys in the maps to be renamed. Each
32       * String is the camelCase version to return.
33       *
34       * @param nameList
35       */
36      public CamelCaser(List<String> nameList) {
37          this.populateNamingMap(nameList);
38      }
39  
40      /**
41       * Creates a new CamelCaser object
42       *
43       * @param camelCaseNames A list of camelcased names, separated by commas.
44       *
45       * @throws NullPointerException if there was a problem loading the resource property list,
46       *   or the propertyKey does not exist in the resource.
47       */
48      public CamelCaser(String camelCaseNames) {
49          List<String> nameList = new ArrayList<String>();
50          StringTokenizer tokenizer = new StringTokenizer(camelCaseNames, ",");
51          String token;
52  
53          while (tokenizer.hasMoreElements()) {
54              token = tokenizer.nextToken();
55              nameList.add(token.trim());
56          }
57  
58          populateNamingMap(nameList);
59      }
60  
61      /** Private method used to create the namingMap object */
62      private void populateNamingMap(List<String> nameList) {
63          // don't croak if we're passed a null list 
64          if (nameList == null) {
65              nameList = new ArrayList<String>(0);
66          }
67  
68          namingMap = new HashMap<String, String>();
69  
70          String name;
71  
72          for (Iterator<String> i = nameList.iterator(); i.hasNext();) {
73              name = (String) i.next();
74              namingMap.put(name.toLowerCase(), name);
75          }
76      }
77  
78      /** Renames an individual string. If the camelCase version of the string is not
79       *  known, then it is returned without modification.
80       *
81       * @param string The String to be renamed
82       * @return The camelCase version of the String
83       */
84      public String renameString(String string) {
85          String result = (String) namingMap.get(string.toLowerCase());
86  
87          if (result == null) {
88              result = string;
89          }
90  
91          return result;
92      }
93  
94      /** Renames all the keys in the map. The map may itself contain Maps and Lists,
95       * which will also be renamed.
96       *
97       * @param map The map to rename
98       */
99      @SuppressWarnings("unchecked")
100 	public void renameMap(Map<String, Object> map) {
101         Object key;
102         Object value;
103         String newKey;
104 
105 
106         // we iterator on this object rather than map.keySet().iterator(), 
107         // since we are modifying the keys in the map
108         // as we iterate. 
109         List<String> keyList = new ArrayList<String>(map.keySet());
110 
111         for (Iterator<String> i = keyList.iterator(); i.hasNext();) {
112             key = i.next();
113             value = map.get(key);
114 
115             if (key instanceof String) {
116                 newKey = renameString((String) key);
117                 map.remove(key);
118                 map.put(newKey, value);
119             }
120 
121             // recurse through this structure
122             if (value instanceof Map) {
123                 renameMap((Map<String, Object>) value);
124             } else if (value instanceof List) {
125                 renameList((List<?>) value);
126             }
127         }
128     }
129 
130     /** Renames all the objects in a list. Any Maps or Lists contained with the List
131      * will be recursed into.
132      *
133      * @param list The list containing maps to rename.
134      */
135     @SuppressWarnings("unchecked")
136 	public void renameList(List<? extends Object> list) {
137         Object obj;
138 
139         for (Iterator<? extends Object> i = list.iterator(); i.hasNext();) {
140             obj = i.next();
141 
142             // recurse through this structure
143             if (obj instanceof Map) {
144                 renameMap((Map<String, Object>) obj);
145             } else if (obj instanceof List) {
146                 renameList((List<?>) obj);
147             }
148         }
149     }
150 }