/*******************************************************************************
* Copyright (c) 2012, Directors of the Tyndale STEP Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* Neither the name of the Tyndale House, Cambridge (www.TyndaleHouse.com)
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package com.tyndalehouse.step.core.service.impl;
import static com.tyndalehouse.step.core.utils.language.ContemporaryLanguageUtils.capitaliseFirstLetter;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import com.tyndalehouse.step.core.models.ClientSession;
import com.tyndalehouse.step.core.models.Language;
import com.tyndalehouse.step.core.service.LanguageService;
import com.tyndalehouse.step.core.utils.StringUtils;
import com.tyndalehouse.step.core.utils.language.ContemporaryLanguageUtils;
/**
* A simple service that returns all the languages that are available
*/
@Singleton
public class LanguageServiceImpl implements LanguageService {
private final Map<Locale, List<Language>> languages = new HashMap<Locale, List<Language>>();
private final Set<String> languageCodes;
private final Provider<ClientSession> clientSessionProvider;
private final Set<String> completedLanguages;
private final Set<String> partialLanguages;
/**
* Instantiates a new language service impl.
*
* @param languageCodes the languages
* @param clientSessionProvider the client session provider
*/
@Inject
public LanguageServiceImpl(
@Named("app.languages.available") final String languageCodes,
@Named("app.languages.completed") final String completedLanguages,
@Named("app.languages.partial") final String partialLanguages,
final Provider<ClientSession> clientSessionProvider) {
this.languageCodes = getLanguageCodes(languageCodes);
this.completedLanguages = getLanguageCodes(completedLanguages);
this.partialLanguages = getLanguageCodes(partialLanguages);
this.clientSessionProvider = clientSessionProvider;
}
private Set<String> getLanguageCodes(final String languageCodes) {
if(StringUtils.isBlank(languageCodes)) {
return new HashSet<String>();
} else {
return new HashSet<String>(Arrays.asList(StringUtils.split(languageCodes, ",")));
}
}
/**
* Gets the available languages.
*
* @return the available languages
*/
@Override
public List<Language> getAvailableLanguages() {
return getLanguagesForSession();
}
@Override
public boolean isSupported(final String langParam, final String country) {
if(langParam.equalsIgnoreCase("iw")) {
return this.languageCodes.contains("he");
} else if(langParam.equalsIgnoreCase("in")) {
return this.languageCodes.contains("id");
} else if(langParam.equalsIgnoreCase("aa")) {
return true;
} else {
return this.languageCodes.contains(langParam) || this.languageCodes.contains(StringUtils.isNotBlank(country) ? langParam + "-" + country : langParam);
}
}
@Override
public boolean isCompleted(final String langParam) {
return this.completedLanguages.contains(langParam);
}
/**
* Sets up the languages.
*
* @return the list
*/
private List<Language> getLanguagesForSession() {
final Locale currentLocale = this.clientSessionProvider.get().getLocale();
List<Language> configuredLanguages = this.languages.get(currentLocale);
if(configuredLanguages == null) {
synchronized (this) {
configuredLanguages = new ArrayList<Language>(64);
Language currentLanguage = null;
for (final String code : this.languageCodes) {
final Locale locale = ContemporaryLanguageUtils.getLocaleFromTag(code);
final Language l = new Language();
l.setCode(code);
// attempt to make first letter upper case
l.setUserLocaleLanguageName(getLanguageName(currentLocale, locale));
l.setOriginalLanguageName(getLanguageName(locale, locale));
l.setComplete(this.completedLanguages.contains(code));
l.setPartial(this.partialLanguages.contains(code));
configuredLanguages.add(l);
if (currentLocale.equals(locale)) {
currentLanguage = l;
}
}
sortLanguages(configuredLanguages);
this.languages.put(currentLocale, configuredLanguages);
}
}
return configuredLanguages;
}
/**
* Gets the language name, with the country if applicable
*
* @param currentLocale the current locale
* @param locale the locale
* @return the language name
*/
private String getLanguageName(final Locale currentLocale, final Locale locale) {
String extra = "";
if("bfo".equalsIgnoreCase(locale.getLanguage())) {
return "Birifor";
}
if (!"".equals(locale.getCountry())) {
if ("TW".equals(locale.getCountry())) {
extra = "Traditional";
} else if("bfo".equalsIgnoreCase(locale.getISO3Language())) {
} else {
extra = locale.getDisplayCountry(currentLocale);
}
return String.format("%s, %s", capitaliseFirstLetter(locale.getDisplayLanguage(currentLocale)),
capitaliseFirstLetter(extra));
}
return capitaliseFirstLetter(locale.getDisplayLanguage(currentLocale));
}
/**
* Sort languages by their original language name, and puts the current locale language at the top.
*
* @param languages a list of languages to be sorted
*/
private void sortLanguages(final List<Language> languages) {
// sort list of languages
Collections.sort(languages, new Comparator<Language>() {
@Override
public int compare(final Language o1, final Language o2) {
return o1.getOriginalLanguageName().compareTo(o2.getOriginalLanguageName());
}
});
}
}