All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.runtime.xstream.LocalizedXStreams Maven / Gradle / Ivy

package cucumber.runtime.xstream;

import cucumber.deps.com.thoughtworks.xstream.XStream;
import cucumber.deps.com.thoughtworks.xstream.converters.Converter;
import cucumber.deps.com.thoughtworks.xstream.converters.ConverterLookup;
import cucumber.deps.com.thoughtworks.xstream.converters.ConverterRegistry;
import cucumber.deps.com.thoughtworks.xstream.converters.SingleValueConverter;
import cucumber.deps.com.thoughtworks.xstream.core.DefaultConverterLookup;
import cucumber.runtime.ParameterInfo;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class LocalizedXStreams {
    // XStream is thread-safe, but some converters below are using non-thread-safe objects, like NumberFormat!
    private final ThreadLocal> xStreamsByLocale = new ThreadLocal>() {
        @Override
        protected Map initialValue() {
            return new HashMap();
        }
    };
    private final ClassLoader classLoader;

    public LocalizedXStreams(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public LocalizedXStream get(Locale locale) {
        LocalizedXStream xStream = xStreamsByLocale.get().get(locale);
        if (xStream == null) {
            xStream = newXStream(locale);
            xStreamsByLocale.get().put(locale, xStream);
        }
        return xStream;
    }

    private LocalizedXStream newXStream(Locale locale) {
        DefaultConverterLookup lookup = new DefaultConverterLookup();
        return new LocalizedXStream(classLoader, lookup, lookup, locale);
    }

    public static class LocalizedXStream extends XStream {
        private final Locale locale;
        private final ThreadLocal> timeConverters = new ThreadLocal>() {
            @Override
            protected List initialValue() {
                return new ArrayList();
            }
        };

        public LocalizedXStream(ClassLoader classLoader, ConverterLookup converterLookup, ConverterRegistry converterRegistry, Locale locale) {
            super(null, null, classLoader, null, converterLookup, converterRegistry);
            this.locale = locale;
            autodetectAnnotations(true);

            // Override with our own Locale-aware converters.
            register(converterRegistry, new BigDecimalConverter(locale));
            register(converterRegistry, new BigIntegerConverter(locale));
            register(converterRegistry, new ByteConverter(locale));
            register(converterRegistry, new DateConverter(locale));
            register(converterRegistry, new CalendarConverter(locale));
            register(converterRegistry, new DoubleConverter(locale));
            register(converterRegistry, new FloatConverter(locale));
            register(converterRegistry, new IntegerConverter(locale));
            register(converterRegistry, new LongConverter(locale));
            register(converterRegistry, new PatternConverter());
            converterRegistry.registerConverter(new DynamicEnumConverter(locale), XStream.PRIORITY_VERY_HIGH);

            // Must be lower priority than the ones above, but higher than xstream's built-in ReflectionConverter
            converterRegistry.registerConverter(new DynamicClassWithStringAssignableConverter(), XStream.PRIORITY_LOW);
        }

        private void register(ConverterRegistry lookup, SingleValueConverter converter) {
            lookup.registerConverter(new SingleValueConverterWrapperExt(converter), XStream.PRIORITY_VERY_HIGH);
        }

        public void setParameterInfo(ParameterInfo parameterInfo) {
            if (parameterInfo != null) {
                List timeClasses = TimeConverter.getTimeClasses();
                for (Class timeClass : timeClasses) {
                    SingleValueConverterWrapperExt converterWrapper = (SingleValueConverterWrapperExt) getConverterLookup().lookupConverterForType(timeClass);
                    TimeConverter timeConverter = (TimeConverter) converterWrapper.getConverter();
                    timeConverter.setParameterInfoAndLocale(parameterInfo, locale);
                    timeConverters.get().add(timeConverter);
                }
            }
        }

        public void unsetParameterInfo() {
            for (TimeConverter timeConverter : timeConverters.get()) {
                timeConverter.removeOnlyFormat();
            }
            timeConverters.get().clear();
        }

        public SingleValueConverter getSingleValueConverter(Type type) {
            if (Object.class.equals(type)) {
                type = String.class;
            }
            if (type instanceof Class) {
                Class clazz = (Class) type;
                ConverterLookup converterLookup = getConverterLookup();
                Converter converter = converterLookup.lookupConverterForType(clazz);
                if (converter instanceof DynamicClassBasedSingleValueConverter) {
                    return ((DynamicClassBasedSingleValueConverter) converter).converterForClass(clazz);
                }
                return converter instanceof SingleValueConverter ? (SingleValueConverter) converter : null;
            } else {
                return null;
            }
        }

        public SingleValueConverter createListConverter(String delimiter, SingleValueConverter elementConverter) {
            return new ListConverter(delimiter, elementConverter);
        }

        public Locale getLocale() {
            return locale;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy