org.unitime.localization.impl.Localization.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.localization.impl.Localization.java

Source

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you 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.unitime.localization.impl;

import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.unitime.timetable.defaults.ApplicationProperty;

import com.google.gwt.i18n.client.Constants;
import com.google.gwt.i18n.client.Messages;

/**
 * @author Tomas Muller
 */
public class Localization {
    private static Log sLog = LogFactory.getLog(Localization.class);
    public static final String ROOT = "org.unitime.localization.messages.";
    public static final String GWTROOT = "org.unitime.timetable.gwt.resources.";
    private static Map<Class, Object> sBundles = new Hashtable<Class, Object>();

    private static final ThreadLocal<String> sLocale = new ThreadLocal<String>() {
        @Override
        protected String initialValue() {
            return ApplicationProperty.Locale.value();
        }
    };
    private static final ThreadLocal<Locale> sJavaLocale = new ThreadLocal<Locale>() {
        @Override
        protected Locale initialValue() {
            return guessJavaLocale(ApplicationProperty.Locale.value());
        }
    };

    public static void setLocale(String locale) {
        sLocale.set(locale);
        sJavaLocale.set(guessJavaLocale(locale));
    }

    public static void removeLocale() {
        sLocale.remove();
        sJavaLocale.remove();
    }

    public static String getLocale() {
        return sLocale.get();
    }

    public static Locale getJavaLocale() {
        return sJavaLocale.get();
    }

    public static DateFormat getDateFormat(String pattern) {
        return new SimpleDateFormat(pattern, getJavaLocale());
    }

    public static NumberFormat getNumberFormat(String pattern) {
        return new DecimalFormat(pattern, new DecimalFormatSymbols(getJavaLocale()));
    }

    public static String getFirstLocale() {
        String locale = getLocale();
        if (locale.indexOf(',') >= 0)
            locale = locale.substring(0, locale.indexOf(','));
        if (locale.indexOf(';') >= 0)
            locale = locale.substring(0, locale.indexOf(';'));
        return locale.trim();
    }

    private static Locale guessJavaLocale(String locale) {
        for (StringTokenizer s = new StringTokenizer(locale, ",;"); s.hasMoreTokens();) {
            String lang = s.nextToken();
            String cc = null;
            if (lang.indexOf('_') >= 0) {
                cc = lang.substring(lang.indexOf('_') + 1);
                lang = lang.substring(0, lang.indexOf('_'));
            }
            for (Locale loc : Locale.getAvailableLocales())
                if ((lang == null || lang.isEmpty() || lang.equals(loc.getLanguage()))
                        && (cc == null || cc.isEmpty() || cc.equals(loc.getCountry()))) {
                    return loc;
                }
        }
        return Locale.getDefault();
    }

    public static <T> T create(Class<T> bundle) {
        synchronized (sBundles) {
            T ret = (T) sBundles.get(bundle);
            if (ret == null) {
                ret = (T) Proxy.newProxyInstance(Localization.class.getClassLoader(),
                        new Class[] { bundle, StrutsActionsRetriever.class }, new Bundle(bundle));
                sBundles.put(bundle, ret);
            }
            return ret;
        }
    }

    public static class Bundle implements InvocationHandler {
        private Map<String, Properties> iProperties = new Hashtable<String, Properties>();
        private Class<?> iMessages = null;

        public Bundle(Class<?> messages) {
            iMessages = messages;
        }

        private synchronized String getProperty(String locale, String name) {
            Properties properties = iProperties.get(locale);
            if (properties == null) {
                properties = new Properties();
                String resource = iMessages.getName().replace('.', '/') + (locale.isEmpty() ? "" : "_" + locale)
                        + ".properties";
                try {
                    InputStream is = Localization.class.getClassLoader().getResourceAsStream(resource);
                    if (is != null)
                        properties.load(is);
                } catch (Exception e) {
                    sLog.warn("Failed to load message bundle "
                            + iMessages.getName().substring(iMessages.getName().lastIndexOf('.') + 1) + " for "
                            + locale + ": " + e.getMessage(), e);
                }
                iProperties.put(locale, properties);
            }
            return properties.getProperty(name);
        }

        private String getProperty(String name) {
            for (String locale : getLocale().split(",")) {
                if (locale.indexOf(';') >= 0)
                    locale = locale.substring(0, locale.indexOf(';'));
                String value = getProperty(locale.trim(), name);
                if (value != null)
                    return value;
                if (locale.indexOf('_') >= 0) {
                    locale = locale.substring(0, locale.indexOf('_'));
                    value = getProperty(locale.trim(), name);
                    if (value != null)
                        return value;
                }
            }
            return getProperty("", name); // try default message bundle
        }

        private String fillArgumentsIn(String value, Object[] args, int firstIndex) {
            if (value == null || args == null)
                return value;
            for (int i = 0; i + firstIndex < args.length; i++)
                value = value.replace("{" + i + "}",
                        (args[i + firstIndex] == null ? "" : args[i + firstIndex].toString()));
            return value;
        }

