View Javadoc

1   package com.panogenesis.webapp.taglib;
2   
3   import java.io.IOException;
4   
5   import java.text.Collator;
6   
7   import java.util.ArrayList;
8   import java.util.Collections;
9   import java.util.Comparator;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Locale;
13  
14  import javax.servlet.jsp.JspException;
15  import javax.servlet.jsp.tagext.TagSupport;
16  
17  import com.panogenesis.model.LabelValue;
18  
19  import org.displaytag.tags.el.ExpressionEvaluator;
20  
21  /***
22   * Tag for creating multiple <select> options for displaying a list of
23   * country names.
24   *
25   * <p>
26   * <b>NOTE</b> - This tag requires a Java2 (JDK 1.2 or later) platform.
27   * </p>
28   *
29   * @author Jens Fischer, Matt Raible
30   * @version $Revision: 1.1 $ $Date: 2004/09/29 10:31:35 $
31   *
32   * @jsp.tag name="country" bodycontent="empty"
33   */
34  public class CountryTag extends TagSupport {
35      private static final String COUNTRIES =
36          CountryTag.class.getName() + ".COUNTRIES";
37      private String name;
38      private String prompt;
39      private String scope;
40      private String selected;
41      private String style;
42      private String styleClass;
43  
44      /***
45       * @param name The name to set.
46       *
47       * @jsp.attribute required="false" rtexprvalue="true"
48       */
49      public void setName(String name) {
50          this.name = name;
51      }
52  
53      /***
54       * @param prompt The prompt to set.
55       * @jsp.attribute required="false" rtexprvalue="true"
56       */
57      public void setPrompt(String prompt) {
58          this.prompt = prompt;
59      }
60  
61      /***
62       * @param selected The selected option.
63       * @jsp.attribute required="false" rtexprvalue="true"
64       */
65      public void setDefault(String selected) {
66          this.selected = selected;
67      }
68  
69      /***
70       * Property used to simply stuff the list of countries into a
71       * specified scope.
72       *
73       * @param scope
74       *
75       * @jsp.attribute required="false" rtexprvalue="true"
76       */
77      public void setToScope(String scope) {
78          this.scope = scope;
79      }
80  
81      /***
82       * Setter included for XDoclet TLD generation.
83       *
84       * @param style
85       *
86       * @jsp.attribute required="false" rtexprvalue="true"
87       */
88      public void setStyle(String style) {
89          this.style = style;
90      }
91  
92      /***
93       * Setter included for XDoclet TLD generation.
94       *
95       * @param styleClass
96       *
97       * @jsp.attribute required="false" rtexprvalue="true"
98       */
99      public void setStyleClass(String styleClass) {
100         this.styleClass = styleClass;
101     }
102 
103     /***
104      * Process the start of this tag.
105      *
106      * @return
107      *
108      * @exception JspException if a JSP exception has occurred
109      *
110      * @see javax.servlet.jsp.tagext.Tag#doStartTag()
111      */
112     public int doStartTag() throws JspException {
113         ExpressionEvaluator eval = new ExpressionEvaluator(this, pageContext);
114 
115         if (selected != null) {
116             selected = eval.evalString("default", selected);
117         }
118 
119         Locale userLocale = pageContext.getRequest().getLocale();
120         List countries = this.buildCountryList(userLocale);
121 
122         if (scope != null) {
123             if (scope.equals("page")) {
124                 pageContext.setAttribute(name, countries);
125             } else if (scope.equals("request")) {
126                 pageContext.getRequest().setAttribute(name, countries);
127             } else if (scope.equals("session")) {
128                 pageContext.getSession().setAttribute(name, countries);
129             } else if (scope.equals("application")) {
130                 pageContext.getServletContext().setAttribute(name, countries);
131             } else {
132                 throw new JspException("Attribute 'scope' must be: page, request, session or application");
133             }
134         } else {
135             StringBuffer sb = new StringBuffer();
136             sb.append("<select name=\"" + name + "\" id=\"" + name + "\">\n");
137 
138             if (prompt != null) {
139                 sb.append("    <option value=\"\" selected=\"selected\">");
140                 sb.append(eval.evalString("prompt", prompt) + "</option>\n");
141             }
142 
143             for (Iterator i = countries.iterator(); i.hasNext();) {
144                 LabelValue country = (LabelValue) i.next();
145                 sb.append("    <option value=\"" + country.getValue() + "\"");
146 
147                 if ((selected != null) && selected.equals(country.getValue())) {
148                     sb.append(" selected=\"selected\"");
149                 }
150 
151                 sb.append(">" + country.getLabel() + "</option>\n");
152             }
153 
154             sb.append("</select>");
155 
156             try {
157                 pageContext.getOut().write(sb.toString());
158             } catch (IOException io) {
159                 throw new JspException(io);
160             }
161         }
162 
163         return super.doStartTag();
164     }
165 
166     /***
167      * Release aquired resources to enable tag reusage.
168      *
169      * @see javax.servlet.jsp.tagext.Tag#release()
170      */
171     public void release() {
172         super.release();
173     }
174 
175     /***
176      * Build a List of LabelValues for all the available countries. Uses
177      * the two letter uppercase ISO name of the country as the value and the
178      * localized country name as the label.
179      *
180      * @param locale The Locale used to localize the country names.
181      *
182      * @return List of LabelValues for all available countries.
183      */
184     protected List buildCountryList(Locale locale) {
185         final String EMPTY = "";
186         final Locale[] available = Locale.getAvailableLocales();
187 
188         List countries = new ArrayList();
189 
190         for (int i = 0; i < available.length; i++) {
191             final String iso = available[i].getCountry();
192             final String name = available[i].getDisplayCountry(locale);
193 
194             if (!EMPTY.equals(iso) && !EMPTY.equals(name)) {
195                 LabelValue country = new LabelValue(name, iso);
196 
197                 if (!countries.contains(country)) {
198                     countries.add(new LabelValue(name, iso));
199                 }
200             }
201         }
202 
203         Collections.sort(countries, new LabelValueComparator(locale));
204 
205         return countries;
206     }
207 
208     /***
209      * Class to compare LabelValues using their labels with
210      * locale-sensitive behaviour.
211      */
212     public class LabelValueComparator implements Comparator {
213         private Comparator c;
214 
215         /***
216          * Creates a new LabelValueComparator object.
217          *
218          * @param locale The Locale used for localized String comparison.
219          */
220         public LabelValueComparator(Locale locale) {
221             c = Collator.getInstance(locale);
222         }
223 
224         /***
225          * Compares the localized labels of two LabelValues.
226          *
227          * @param o1 The first LabelValue to compare.
228          * @param o2 The second LabelValue to compare.
229          *
230          * @return The value returned by comparing the localized labels.
231          */
232         public final int compare(Object o1, Object o2) {
233             LabelValue lhs = (LabelValue) o1;
234             LabelValue rhs = (LabelValue) o2;
235 
236             return c.compare(lhs.getLabel(), rhs.getLabel());
237         }
238     }
239 }