View Javadoc
1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.webapp.taglib;
24  
25  import java.io.IOException;
26  import java.text.Collator;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.Comparator;
30  import java.util.List;
31  import java.util.Locale;
32  
33  import javax.servlet.jsp.JspException;
34  import javax.servlet.jsp.tagext.TagSupport;
35  
36  import org.displaytag.tags.el.ExpressionEvaluator;
37  
38  import com.gisgraphy.model.LabelValue;
39  
40  /**
41   * Tag for creating multiple &lt;select&gt; options for displaying a list of
42   * country names.
43   * <p>
44   * <b>NOTE</b> - This tag requires a Java2 (JDK 1.2 or later) platform.
45   * </p>
46   * 
47   * @author Jens Fischer, Matt Raible
48   * @version $Revision: 1.4.2.1 $ $Date: 2006-06-10 08:00:48 -0600 (Sat, 10 Jun
49   *          2006) $
50   */
51  public class CountryTag extends TagSupport {
52      private static final long serialVersionUID = 3905528206810167095L;
53  
54      private String name;
55  
56      private String prompt;
57  
58      private String scope;
59  
60      private String selected;
61  
62      public void setName(String name) {
63  	this.name = name;
64      }
65  
66      public void setPrompt(String prompt) {
67  	this.prompt = prompt;
68      }
69  
70      public void setDefault(String selected) {
71  	this.selected = selected;
72      }
73  
74      public void setToScope(String scope) {
75  	this.scope = scope;
76      }
77  
78      /**
79       * Process the start of this tag.
80       * 
81       * @return int status
82       * @exception JspException
83       *                    if a JSP exception has occurred
84       * @see javax.servlet.jsp.tagext.Tag#doStartTag()
85       */
86      @Override
87      public int doStartTag() throws JspException {
88  	ExpressionEvaluator eval = new ExpressionEvaluator(this, pageContext);
89  
90  	if (selected != null) {
91  	    selected = eval.evalString("default", selected);
92  	}
93  
94  	Locale userLocale = pageContext.getRequest().getLocale();
95  	List<LabelValue> countries = this.buildCountryList(userLocale);
96  
97  	if (scope != null) {
98  	    if (scope.equals("page")) {
99  		pageContext.setAttribute(name, countries);
100 	    } else if (scope.equals("request")) {
101 		pageContext.getRequest().setAttribute(name, countries);
102 	    } else if (scope.equals("session")) {
103 		pageContext.getSession().setAttribute(name, countries);
104 	    } else if (scope.equals("application")) {
105 		pageContext.getServletContext().setAttribute(name, countries);
106 	    } else {
107 		throw new JspException(
108 			"Attribute 'scope' must be: page, request, session or application");
109 	    }
110 	} else {
111 	    StringBuffer sb = new StringBuffer();
112 	    sb.append("<select name=\"").append(name).append("\" id=\"")
113 		    .append(name).append("\" class=\"select\">\n");
114 
115 	    if (prompt != null) {
116 		sb.append("    <option value=\"\" selected=\"selected\">");
117 		sb.append(eval.evalString("prompt", prompt)).append(
118 			"</option>\n");
119 	    }
120 
121 	    for (Object country1 : countries) {
122 		LabelValue country = (LabelValue) country1;
123 		sb.append("    <option value=\"").append(country.getValue())
124 			.append("\"");
125 
126 		if ((selected != null) && selected.equals(country.getValue())) {
127 		    sb.append(" selected=\"selected\"");
128 		}
129 
130 		sb.append(">").append(country.getLabel()).append("</option>\n");
131 	    }
132 
133 	    sb.append("</select>");
134 
135 	    try {
136 		pageContext.getOut().write(sb.toString());
137 	    } catch (IOException io) {
138 		throw new JspException(io);
139 	    }
140 	}
141 
142 	return super.doStartTag();
143     }
144 
145     /**
146      * Release aquired resources to enable tag reusage.
147      * 
148      * @see javax.servlet.jsp.tagext.Tag#release()
149      */
150     @Override
151     public void release() {
152 	super.release();
153     }
154 
155     /**
156      * Build a List of LabelValues for all the available countries. Uses the two
157      * letter uppercase ISO name of the country as the value and the localized
158      * country name as the label.
159      * 
160      * @param locale
161      *                The Locale used to localize the country names.
162      * @return List of LabelValues for all available countries.
163      */
164     @SuppressWarnings("unchecked")
165     protected List<LabelValue> buildCountryList(Locale locale) {
166 	final Locale[] available = Locale.getAvailableLocales();
167 
168 	List<LabelValue> countries = new ArrayList<LabelValue>();
169 
170 	for (Locale anAvailable : available) {
171 	    final String iso = anAvailable.getCountry();
172 	    final String name = anAvailable.getDisplayCountry(locale);
173 
174 	    if (!"".equals(iso) && !"".equals(name)) {
175 		LabelValue country = new LabelValue(name, iso);
176 
177 		if (!countries.contains(country)) {
178 		    countries.add(new LabelValue(name, iso));
179 		}
180 	    }
181 	}
182 
183 	Collections.sort(countries, new LabelValueComparator(locale));
184 
185 	return countries;
186     }
187 
188     /**
189      * Class to compare LabelValues using their labels with locale-sensitive
190      * behaviour.
191      */
192     @SuppressWarnings("unchecked")
193     public class LabelValueComparator implements Comparator {
194 	private Comparator c;
195 
196 	/**
197 	 * Creates a new LabelValueComparator object.
198 	 * 
199 	 * @param locale
200 	 *                The Locale used for localized String comparison.
201 	 */
202 	public LabelValueComparator(final Locale locale) {
203 	    c = Collator.getInstance(locale);
204 	}
205 
206 	/**
207 	 * Compares the localized labels of two LabelValues.
208 	 * 
209 	 * @param o1
210 	 *                The first LabelValue to compare.
211 	 * @param o2
212 	 *                The second LabelValue to compare.
213 	 * @return The value returned by comparing the localized labels.
214 	 */
215 	@SuppressWarnings("unchecked")
216 	public final int compare(Object o1, Object o2) {
217 	    LabelValue lhs = (LabelValue) o1;
218 	    LabelValue rhs = (LabelValue) o2;
219 
220 	    return c.compare(lhs.getLabel(), rhs.getLabel());
221 	}
222     }
223 }