2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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             // toggle the sort order flag
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 }