View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.converter;
23  
24  import java.io.Serializable;
25  import java.util.Locale;
26  
27  import javax.faces.application.FacesMessage;
28  import javax.faces.component.UIComponent;
29  import javax.faces.context.FacesContext;
30  import javax.faces.convert.Converter;
31  import javax.faces.convert.ConverterException;
32  import javax.faces.convert.FacesConverter;
33  
34  import org.primefaces.extensions.util.ExtLangUtils;
35  import org.primefaces.util.Constants;
36  import org.primefaces.util.LangUtils;
37  
38  /**
39   * {@link Converter} which converts a string to a {@link java.util.Locale} an vice-versa.
40   *
41   * @author Thomas Andraschko / last modified by $Author$
42   * @version $Revision$
43   * @since 0.2
44   */
45  @FacesConverter(value = "org.primefaces.extensions.converter.LocaleConverter")
46  public class LocaleConverter implements Converter<Object>, Serializable {
47  
48      private static final long serialVersionUID = 20121214L;
49  
50      private char separator = '_';
51  
52      @Override
53      public Object getAsObject(final FacesContext fc, final UIComponent component, final String value) {
54          if (LangUtils.isBlank(value)) {
55              return fc.getApplication().getDefaultLocale();
56          }
57  
58          return getLocaleObject(value, separator);
59      }
60  
61      @Override
62      public String getAsString(final FacesContext fc, final UIComponent component, final Object value) {
63          if (value == null) {
64              final Locale defaultLocale = fc.getApplication().getDefaultLocale();
65              if (defaultLocale == null) {
66                  return null;
67              }
68  
69              return getLocaleString(defaultLocale, separator);
70          }
71  
72          if (value instanceof String) {
73              return (String) value;
74          }
75          else if (value instanceof Locale) {
76              return getLocaleString((Locale) value, separator);
77          }
78          else {
79              throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
80                          "Wrong type: '" + value.getClass().getSimpleName()
81                                      + "' is not 'Locale'.",
82                          Constants.EMPTY_STRING));
83          }
84      }
85  
86      public static Locale getLocaleObject(final String locale, final char seperator) {
87          String replacedLocale = locale;
88          if (seperator != '-' && seperator != '_') {
89              replacedLocale = replacedLocale.replace(seperator, '_');
90          }
91  
92          replacedLocale = replacedLocale.replace('-', '_');
93  
94          final String[] parts = replacedLocale.split("_");
95          if (parts.length == 0
96                      || !parts[0].matches("[a-zA-Z]{2,2}")
97                      || parts.length > 1 && parts[1].length() != 0 && !parts[1].matches("[a-zA-Z]{2,2}")) {
98              throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
99                          "'" + locale + "' does not represent a valid locale",
100                         Constants.EMPTY_STRING));
101         }
102 
103         switch (parts.length) {
104             case 3:
105                 return new Locale(parts[0], parts[1], parts[2]);
106 
107             case 2:
108                 return new Locale(parts[0], parts[1]);
109 
110             case 1:
111                 return new Locale(parts[0]);
112 
113             default:
114                 final String[] arr = ExtLangUtils.subarray(parts, 2, parts.length);
115                 return new Locale(parts[0], parts[1], String.join("_", arr));
116         }
117     }
118 
119     public static String getLocaleString(final Locale locale, final char seperator) {
120         if (LangUtils.isBlank(locale.getCountry())) {
121             return locale.getLanguage();
122         }
123 
124         return locale.getLanguage() + seperator + locale.getCountry();
125     }
126 
127     public char getSeparator() {
128         return separator;
129     }
130 
131     public void setSeparator(final char separator) {
132         this.separator = separator;
133     }
134 }