1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.ui.server.gwt;
17
18 import java.lang.ref.SoftReference;
19 import java.util.Collections;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Map.Entry;
24
25 import org.kuali.student.common.ui.client.service.SearchRpcService;
26 import org.kuali.student.r1.common.assembly.transform.IdTranslatorFilter;
27 import org.kuali.student.r2.common.exceptions.MissingParameterException;
28 import org.kuali.student.r1.common.search.dto.SearchParam;
29 import org.kuali.student.r1.common.search.dto.SearchRequest;
30 import org.kuali.student.r1.common.search.dto.SearchResult;
31 import org.kuali.student.r1.common.search.dto.SearchResultCell;
32 import org.kuali.student.r1.common.search.dto.SearchResultRow;
33 import org.kuali.student.r1.common.search.service.SearchDispatcher;
34 import org.springframework.beans.factory.InitializingBean;
35
36 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
37
38 public class SearchDispatchRpcGwtServlet extends RemoteServiceServlet implements SearchRpcService, InitializingBean {
39
40 private static final long serialVersionUID = 1L;
41
42 private IdTranslatorFilter idTranslatorFilter;
43
44 private SearchDispatcher searchDispatcher;
45
46 protected boolean cachingEnabled = false;
47 protected int searchCacheMaxSize = 20;
48 protected int searchCacheMaxAgeSeconds = 90;
49 protected Map<String,MaxAgeSoftReference<SearchResult>> searchCache;
50
51
52 public SearchDispatchRpcGwtServlet() {
53 super();
54 }
55
56
57
58
59
60
61
62
63 @Override
64 public SearchResult search(SearchRequest searchRequest) {
65 try
66 {
67 SearchResult searchResult = searchDispatcher.dispatchSearch(searchRequest);
68 List<SearchParam> params = searchRequest.getParams();
69 if (params != null && params.size() > 0) {
70 SearchParam firstParam = params.get(0);
71 if (firstParam.getKey().equals("lu.queryParam.cluVersionIndId")) {
72 doIdTranslation(searchResult);
73 }
74 }
75 return searchResult;
76 } catch (Exception ex) {
77
78 ex.printStackTrace();
79 throw new RuntimeException(ex);
80 }
81 }
82
83 @Override
84 public SearchResult cachingSearch(SearchRequest searchRequest) {
85 try
86 {
87 String cacheKey = searchRequest.toString();
88 if (cachingEnabled) {
89
90
91 MaxAgeSoftReference<SearchResult> ref = searchCache.get(cacheKey);
92 if (ref != null) {
93 SearchResult cachedSearchResult = ref.get();
94 if (cachedSearchResult != null) {
95 return cachedSearchResult;
96 }
97 }
98 }
99
100
101 SearchResult searchResult = search(searchRequest);
102
103 if (cachingEnabled) {
104
105 searchCache
106 .put(cacheKey, new MaxAgeSoftReference<SearchResult>(searchCacheMaxAgeSeconds, searchResult));
107 }
108
109 return searchResult;
110 } catch (Exception ex) {
111
112 ex.printStackTrace();
113 throw new RuntimeException(ex);
114 }
115 }
116
117 private void doIdTranslation(SearchResult searchResult) {
118 for (SearchResultRow searchResultRow : searchResult.getRows()) {
119 for (SearchResultCell searchResultCell : searchResultRow.getCells()) {
120 String value = searchResultCell.getValue();
121 if (value != null && value.startsWith("kuali.atp")) {
122 String newValue = idTranslatorFilter.getTranslationForAtp(value);
123 if (newValue != null) {
124 searchResultCell.setValue(newValue);
125 }
126 }
127 }
128 }
129 }
130
131 @Override
132 public void afterPropertiesSet() throws Exception {
133 if(cachingEnabled){
134 searchCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<SearchResult>>( searchCacheMaxSize ) );
135 }
136 }
137
138 public void setSearchDispatcher(SearchDispatcher searchDispatcher) {
139 this.searchDispatcher = searchDispatcher;
140 }
141
142 public void setIdTranslatorFilter(IdTranslatorFilter idTranslatorFilter) {
143 this.idTranslatorFilter = idTranslatorFilter;
144 }
145
146 public void setCachingEnabled(boolean cachingEnabled) {
147 this.cachingEnabled = cachingEnabled;
148 }
149
150 public void setSearchCacheMaxSize(int searchCacheMaxSize) {
151 this.searchCacheMaxSize = searchCacheMaxSize;
152 }
153
154 public void setSearchCacheMaxAgeSeconds(int searchCacheMaxAgeSeconds) {
155 this.searchCacheMaxAgeSeconds = searchCacheMaxAgeSeconds;
156 }
157
158
159
160
161
162
163
164
165 public class MaxAgeSoftReference<T> extends SoftReference<T> {
166
167 private long expires;
168
169 public MaxAgeSoftReference(long expires, T referent) {
170 super(referent);
171 this.expires = System.currentTimeMillis() + expires * 1000;
172 }
173
174 public boolean isValid() {
175 return System.currentTimeMillis() < expires;
176 }
177
178 public T get() {
179 return isValid() ? super.get() : null;
180 }
181
182 }
183
184
185
186
187
188 public class MaxSizeMap<K,V> extends LinkedHashMap<K,V> {
189 private static final long serialVersionUID = -5354227348838839919L;
190
191 private int maxSize;
192
193
194
195
196 public MaxSizeMap( int maxSize ) {
197 this( maxSize, false );
198 }
199
200
201
202
203 public MaxSizeMap( int maxSize, boolean accessOrder ) {
204 super( maxSize / 2, 0.75f, accessOrder );
205 this.maxSize = maxSize;
206 }
207
208
209
210
211 @Override
212 protected boolean removeEldestEntry(Entry<K,V> eldest) {
213 return size() > maxSize;
214 }
215
216 }
217 }