]> git.mxchange.org Git - jjobs-war.git/blobdiff - src/java/org/mxchange/jjobs/beans/localization/JobsLocalizationSessionBean.java
Please cherry-pick:
[jjobs-war.git] / src / java / org / mxchange / jjobs / beans / localization / JobsLocalizationSessionBean.java
index f95bf02a6e05cec00c25cea1e053c5cb0c209633..2737bc22f4ed1d780e1c14ba36ad3fb22deb07cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Roland Häder
+ * Copyright (C) 2016 - 2020 Free Software Foundation
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 package org.mxchange.jjobs.beans.localization;
 
 import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
 import javax.annotation.PostConstruct;
 import javax.enterprise.context.SessionScoped;
+import javax.enterprise.event.Event;
 import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
 import javax.faces.context.FacesContext;
+import javax.inject.Inject;
 import javax.inject.Named;
-import org.mxchange.jjobs.beans.BaseJobsController;
-import org.mxchange.jusercore.events.login.ObservableUserLoggedInEvent;
-import org.mxchange.jusercore.events.logout.ObservableUserLogoutEvent;
+import org.mxchange.jcoreee.events.locale.LocaleChangeEvent;
+import org.mxchange.jcoreee.events.locale.ObservableLocaleChangeEvent;
+import org.mxchange.jjobs.beans.BaseJobsBean;
+import org.mxchange.juserlogincore.events.login.ObservableUserLoggedInEvent;
+import org.mxchange.juserlogincore.events.logout.ObservableUserLogoutEvent;
 
 /**
- * A session bean for handling localization/internationalization changes. This
- * class is based on an example at [1] from mkyong.
+ * A session-scoped bean for handling localization/internationalization changes.
+ * This class is based on an example at [1] from mkyong.
  * <p>
  * 1: http://www.mkyong.com/jsf2/jsf-2-internationalization-example/
  * <p>
@@ -37,21 +47,58 @@ import org.mxchange.jusercore.events.logout.ObservableUserLogoutEvent;
  */
 @Named ("localizationController")
 @SessionScoped
-public class JobsLocalizationSessionBean extends BaseJobsController implements JobsLocalizationSessionController {
+public class JobsLocalizationSessionBean extends BaseJobsBean implements JobsLocalizationSessionController {
+
+       /**
+        * Number format
+        */
+       private static NumberFormat NUMBER_FORMAT;
 
        /**
         * Serial number
         */
-       private static final long serialVersionUID = 1_867_671_657_629_601_528L;
+       private static final long serialVersionUID = 158_768_216_759_107L;
 
        /**
         * Current Locale
         */
        private Locale locale;
 
-       @Override
+       /**
+        * Event being fired when a locale has changed successfully
+        */
+       @Inject
+       @Any
+       private Event<ObservableLocaleChangeEvent> localeChangeEvent;
+
+       /**
+        * Locale code (example: de for Germany)
+        */
+       private String localeCode;
+
+       /**
+        * A map of all supported locales, using language code as key
+        */
+       private final Map<String, Locale> supportedLocales;
+
+       /**
+        * Default constructor
+        */
+       public JobsLocalizationSessionBean () {
+               // Call super constructor
+               super();
+
+               // Init locale list
+               this.supportedLocales = new LinkedHashMap<>(2);
+       }
+
+       /**
+        * Event observer for logged-in user
+        * <p>
+        * @param event Event instance
+        */
        public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
-               // event should not be null
+               // Event and contained entity instance should not be null
                if (null == event) {
                        // Throw NPE
                        throw new NullPointerException("event is null"); //NOI18N
@@ -68,14 +115,21 @@ public class JobsLocalizationSessionBean extends BaseJobsController implements J
 
                // Is the locale set?
                if (event.getLoggedInUser().getUserLocale() instanceof Locale) {
-                       // Set locale here
-                       this.setLocale(event.getLoggedInUser().getUserLocale());
+                       // Get user local
+                       final Locale userLocale = event.getLoggedInUser().getUserLocale();
+
+                       // Change locale
+                       this.changeLocale(userLocale, Boolean.TRUE);
                }
        }
 
-       @Override
+       /**
+        * Event observer for logged-out user
+        * <p>
+        * @param event Event instance
+        */
        public void afterUserLogoutEvent (@Observes final ObservableUserLogoutEvent event) {
-               // event should not be null
+               // Event and contained entity instance should not be null
                if (null == event) {
                        // Throw NPE
                        throw new NullPointerException("event is null"); //NOI18N
@@ -90,66 +144,101 @@ public class JobsLocalizationSessionBean extends BaseJobsController implements J
                        throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedOutUser(), event.getLoggedOutUser().getUserId())); //NOI18N
                }
 
-               // Trace message
-               //* NOISY-DEBUG: */ System.out.println("LandingLocalizationSessionBean:afterUserLogin - EXIT!"); //NOI18N
+               // Clear this bean as well
+               this.clear();
        }
 
