/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  javax.xml.bind.DatatypeConverter
 */
package org.apache.logging.log4j.core.config.plugins.util;

import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.Provider;
import java.security.Security;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.config.plugins.util.TypeConverter;
import org.apache.logging.log4j.core.layout.HtmlLayout;
import org.apache.logging.log4j.core.net.Facility;
import org.apache.logging.log4j.core.net.Protocol;
import org.apache.logging.log4j.core.util.Assert;
import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.EnglishEnums;

public final class TypeConverters {
    private static final Logger LOGGER = StatusLogger.getLogger();
    private final Map<Class<?>, TypeConverter<?>> registry = new ConcurrentHashMap();

    public static Object convert(String s, Class<?> clazz, Object defaultValue) {
        TypeConverter<?> converter = TypeConverters.findTypeConverter(Assert.requireNonNull(clazz, "No class specified to convert to."));
        if (converter == null) {
            throw new IllegalArgumentException("No type converter found for class: " + clazz.getName());
        }
        if (s == null) {
            return TypeConverters.parseDefaultValue(converter, defaultValue);
        }
        try {
            return converter.convert(s);
        }
        catch (Exception e) {
            LOGGER.warn("Error while converting string [{}] to type [{}]. Using default value [{}].", s, clazz, defaultValue, e);
            return TypeConverters.parseDefaultValue(converter, defaultValue);
        }
    }

    public static TypeConverter<?> findTypeConverter(Class<?> clazz) {
        return Holder.INSTANCE.registry.get(clazz);
    }

    private static Object parseDefaultValue(TypeConverter<?> converter, Object defaultValue) {
        if (defaultValue == null) {
            return null;
        }
        if (!(defaultValue instanceof String)) {
            return defaultValue;
        }
        try {
            return converter.convert((String)defaultValue);
        }
        catch (Exception e) {
            LOGGER.debug("Can't parse default value [{}] for type [{}].", defaultValue, converter.getClass(), e);
            return null;
        }
    }

    public static void registerTypeConverter(Class<?> clazz, TypeConverter<?> converter) {
        Holder.INSTANCE.registry.put(clazz, converter);
    }

    private TypeConverters() {
        this.registry.put(Boolean.class, new BooleanConverter());
        this.registry.put(Byte.class, new ByteConverter());
        this.registry.put(Character.class, new CharacterConverter());
        this.registry.put(Double.class, new DoubleConverter());
        this.registry.put(Float.class, new FloatConverter());
        this.registry.put(Integer.class, new IntegerConverter());
        this.registry.put(Long.class, new LongConverter());
        this.registry.put(Short.class, new ShortConverter());
        this.registry.put(Boolean.TYPE, this.registry.get(Boolean.class));
        this.registry.put(Byte.TYPE, new ByteConverter());
        this.registry.put(char[].class, new CharArrayConverter());
        this.registry.put(Double.TYPE, this.registry.get(Double.class));
        this.registry.put(Float.TYPE, this.registry.get(Float.class));
        this.registry.put(Integer.TYPE, this.registry.get(Integer.class));
        this.registry.put(Long.TYPE, this.registry.get(Long.class));
        this.registry.put(Short.TYPE, this.registry.get(Short.class));
        this.registry.put(byte[].class, new ByteArrayConverter());
        this.registry.put(Character.TYPE, new CharacterConverter());
        this.registry.put(BigInteger.class, new BigIntegerConverter());
        this.registry.put(BigDecimal.class, new BigDecimalConverter());
        this.registry.put(String.class, new StringConverter());
        this.registry.put(Charset.class, new CharsetConverter());
        this.registry.put(File.class, new FileConverter());
        this.registry.put(URL.class, new UrlConverter());
        this.registry.put(URI.class, new UriConverter());
        this.registry.put(Class.class, new ClassConverter());
        this.registry.put(Pattern.class, new PatternConverter());
        this.registry.put(Provider.class, new SecurityProviderConverter());
        this.registry.put(Level.class, new LevelConverter());
        this.registry.put(Filter.Result.class, new EnumConverter(Filter.Result.class));
        this.registry.put(Facility.class, new EnumConverter(Facility.class));
        this.registry.put(Protocol.class, new EnumConverter(Protocol.class));
        this.registry.put(HtmlLayout.FontSize.class, new EnumConverter(HtmlLayout.FontSize.class));
    }

    public static class UrlConverter
    implements TypeConverter<URL> {
        @Override
        public URL convert(String s) throws MalformedURLException {
            return new URL(s);
        }
    }

