2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.usecases.rolodex;
19
20 import java.io.IOException;
21 import java.net.URLEncoder;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.faces.component.UIComponent;
27 import javax.faces.component.UIData;
28 import javax.faces.context.FacesContext;
29 import javax.faces.context.ResponseWriter;
30 import javax.faces.render.Renderer;
31
32 import org.apache.shale.util.Messages;
33
34 public class HeaderSorterRenderer extends Renderer {
35
36
37 /***
38 * <p>Localized messages for this application.</p>
39 */
40 private static Messages messages =
41 new Messages("org.apache.shale.usecases.view.Bundle");
42
43
44 /***
45 * <p>Constant used to create the query parameter that
46 * identifies the sorted column.</p>
47 */
48 private static final String SORTED_COLUMN = "s";
49
50
51 /***
52 * <p>Constant used to create the query parameter that
53 * identifies the sorted column's next sort direction.</p>
54 */
55 private static final String SORTED_SEQUENCE = "a";
56
57
58
59 /***
60 * <p>Finds the parent IUData component.</p>
61 */
62 protected UIData findDataComponent(UIComponent uicomponent) {
63 return (UIData) findDataParent(uicomponent);
64 }
65
66 /***
67 * <p>Recursive method that finds the first parent Idata component.</p>
68 */
69 private UIComponent findDataParent(UIComponent uicomponent) {
70 if (uicomponent == null)
71 return null;
72 if (uicomponent instanceof UIData)
73 return uicomponent;
74 else
75 return findDataParent(uicomponent.getParent());
76 }
77
78 /***
79 * <p>Returns the base context root of the form using the
80 * view handler.</p>
81 */
82 protected String getActionStr(FacesContext context) {
83 String uri = context.getViewRoot().getViewId();
84 String url =
85 context.getApplication().getViewHandler().getActionURL(
86 context,
87 uri);
88
89 return url;
90 }
91
92 /***
93 * <p>The name of the query parameter used to control column sorting.</p>
94 */
95 protected String getSortedTag(FacesContext context, UIData data) {
96 StringBuffer clientId = new StringBuffer(data.getClientId(context));
97 clientId.append(SORTED_COLUMN);
98 return clientId.toString();
99 }
100
101 /***
102 * <p>Determines if the column was click to be sorted on.</p>
103 */
104 protected boolean wasSelected(
105 FacesContext context,
106 UIData data,
107 HeaderSorter column) {
108
109 boolean wasSelected = false;
110 Map params = context.getExternalContext().getRequestParameterMap();
111 String tag = getSortedTag(context, data);
112 if (params.containsKey(tag)) {
113 String value = (String) params.get(tag);
114 wasSelected = value.equals(column.getId());
115 column.getAttributes().put("defaultSort", value);
116
117
118 String sortAcending = (String) params.get(SORTED_SEQUENCE);
119 boolean isSortedAcending = true;
120 try {
121 isSortedAcending = Boolean.valueOf(sortAcending).booleanValue();
122 } catch (Exception e) {
123 }
124
125
126 column.setSortAscending(isSortedAcending);
127
128 value = null;
129 } else if (column.wasSelected()) {
130 wasSelected = true;
131 }
132
133 tag = null;
134 params = null;
135
136 return wasSelected;
137 }
138
139 /***
140 * <p>Initiates the component rendering.</p>
141 */
142 public void encodeBegin(FacesContext context, UIComponent component)
143 throws IOException {
144
145 if (context == null || component == null)
146 throw new NullPointerException();
147
148 if (!component.isRendered())
149 return;
150
151 ResponseWriter writer = context.getResponseWriter();
152
153 UIData data = findDataComponent(component);
154 if (data == null)
155 throw new NullPointerException(messages.getMessage("headerSorter.invalid"));
156
157 boolean wasSelected =
158 wasSelected(context, data, (HeaderSorter) component);
159
160 if (wasSelected) {
161 GenericComparator adapter =
162 new GenericComparator();
163 adapter.setSortAscending(
164 ((HeaderSorter) component).isSortAscending());
165 adapter.setSortBy(
166 ((HeaderSorter) component).getSortBy());
167
168 Collections.sort((List) data.getValue(), adapter);
169
170 adapter = null;
171
172 writer.startElement("input", component);
173 writer.writeAttribute("type", "hidden", "type");
174 writer.writeAttribute("name", this.getSortedTag(context, data), "name");
175 writer.writeAttribute("value", ((HeaderSorter) component).getId(), "value");
176 writer.write(' ');
177 }
178
179
180 StringBuffer url = new StringBuffer(getActionStr(context));
181 url.append('?').append(getSortedTag(context, data)).append("=").append(
182 URLEncoder.encode(component.getId(), "UTF-8"))
183 .append("&").append(SORTED_SEQUENCE).append("=")
184 .append(!((HeaderSorter) component).isSortAscending());
185 writer.startElement("a", component);
186 writer.writeAttribute("href", context.getExternalContext().encodeActionURL(url.toString()), "href");
187 writer.writeText((String) ((HeaderSorter) component).getValue(), "value");
188
189 url = null;
190 writer = null;
191 data = null;
192
193 super.encodeBegin(context, component);
194 }
195
196 /***
197 * <p>Completes component rendering.</p>
198 */
199 public void encodeEnd(FacesContext context, UIComponent component)
200 throws IOException {
201
202 if (context == null || component == null)
203 throw new NullPointerException();
204
205 if (!component.isRendered())
206 return;
207
208 super.encodeEnd(context, component);
209
210 boolean wasSelected = ((HeaderSorter) component).wasSelected();
211 boolean wasSortedAscending =
212 ((HeaderSorter) component).isSortAscending();
213
214 ResponseWriter writer = context.getResponseWriter();
215
216 if (wasSelected) {
217
218 StringBuffer url =
219 new StringBuffer(
220 context.getExternalContext().getRequestContextPath());
221
222 String title = null;
223 if (wasSortedAscending) {
224 if (((HeaderSorter) component).getAscImage() != null) {
225 url.append(((HeaderSorter) component).getAscImage());
226 } else {
227 url.append(messages.getMessage("headerSorter.ascImage"));
228 }
229 title = messages.getMessage("headerSorter.ascTitle");
230 } else {
231 if (((HeaderSorter) component).getDescImage() != null) {
232 url.append(((HeaderSorter) component).getDescImage());
233 } else {
234 url.append(messages.getMessage("headerSorter.descImage"));
235 }
236 title = messages.getMessage("headerSorter.descTitle");
237 }
238
239 writer.startElement("img", component);
240 writer.writeAttribute("border", "0", "border");
241 writer.writeAttribute("src", context.getExternalContext().encodeActionURL(url.toString()), "src");
242 writer.writeAttribute("title", title, "title");
243 writer.write(' ');
244
245 url = null;
246 title = null;
247
248 }
249 writer.endElement("a");
250 writer = null;
251
252 }
253
254 }