-       @Override
-       public String getLanguage () {
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::getLanguage(): locale.language={0} - EXIT!", this.getLocale().getLanguage())); //NOI18N
-               return this.getLocale().getLanguage().toLowerCase();
-       }
-
-       @Override
-       public void setLanguage (final String language) {
-               // Log trace message
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::setLanguage: language={0} - CALLED!", language)); //NOI18N
-
-               // Is the language null?
-               if (null == language) {
-                       // This may sometimes happen, so abort here
-                       return;
+       /**
+        * Changes locale in application
+        */
+       public void doChangeLocale () {
+               // Is locale code set?
+               if (this.getLocaleCode() == null) {
+                       // Throw NPE
+                       throw new NullPointerException("this.localeCode is null"); //NOI18N
+               } else if (this.getLocaleCode().isEmpty()) {
+                       // Throw IAE
+                       throw new IllegalArgumentException("this.localeCode is empty"); //NOI18N
                }
 
-               // Language splits
-               String[] splits = language.split("_"); //NOI18N
-               if (null == splits[1]) {
-                       splits[1] = ""; //NOI18N
+               // Default new locale is null, will be handled later
+               Locale newLocale = null;
+
+               // Iterate over whole map
+               for (final Map.Entry<String, Locale> entry : this.getSupportedLocales().entrySet()) {
+                       final Locale foundLocale = entry.getValue();
+
+                       // Does the language match?
+                       if (Objects.equals(foundLocale.toString(), this.getLocaleCode())) {
+                               // Is found, take it as request locale
+                               newLocale = foundLocale;
+                               break;
+                       }
                }
 
-               // Get new locale with upper-case country code
-               Locale loc = new Locale(splits[0], splits[1]);
+               // Clear locale code field
+               this.clear();
 
-               // Log debug message
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::setLanguage: loc={0}", loc)); //NOI18N
+               // Has a matching locale
+               if (null == newLocale) {
+                       // Throw NPE
+                       throw new NullPointerException("this.localeCode=" + this.getLocaleCode() + " cannot be found."); //NOI18N
+               }
+
+               // Then change it
+               this.changeLocale(newLocale, Boolean.TRUE);
 
-               // Set it here and in the JSF context
-               this.setLocale(loc);
-               FacesContext.getCurrentInstance().getViewRoot().setLocale(loc);
+               // Change formatting
+               NUMBER_FORMAT = NumberFormat.getNumberInstance(newLocale);
+       }
 
-               // Log trace message
-               //* NOISY-DEBUG: */ System.out.println("JobsLocalizationSessionBean::setLanguage: EXIT!"); //NOI18N
+       @Override
+       public String formatCurrency (final Float amount) {
+               // Format amount
+               return NUMBER_FORMAT.format(amount);
        }
 
        @Override
        public Locale getLocale () {
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::getLocale(): locale={0} - EXIT!", this.locale)); //NOI18N
                return this.locale;
        }
 
-       @Override
+       /**
+        * Setter for locale
+        * <p>
+        * @param locale Locale
+        */
        public void setLocale (final Locale locale) {
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::setLocale(): locale={0} - CALLED!", locale)); //NOI18N
                this.locale = locale;
        }
 
-       @Override
-       public Locale[] getSelectableLocalizations () {
-               Locale[] locales = {
-                       Locale.GERMANY,
-                       Locale.US
-               };
-               return locales;
+       /**
+        * Getter for localeCode code
+        * <p>
+        * @return Language code
+        */
+       public String getLocaleCode () {
+               return this.localeCode;
+       }
+
+       /**
+        * Setter for localeCode code
+        * <p>
+        * @param localeCode Language code
+        */
+       public void setLocaleCode (final String localeCode) {
+               this.localeCode = localeCode;
+       }
+
+       /**
+        * Getter for selectable localizations
+        * <p>
+        * @return Selectable localizations
+        */
+       @SuppressWarnings ("ReturnOfCollectionOrArrayField")
+       public Map<String, Locale> getSupportedLocales () {
+               // Return full list
+               return this.supportedLocales;
        }
 
        /**
@@ -157,20 +246,100 @@ public class JobsLocalizationSessionBean extends BaseJobsController implements J
         */
        @PostConstruct
        public void init () {
-               // Log trace message
-               //* NOISY-DEBUG: */ System.out.println("JobsLocalizationSessionBean::init: CALLED!"); //NOI18N
+               // Get default locale
+               final Locale defaultLocale = FacesContext.getCurrentInstance().getApplication().getDefaultLocale();
+
+               // Add it to list
+               this.getSupportedLocales().put(defaultLocale.toString(), defaultLocale);
+
+               // Get iterator from faces context
+               final Iterator<Locale> iterator = FacesContext.getCurrentInstance().getApplication().getSupportedLocales();
+
+               // Add all locales
+               while (iterator.hasNext()) {
+                       // Get next locale
+                       Locale supportedLocale = iterator.next();
+
+                       // Add it
+                       this.getSupportedLocales().put(supportedLocale.toString(), supportedLocale);
+               }
 
-               // Create locale instance from context
-               Locale loc = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
+               // Get locale instance from request (e.g. browser)
+               Locale requestLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
 
-               // Log debug message
-               //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("JobsLocalizationSessionBean::init: loc={0}", loc)); //NOI18N
+               // Is no country code found?
+               if (requestLocale.getCountry().isEmpty()) {
+                       // Then try to find one, get language from it
+                       final String language = requestLocale.getLanguage();
+                       Boolean found = Boolean.FALSE;
 
-               // Set it here
-               this.setLocale(loc);
+                       // Iterate over whole map
+                       for (final Map.Entry<String, Locale> entry : this.getSupportedLocales().entrySet()) {
+                               final String languageCode = entry.getKey();
+                               final Locale foundLocale = entry.getValue();
 
-               // Log trace message
-               //* NOISY-DEBUG: */ System.out.println("JobsLocalizationSessionBean::init: EXIT!"); //NOI18N
+                               // Does the language match?
+                               if (languageCode.startsWith(language)) {
+                                       // Is found, take it as request locale
+                                       requestLocale = foundLocale;
+                                       found = Boolean.TRUE;
+                                       break;
+                               }
+                       }
+
+                       // Nothing found?
+                       if (!found) {
+                               // Then set default locale
+                               requestLocale = defaultLocale;
+                       }
+               }
+
+               // Change locale, may set same back in faces context, but triggers event
+               this.changeLocale(requestLocale, Boolean.FALSE);
+
+               // Initial formatting, may change when user chooses other locale
+               NUMBER_FORMAT = NumberFormat.getNumberInstance(this.locale);
+       }
+
+       /**
+        * Changes current locale in this controller and faces context to given.
+        * This method makes sure that locales with at least language and country
+        * information are being changed to.
+        * <p>
+        * @param locale      New locale to set
+        * @param notifyBeans Whether to notify other beans
+        */
+       private void changeLocale (final Locale locale, final Boolean notifyBeans) {
+               // Is the locale language_country at least?
+               if (null == locale) {
+                       // Throw NPE
+                       throw new NullPointerException("locale is null"); //NOI18N
+               } else if (!locale.toString().contains("_")) { //NOI18N
+                       // Throw IAE
+                       throw new IllegalArgumentException(MessageFormat.format("locale={0} does not have country information set.", locale)); //NOI18N
+               }
+
+               // Set locale + code here
+               this.setLocale(locale);
+               this.setLocaleCode(locale.toString());
+
+               // Inform faces context
+               FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
+
+               // Notify other beans?
+               if (notifyBeans) {
+                       // Fire event
+                       this.localeChangeEvent.fire(new LocaleChangeEvent(locale));
+               }
+       }
+
+       /**
+        * Clears this bean
+        */
+       private void clear () {
+               // Clear all fields
+               this.setLocaleCode(null);
+               this.setLocale(null);
        }
 
 }