blob: bacf40b472dde792cad5a8a4c8b04368b87894f7 [file] [log] [blame]
// Copyright 2006, 2007, 2009, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.tapestry5.internal.services;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.OptionModelImpl;
import org.apache.tapestry5.internal.SelectModelImpl;
import org.apache.tapestry5.internal.TapestryInternalUtils;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.services.ThreadLocale;
import org.apache.tapestry5.services.LocalizationSetter;
import org.apache.tapestry5.services.PersistentLocale;
import org.apache.tapestry5.services.Request;
/**
* Given a set of supported locales, for a specified desired locale, sets the current thread's locale to a supported
* locale that is closest to the desired.
*/
public class LocalizationSetterImpl implements LocalizationSetter
{
private final Request request;
private final ThreadLocale threadLocale;
private final Locale defaultLocale;
private final Set<String> supportedLocaleNames;
private final List<Locale> supportedLocales;
private final Map<String, Locale> localeCache = CollectionFactory.newConcurrentMap();
private final PersistentLocale persistentLocale;
public LocalizationSetterImpl(Request request,
PersistentLocale persistentLocale,
ThreadLocale threadLocale,
@Symbol(SymbolConstants.SUPPORTED_LOCALES)
String localeNames)
{
this.request = request;
this.persistentLocale = persistentLocale;
this.threadLocale = threadLocale;
this.supportedLocaleNames = CollectionFactory.newSet();
String[] names = TapestryInternalUtils.splitAtCommas(localeNames);
for (String name : names)
{
supportedLocaleNames.add(name.toLowerCase());
}
supportedLocales = parseNames(names);
defaultLocale = supportedLocales.get(0);
}
private List<Locale> parseNames(String[] localeNames)
{
List<Locale> list = CollectionFactory.newList();
for (String name : localeNames)
{
list.add(toLocale(name));
}
return Collections.unmodifiableList(list);
}
public Locale toLocale(String localeName)
{
Locale result = localeCache.get(localeName);
if (result == null)
{
result = constructLocale(localeName);
localeCache.put(localeName, result);
}
return result;
}
private Locale constructLocale(String name)
{
String[] terms = name.split("_");
switch (terms.length)
{
case 1:
return new Locale(terms[0], "");
case 2:
return new Locale(terms[0], terms[1]);
case 3:
return new Locale(terms[0], terms[1], terms[2]);
default:
throw new IllegalArgumentException();
}
}
public boolean setLocaleFromLocaleName(String localeName)
{
boolean supported = isSupportedLocaleName(localeName);
if (supported)
{
Locale locale = findClosestSupportedLocale(toLocale(localeName));
persistentLocale.set(locale);
threadLocale.setLocale(locale);
}
else
{
Locale requestLocale = request.getLocale();
Locale supportedLocale = findClosestSupportedLocale(requestLocale);
threadLocale.setLocale(supportedLocale);
}
return supported;
}
public void setNonPeristentLocaleFromLocaleName(String localeName)
{
Locale requested = toLocale(localeName);
Locale supported = findClosestSupportedLocale(requested);
threadLocale.setLocale(supported);
}
private Locale findClosestSupportedLocale(Locale desiredLocale)
{
String localeName = desiredLocale.toString();
while (true)
{
if (isSupportedLocaleName(localeName))
return toLocale(localeName);
localeName = stripTerm(localeName);
if (localeName.length() == 0)
break;
}
return defaultLocale;
}
static String stripTerm(String localeName)
{
int scorex = localeName.lastIndexOf('_');
return scorex < 0 ? "" : localeName.substring(0, scorex);
}
public List<Locale> getSupportedLocales()
{
return supportedLocales;
}
public boolean isSupportedLocaleName(String localeName)
{
return supportedLocaleNames.contains(localeName.toLowerCase());
}
public SelectModel getSupportedLocalesModel()
{
List<OptionModel> options = CollectionFactory.newList();
for (Locale l : supportedLocales)
{
options.add(new OptionModelImpl(l.getDisplayName(l), l));
}
return new SelectModelImpl(null, options);
}
}