        private String[] string2array(String value) {
            return value.split("(?<=^.*[^\\\\]),(?=.*$)");
        }

        private Map<String, String> array2map(String[] value) {
            Map<String, String> map = new HashMap<String, String>();
            for (int i = 0; i < value.length - 1; i += 2)
                map.put(value[i], value[i + 1]);
            return map;
        }

        private Object type(String value, Class returnType) {
            if (value == null)
                return value;
            if (String.class.equals(returnType))
                return value;

            if (Boolean.class.equals(returnType) || boolean.class.equals(returnType))
                return "true".equalsIgnoreCase(value);
            if (Double.class.equals(returnType) || double.class.equals(returnType))
                return Double.valueOf(value);
            if (Float.class.equals(returnType) || float.class.equals(returnType))
                return Float.valueOf(value);
            if (Integer.class.equals(returnType) || int.class.equals(returnType))
                return Integer.valueOf(value);

            if (String[].class.equals(returnType))
                return string2array(value);

            if (Map.class.equals(returnType)) {
                Map<String, String> map = new HashMap<String, String>();
                for (String key : string2array(value)) {
                    String val = getProperty(key.trim());
                    if (val != null)
                        map.put(key.trim(), val);
                }
                if (map.isEmpty())
                    return array2map(string2array(value));
                return map;
            }

            return value;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("getStrutsActions".equals(method.getName()) && method.getParameterTypes().length == 1)
                return getStrutsActions(proxy, (Class<? extends LocalizedLookupDispatchAction>) args[0]);
            if ("translateMessage".equals(method.getName()) && method.getParameterTypes().length >= 2) {
                String value = (args[0] == null ? null : getProperty((String) args[0]));
                return (value == null ? (String) args[1] : fillArgumentsIn(value, args, 2));
            }
            String value = getProperty(method.getName());
            if (value != null)
                return type(fillArgumentsIn(value, args, 0), method.getReturnType());
            Messages.DefaultMessage dm = method.getAnnotation(Messages.DefaultMessage.class);
            if (dm != null)
                return fillArgumentsIn(dm.value(), args, 0);
            Constants.DefaultBooleanValue db = method.getAnnotation(Constants.DefaultBooleanValue.class);
            if (db != null)
                return db.value();
            Constants.DefaultDoubleValue dd = method.getAnnotation(Constants.DefaultDoubleValue.class);
            if (dd != null)
                return dd.value();
            Constants.DefaultFloatValue df = method.getAnnotation(Constants.DefaultFloatValue.class);
            if (df != null)
                return df.value();
            Constants.DefaultIntValue di = method.getAnnotation(Constants.DefaultIntValue.class);
            if (di != null)
                return di.value();
            Constants.DefaultStringValue ds = method.getAnnotation(Constants.DefaultStringValue.class);
            if (ds != null)
                return ds.value();
            Constants.DefaultStringArrayValue dsa = method.getAnnotation(Constants.DefaultStringArrayValue.class);
            if (dsa != null)
                return dsa.value();
            Constants.DefaultStringMapValue dsm = method.getAnnotation(Constants.DefaultStringMapValue.class);
            if (dsm != null)
                return array2map(dsm.value());

            return method.getName();
        }

        private Map<String, String> getStrutsActions(Object proxy,
                Class<? extends LocalizedLookupDispatchAction> apply) throws Throwable {
            Map<String, String> ret = new HashMap<String, String>();
            for (Method m : iMessages.getDeclaredMethods()) {
                if (m.getParameterTypes().length > 0)
                    continue;
                org.unitime.localization.messages.Messages.StrutsAction action = m
                        .getAnnotation(org.unitime.localization.messages.Messages.StrutsAction.class);
                if (action != null) {
                    Messages.DefaultMessage dm = m.getAnnotation(Messages.DefaultMessage.class);
                    if (action.apply() == null || action.apply().length == 0) {
                        try {
                            if (apply.getMethod(action.value(),
                                    new Class<?>[] { ActionMapping.class, ActionForm.class,
                                            HttpServletRequest.class, HttpServletResponse.class }) != null) {
                                ret.put((String) invoke(proxy, m, new Object[] {}), action.value());
                                if (dm != null)
                                    ret.put(dm.value(), action.value());
                            }
                        } catch (NoSuchMethodException e) {
                        }
                    } else {
                        for (Class<? extends LocalizedLookupDispatchAction> a : action.apply())
                            if (a.equals(apply)) {
                                ret.put((String) invoke(proxy, m, new Object[] {}), action.value());
                                if (dm != null)
                                    ret.put(dm.value(), action.value());
                            }
                    }
                }
            }
            return ret;
        }
    }

    public static interface StrutsActionsRetriever {
        Map<String, String> getStrutsActions(Class<? extends LocalizedLookupDispatchAction> apply);
    }

}