    public static class UriConverter
    implements TypeConverter<URI> {
        @Override
        public URI convert(String s) throws URISyntaxException {
            return new URI(s);
        }
    }

    public static class StringConverter
    implements TypeConverter<String> {
        @Override
        public String convert(String s) {
            return s;
        }
    }

    public static class ShortConverter
    implements TypeConverter<Short> {
        @Override
        public Short convert(String s) {
            return Short.valueOf(s);
        }
    }

    public static class SecurityProviderConverter
    implements TypeConverter<Provider> {
        @Override
        public Provider convert(String s) {
            return Security.getProvider(s);
        }
    }

    public static class PatternConverter
    implements TypeConverter<Pattern> {
        @Override
        public Pattern convert(String s) {
            return Pattern.compile(s);
        }
    }

    public static class LongConverter
    implements TypeConverter<Long> {
        @Override
        public Long convert(String s) {
            return Long.valueOf(s);
        }
    }

    public static class LevelConverter
    implements TypeConverter<Level> {
        @Override
        public Level convert(String s) {
            return Level.valueOf(s);
        }
    }

    public static class IntegerConverter
    implements TypeConverter<Integer> {
        @Override
        public Integer convert(String s) {
            return Integer.valueOf(s);
        }
    }

    private static final class Holder {
        private static final TypeConverters INSTANCE = new TypeConverters();

        private Holder() {
        }
    }

    public static class FloatConverter
    implements TypeConverter<Float> {
        @Override
        public Float convert(String s) {
            return Float.valueOf(s);
        }
    }

    public static class FileConverter
    implements TypeConverter<File> {
        @Override
        public File convert(String s) {
            return new File(s);
        }
    }

    public static class EnumConverter<E extends Enum<E>>
    implements TypeConverter<E> {
        private final Class<E> clazz;

        private EnumConverter(Class<E> clazz) {
            this.clazz = clazz;
        }

        @Override
        public E convert(String s) {
            return EnglishEnums.valueOf(this.clazz, s);
        }
    }

    public static class DoubleConverter
    implements TypeConverter<Double> {
        @Override
        public Double convert(String s) {
            return Double.valueOf(s);
        }
    }

    public static class ClassConverter
    implements TypeConverter<Class<?>> {
        @Override
        public Class<?> convert(String s) throws ClassNotFoundException {
            return Loader.loadClass(s);
        }
    }

    public static class CharsetConverter
    implements TypeConverter<Charset> {
        @Override
        public Charset convert(String s) {
            return Charset.forName(s);
        }
    }

    public static class CharArrayConverter
    implements TypeConverter<char[]> {
        @Override
        public char[] convert(String s) {
            return s.toCharArray();
        }
    }

    public static class CharacterConverter
    implements TypeConverter<Character> {
        @Override
        public Character convert(String s) {
            if (s.length() != 1) {
                throw new IllegalArgumentException("Character string must be of length 1: " + s);
            }
            return Character.valueOf(s.toCharArray()[0]);
        }
    }

    public static class ByteConverter
    implements TypeConverter<Byte> {
        @Override
        public Byte convert(String s) {
            return Byte.valueOf(s);
        }
    }

    public static class ByteArrayConverter
    implements TypeConverter<byte[]> {
        private static final String PREFIX_0x = "0x";
        private static final String PREFIX_BASE64 = "Base64:";

        @Override
        public byte[] convert(String value) {
            byte[] bytes;
            if (value == null || value.isEmpty()) {
                bytes = new byte[]{};
            } else if (value.startsWith(PREFIX_BASE64)) {
                String lexicalXSDBase64Binary = value.substring(PREFIX_BASE64.length());
                bytes = DatatypeConverter.parseBase64Binary((String)lexicalXSDBase64Binary);
            } else if (value.startsWith(PREFIX_0x)) {
                String lexicalXSDHexBinary = value.substring(PREFIX_0x.length());
                bytes = DatatypeConverter.parseHexBinary((String)lexicalXSDHexBinary);
            } else {
                bytes = value.getBytes(Charset.defaultCharset());
            }
            return bytes;
        }
    }

    public static class BooleanConverter
    implements TypeConverter<Boolean> {
        @Override
        public Boolean convert(String s) {
            return Boolean.valueOf(s);
        }
    }

    public static class BigIntegerConverter
    implements TypeConverter<BigInteger> {
        @Override
        public BigInteger convert(String s) {
            return new BigInteger(s);
        }
    }

    public static class BigDecimalConverter
    implements TypeConverter<BigDecimal> {
        @Override
        public BigDecimal convert(String s) {
            return new BigDecimal(s);
        }
    }
}
