1 /**
2 * Copyright 2005-2012 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.core.api.cache;
17
18
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.SortedMap;
26 import java.util.TreeMap;
27
28 /**
29 * A utility class that can be used to generate cache keys for more complex method signatures. Currently, the utilities
30 * on this class focus on generating cache keys for collections of objects. Since the caching infrastructure only
31 * supports a single @{code String} value as a key for cache entries, this utility helps to provide a standard way to
32 * generate such compound caching keys.
33 *
34 * <p>It is possible to use this utility class when specifying keys for cached objects using Spring's caching
35 * abstraction (which is what the Rice caching infrastructure is built on). This is possible using the Spring
36 * Expression Language (SPEL). An example might look something like the following:</p>
37 *
38 * <pre>
39 * {@code @Cacheable(value = "StuffCache", key="'ids=' + T(org.kuali.rice.core.api.cache.CacheKeyUtils).key(#p0)")
40 * List<Stuff> getStuff(List<String> stuffIds); }
41 * </pre>
42 *
43 * @author Kuali Rice Team (rice.collab@kuali.org)
44 * @since 2.0
45 */
46 public final class CacheKeyUtils {
47
48 private CacheKeyUtils() {
49 throw new UnsupportedOperationException();
50 }
51
52 /**
53 * Create a String key value out of a Collection. It accomplishes this by first sorting the given collection
54 * (entries in the collection must implement Comparable) and then construct a key based on the {@code .toString()}
55 * values of each item in the sorted collection.
56 *
57 * <p>The sorting of the given list happens on a copy of the list, so this method does not side-affect the given
58 * list.</p>
59 *
60 * @param col the collection. if null will return "", if empty, will return "[]"
61 * @param <K> the col type
62 *
63 * @return the collection as a string value
64 */
65 public static <K extends Comparable<K>> String key(Collection<K> col) {
66 if (col == null) {
67 return "";
68 }
69
70 final List<K> sorted = new ArrayList<K>(col);
71
72 if (col.size() > 1) {
73 Collections.sort(sorted);
74 }
75
76 final StringBuilder b = new StringBuilder("[");
77 for (K entry : sorted) {
78 if (entry != null) {
79 b.append(entry);
80 b.append(",");
81 }
82 }
83 b.append("]");
84 return b.toString();
85 }
86
87 /**
88 * Create a String key value out of a Map. It accomplishes this by first sorting the given map on it's keys
89 * (keys in the map must implement Comparable) and then construct a key based on the {@code .toString()}
90 * values of each item in the sorted collection.
91 *
92 * <p>The sorting of the given map happens on a copy of the map, so this method does not side-affect the given
93 * map.</p>
94 *
95 * @param col the map. if null will return "", if empty, will return "[]"
96 * @param <K> the col type
97 *
98 * @return the map as a string value
99 */
100 public static <K extends Comparable<K>> String mapKey(Map<K, ?> col) {
101 if (col == null) {
102 return "";
103 }
104
105 final List<K> sorted = new ArrayList<K>(col.keySet());
106
107 if (col.size() > 1) {
108 Collections.sort(sorted);
109 }
110
111 final StringBuilder b = new StringBuilder("[");
112 for (K entry : sorted) {
113 if (entry != null) {
114 b.append(entry);
115 b.append("|");
116 b.append(col.get(entry));
117 b.append(",");
118 }
119 }
120 b.append("]");
121 return b.toString();
122 }
123
124 }