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

oms3.Conversions Maven / Gradle / Ivy

There is a newer version: 0.8.1
Show newest version
/*
 * $Id:$
 * 
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 
 *  1. The origin of this software must not be misrepresented; you must not
 *     claim that you wrote the original software. If you use this software
 *     in a product, an acknowledgment in the product documentation would be
 *     appreciated but is not required.
 * 
 *  2. Altered source versions must be plainly marked as such, and must not be
 *     misrepresented as being the original software.
 * 
 *  3. This notice may not be removed or altered from any source
 *     distribution.
 */
package oms3;

import java.io.File;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Conversion Utilities. This class deals with conversion from string values
 * to some known types.
 * 
 * @author Olaf David
 */
public class Conversions {

    /** Conversion SPI */
    static private ServiceLoader convServices = ServiceLoader.load(ConversionProvider.class);
    //
    static final char LB = '{';
    static final char RB = '}';
    static final char SEP = ',';
    static final Pattern pattern = Pattern.compile("(\\w+)\\s*(\\[[0-9]+\\])*?");
    static final Pattern splitP = Pattern.compile(Character.toString(SEP));
    public static boolean debug = false;
    /** Some common date patters */
    static private final String[] fmt = {
        "yyyy-MM-dd'T'HH:mm:ss",
        "yyyy-MM-dd'T'HH:mm",
        "yyyy-MM-dd hh:mm",
        "yyyy-MM-dd hh:mm:ss",
        "yyyy-MM-dd", // ISO
        "MM-dd-yyyy", // US
        "MM/dd/yyyy",
        "dd.MM.yyyy", // DE
        "yyyy.MM.dd", // DE
        "yyyy MM dd H m s" // MMS
    };

    public static class Params {

        HashMap arg = new HashMap();

        public void add(Class from, Class to, Object par) {
            arg.put(key(from, to), par);
        }

        public Object get(Class from, Class to) {
            return arg.get(key(from, to));
        }
    }
    
    public static boolean canConvert(Class from, Class to) {
        if (from == String.class && to.isArray()) {
            return true;
        }
        // get it from the internal cache.new ArrayConverter((String) from).getArrayForType(to);
        Converter c = co.get(key(from, to));
        if (c == null) {
            // service provider lookup
            c = lookupConversionService(from, to);
            if (c == null) {
                return false;
            }
        }
        return true;
    }

//    public static Params createDefault() {
//        Params p = new Params();
//        p.add(double.class, String.class, "10.5");
//        return p;
//    }
    /** Convert a String value into an object of a certain type
     *
     * @param to the type to convert to
     * @param from the value to convert
     * @param arg conversion argument (e.g. Date format)
     * @return the object of a certain type.
     */
    public static  T convert(Object from, Class to, Params arg) {
        if (from == null) {
            throw new NullPointerException("from");
        }
        if (to == null) {
            throw new NullPointerException("to");
        }
        if (from.getClass() == String.class && to.isArray()) {
            return new ArrayConverter((String) from).getArrayForType(to);
        }
        // get it from the internal cache.
        @SuppressWarnings("unchecked")
        Converter c = co.get(key(from.getClass(), to));
        if (c == null) {
            // service provider lookup
            c = lookupConversionService(from.getClass(), to);
            if (c == null) {
                throw new ComponentException("No Converter: " + from + " (" + from.getClass() + ") -> " + to);
            }
            co.put(key(from.getClass(), to), c);
        }
        Object param = null;
        if (arg != null) {
            param = arg.get(from.getClass(), to);
        }
        return (T) c.convert(from, param);
    }

    public static  T convert(Object from, Class to) {
        return convert(from, to, null);
    }
    // SPI

    /**
     * Lookup a conversion service
     * 
     * @param from
     * @param to
     * @return
     */
    @SuppressWarnings("unchecked")
    private static  Converter lookupConversionService(Class from, Class to) {
        for (ConversionProvider converter : convServices) {
            Converter c = converter.getConverter(from, to);
            if (c != null) {
                return c;
            }
        }
        return null;
    }

    /**
     *
     * @param src  e.g  test[1][3]
     * @return     [test,1,2]
     */
    public static String[] parseArrayElement(String src) {
        Matcher matcher = pattern.matcher(src.trim());
        List a = new ArrayList();
        while (matcher.find()) {
            a.add(matcher.group(0));
        }
        return a.toArray(new String[0]);
    }

    /** Get the array base type
     * 
     * @param array
     * @return
     */
    private static Class getArrayBaseType(Class array) {
        while (array.isArray()) {
            array = array.getComponentType();
        }
        return array;
    }

    /** ArrayConverter
     * 
     */
    static class ArrayConverter {

        String[] content;
        String layout;
        /* 10 dimensions max.*/
        int[] dims = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};

        private int count(String s, char c) {
            int count = 0;
            int len = s.length();
            for (int i = 0; i < len; i++) {
                if (s.charAt(i) == c) {
                    count++;
                }
            }
            return count;
        }

        ArrayConverter(String text) {
            text = text.trim();
            if (count(text, '}') != count(text, '}')) {
                throw new IllegalArgumentException("Brackets mismatch.");
            }
            if (debug) {
                System.out.println(text);
            }
            String mass = text.replace(LB, ' ').replace(RB, ' ').trim();
            content = splitP.split(mass);
            if (debug) {
                System.out.println(mass.isEmpty());
                System.out.println("content " + Arrays.toString(content));
            }
            layout = changed(text, mass.isEmpty() ? 0 : content.length);
            if (debug) {
                System.out.println("layout " + layout);
            }
            parseDims(layout);
        }

        private String changed(String inp, int len) {
            StringBuilder c = new StringBuilder();
            int count = 0;
            int b = 0;
            boolean first = true;
            for (int i = 0; i < inp.length(); i++) {
                char ch = inp.charAt(i);
                switch (ch) {
                    case ' ':
                        break;    // TODO, repect string quotes.
                    case LB:
                    case RB:
                    case SEP:
                        first = true;
                        c.append(ch);
                        break;
                    default:
                        if (first) {
                            c.append(count++);
                            first = false;
                        }
                }
            }
            if (count != len) {
                throw new IllegalArgumentException(count + "!=" + len);
            }
            return c.toString();
        }

        private Class[] types(int[] dims, Class basetype) {
            int i = 0;
            while (dims[i] > -1) {
                i++;
            }
            if (debug) {
                System.out.println(" rank " + i);
            }
            Class[] c = new Class[i];
            c[i - 1] = basetype;
            while (--i > 0) {
                c[i - 1] = Array.newInstance(c[i], 0).getClass();
            }
            if (debug) {
                System.out.println("Types " + java.util.Arrays.toString(c));
            }
            return c;
        }

        private void parseDims(String layout) {
            for (int i = 0, level = -1; i < layout.length(); i++) {
                char c = layout.charAt(i);
                switch (c) {
                    case LB:
                        if (level == dims.length - 1) {
                            throw new UnsupportedOperationException("Can only handle arrays with length " + dims.length);
                        }
                        if (i > 0 && layout.charAt(i - 1) == LB) {
                            dims[level]++;
                        }
                        dims[++level] = 0;
                        break;
                    case RB:
                        level--;
                        break;
                    case SEP:
                        dims[level]++;
                        break;
                    default:
                        if (dims[level] == 0) {
                            dims[level]++;
                        }
                }
            }
            if (debug) {
                System.out.println("dims :" + Arrays.toString(dims));
            }
        }

        @SuppressWarnings("unchecked")
         T getArrayForType(Class type) {
            if (!type.isArray()) {
                throw new IllegalArgumentException("Not an array type");
            }
            Class cType = getArrayBaseType(type);
            Object o = new Parser(co.get(key(String.class, cType))).parse(0, layout, types(dims, cType));
            if (o.getClass() != type) {
                throw new RuntimeException(o.getClass() + "!=" + type);
            }
            return (T) o;
        }

        /**
         * Internal Parser.
         */
        private class Parser {

            int idx = 1;
            Converter converter;

            Parser(Converter converter) {
                if (converter == null) {
                    throw new RuntimeException("cannot convert.");
                }
                this.converter = converter;
            }

            @SuppressWarnings("unchecked")
            Object parse(int level, String layout, Class[] cc) {
                int arridx = 0;
                Object arr = Array.newInstance(cc[level], dims[level]);
                while (idx < layout.length()) {
                    char c = layout.charAt(idx);
                    switch (c) {
                        case LB:
                            idx++;
                            Object elem = parse(level + 1, layout, cc);
//                        System.out.println("Adding Array " + elem + " to " + arr.getClass() + " at " + arridx);
                            System.out.flush();
                            Array.set(arr, arridx, elem);
                            break;
                        case RB:
                            return arr;
                        case SEP:
                            arridx++;
                            break;
                        default:
                            int index = 0;
                            while (Character.isDigit(layout.charAt(idx))) {
                                index = index * 10 + (layout.charAt(idx++) - '0');
                            }
                            idx--;
                            Object o = converter.convert(content[index], null);
                            try {
                                Array.set(arr, arridx, o);
                            } catch (IllegalArgumentException E) {
                                System.out.println(arr.getClass() + " element " + arridx + " " + o + " " + o.getClass());
                                throw E;
                            }
                    }
                    idx++;
                }
                return arr;
            }
        }
    }

    public static String formatISO(Date date) {
        return ISO().format(date);
    }

    public static SimpleDateFormat ISO() {
        return new SimpleDateFormat(fmt[3]);
    }

    /**
     * parse the date using the formats above. This is thread safe.
     *
     * @param date
     * @return
     */
    private static Date parse(String date) {
        for (int i = 0; i < fmt.length; i++) {
            try {
                SimpleDateFormat df = new SimpleDateFormat(fmt[i]);
                return df.parse(date);
            } catch (ParseException E) {
                // keep trying
            }
        }
        throw new IllegalArgumentException(date);
    }

//    DecimalFormat dfmt
    private final static String key(Class from, Class to) {
        return from.getName() + "->" + to.getName();
    }
    /**
     * Converter table.
     */
    @SuppressWarnings("serial")
    private static Map co = new HashMap() {

        @Override
        public Converter put(String key, Converter value) {
            Converter v = super.put(key, value);
            if (v != null) {
                throw new IllegalArgumentException("Duplicate Converter for " + key);
            }
            return v;
        }

        {
            put(key(String.class, String.class), new Converter() {

                @Override
                public String convert(String s, Object arg) {
                    return s;
                }
            });
            put(key(BigDecimal.class, Double.class), new Converter() {

                @Override
                public Double convert(BigDecimal s, Object arg) {
                    return s.doubleValue();
                }
            });
            put(key(Integer.class, Double.class), new Converter() {

                @Override
                public Double convert(Integer s, Object arg) {
                    return s.doubleValue();
                }
            });

            put(key(double[].class, String.class), new Converter() {

                @Override
                public String convert(double[] s, Object arg) {
                    StringBuilder b = new StringBuilder("{");
                    if (s.length > 0) {
                        for (int i = 0; i < s.length - 1; i++) {
                            b.append(s[i] + ", ");
                        }
                        b.append(s[s.length - 1]);
                    }
                    b.append("}");
                    return b.toString();
                }
            });
            put(key(double[][].class, String.class), new Converter() {

                @Override
                public String convert(double[][] s, Object arg) {
                    StringBuilder b = new StringBuilder("{");
                    if (s.length > 0) {
                        for (int i = 0; i < s.length - 1; i++) {
                            b.append(Conversions.convert(s[i], String.class) + ", ");
                        }
                        b.append(Conversions.convert(s[s.length - 1], String.class));
                    }
                    b.append("}");
                    return b.toString();
                }
            });
            put(key(int[].class, String.class), new Converter() {

                @Override
                public String convert(int[] s, Object arg) {
                    StringBuilder b = new StringBuilder("{");
                    if (s.length > 0) {
                        for (int i = 0; i < s.length - 1; i++) {
                            b.append(s[i] + ", ");
                        }
                        b.append(s[s.length - 1]);
                    }
                    b.append("}");
                    return b.toString();
                }
            });
            put(key(int[][].class, String.class), new Converter() {

                @Override
                public String convert(int[][] s, Object arg) {
                    StringBuilder b = new StringBuilder("{");
                    if (s.length > 0) {
                        for (int i = 0; i < s.length - 1; i++) {
                            b.append(Conversions.convert(s[i], String.class) + ", ");
                        }
                        b.append(Conversions.convert(s[s.length - 1], String.class));
                    }
                    b.append("}");
                    return b.toString();
                }
            });
            put(key(String.class, URL.class), new Converter() {    // File

                @Override
                public URL convert(String s, Object arg) {
                    try {
                        return new URL(s);
                    } catch (MalformedURLException ex) {
                        throw new IllegalArgumentException(s, ex);
                    }
                }
            });
            put(key(String.class, File.class), new Converter() {    // File

                @Override
                public File convert(String s, Object arg) {
                    return new File(s);
                }
            });
            put(key(String.class, Date.class), new Converter() {    // File

                @Override
                public Date convert(String s, Object arg) {
                    if (arg instanceof DateFormat) {
                        try {
                            return ((DateFormat) arg).parse(s);
                        } catch (ParseException E) {
                            throw new RuntimeException(E);
                        }
                    }
                    return parse(s);
                }
            });
            put(key(String.class, Calendar.class), new Converter() {    // Calendar

                @Override
                public Calendar convert(String s, Object arg) {
                    Date d = null;
                    if (arg instanceof DateFormat) {
                        try {
                            d = ((DateFormat) arg).parse(s);
                        } catch (ParseException E) {
                            throw new RuntimeException(E);
                        }
                    } else {
                        d = parse(s);
                    }
                    Calendar cal = new GregorianCalendar();
                    cal.setTime(d);
                    return cal;
                }
            });
            put(key(GregorianCalendar.class, String.class), new Converter() {    // Calendar

                @Override
                public String convert(GregorianCalendar s, Object arg) {
                    if (arg instanceof DateFormat) {
                        return ((DateFormat) arg).format(s.getTime());
                    } else {
                        return ISO().format(s.getTime());
                    }
                }
            });
            put(key(Double.class, String.class), new Converter() {    // Double

                @Override
                public String convert(Double s, Object arg) {
                    if (arg instanceof NumberFormat) {
                        NumberFormat nf = (NumberFormat) arg;
                        return nf.format(s);
                    }
                    return s.toString();
                }
            });
            put(key(Float.class, String.class), new Converter() {    // Double

                @Override
                public String convert(Float s, Object arg) {
                    if (arg instanceof NumberFormat) {
                        NumberFormat nf = (NumberFormat) arg;
                        return nf.format(s);
                    }
                    return s.toString();
                }
            });
            put(key(Integer.class, String.class), new Converter() {    // Integer

                @Override
                public String convert(Integer s, Object arg) {
                    return s.toString();
                }
            });
            put(key(String.class, BigDecimal.class), new Converter() {    // File

                @Override
                public BigDecimal convert(String s, Object arg) {
                    return new BigDecimal(s.trim());
                }
            });
            put(key(String.class, double.class), new Converter() {    // double

                @Override
                public Double convert(String s, Object arg) {
                    return Double.parseDouble(s.trim());
                }
            });
            put(key(String.class, Double.class), get(key(String.class, double.class)));
            put(key(String.class, float.class), new Converter() {     // float

                @Override
                public Float convert(String s, Object arg) {
                    return Float.parseFloat(s.trim());
                }
            });
            put(key(String.class, Float.class), get(key(String.class, float.class)));
            put(key(String.class, long.class), new Converter() {       // long

                @Override
                public Long convert(String s, Object arg) {
                    return Long.parseLong(s.trim());
                }
            });
            put(key(String.class, Long.class), get(key(String.class, long.class)));
            put(key(String.class, int.class), new Converter() {        // int

                @Override
                public Integer convert(String s, Object arg) {
                    return Integer.parseInt(s.trim());
                }
            });
            put(key(String.class, Integer.class), get(key(String.class, int.class)));
            put(key(String.class, short.class), new Converter() {      // short

                @Override
                public Short convert(String s, Object arg) {
                    return Short.parseShort(s.trim());
                }
            });
            put(key(String.class, Short.class), get(key(String.class, short.class)));
            put(key(String.class, byte.class), new Converter() {         // byte

                @Override
                public Byte convert(String s, Object arg) {
                    return Byte.parseByte(s.trim());
                }
            });
            put(key(String.class, Byte.class), get(key(String.class, byte.class)));
            put(key(boolean.class, String.class), new Converter() {       // boolean

                @Override
                public String convert(Boolean s, Object arg) {
                    return s.toString();
                }
            });
            put(key(Boolean.class, String.class), get(key(boolean.class, String.class)));
            put(key(String.class, boolean.class), new Converter() {       // boolean

                @Override
                public Boolean convert(String s, Object arg) {
                    return Boolean.parseBoolean(s.trim());
                }
            });
            put(key(String.class, Boolean.class), get(key(String.class, boolean.class)));
            put(key(String.class, char.class), new Converter() {        // String

                @Override
                public Character convert(String s, Object arg) {
                    return s.trim().charAt(0);
                }
            });
            put(key(String.class, Character.class), get(key(String.class, char.class)));
            put(key(Integer.class, int.class), new Converter() {         // byte

                @Override
                public Integer convert(Integer s, Object arg) {
                    return s;
                }
            });
            put(key(Double.class, double.class), new Converter() {         // double

                @Override
                public Double convert(Double s, Object arg) {
                    return s;
                }
            });
            put(key(Float.class, float.class), new Converter() {         // double

                @Override
                public Float convert(Float s, Object arg) {
                    return s;
                }
            });
            put(key(Boolean.class, boolean.class), new Converter() {         // byte

                @Override
                public Boolean convert(Boolean s, Object arg) {
                    return s;
                }
            });
            // add more
        }
    };

    public static void main(String[] args) throws ParseException {
        
        String t = "t[10]";
        
        System.out.println(Arrays.toString(Conversions.parseArrayElement(t)));


        double a = 1231.2345672828288284;
        System.out.println(String.format(Locale.US, "'%2.5f'", a));

//        Formatter f = new Formatter();
//        NumberFormat formatter = new DecimalFormat("#0.000");
//        System.out.println(formatter.);

//        System.out.println("1 " + Double.class.isAssignableFrom(Object.class));
//        System.out.println("2 " + Object.class.isAssignableFrom(Double.class));
//        System.out.println("3 " + Number.class.isAssignableFrom(Double.class));
//        System.out.println("4 " + double.class.isAssignableFrom(Double.class));
//        System.out.println("5 " + Double.class.isAssignableFrom(double.class));
//        System.out.println("6 " + Double.class.getCanonicalName());
//        System.out.println("7 " + Double.class.getName());
//        System.out.println("8 " + Double.class.getSimpleName());
//
//        Currency c = convert("USD", Currency.class);
//        Color col = convert("ff0110", Color.class);
//        System.out.println(c);
//        System.out.println(col);


        System.out.print(co.keySet());

    }
////        String content = "{{   333.345, 12.23},  {444.1, 222.4},{1.2, 3.4}}";
////        String content3 = "{{   333.345, 12.23, 444.1},{ 222.4 , 1.2, 3.4}}";
////        String content1 = "{333.345, 12.23, 444.1, 222.4,1.2, 3.4}";
//////        String content11 = "[333.345     12.23 444.1 222.4 1.2 3.4]";
//        String b = "{{{333.345, 12.23},{444.1, 222.4},{1.2, 3.4}}}";
//
//        String b = "{ 0.0, 0.0,0.0,0.1500000059605,0.0,0.0,0.0,0.0,0.0,0.1500000059605,0.8000000119209,0.0,0.05000000074506,0.6998999714851,0.0,0.660000026226,1.759899973869,0.0,0.2599000036716,0.01989999972284,1.799900054932,1.840000033379,1.700000047684,1.070000052452,0.6800000071526,3.72000002861,3.410000085831,0.140000000596,3.650000095367,1.659899950027,1.070000052452,0.5400000214577,3.059900045395,3.25,3.910000085831,1.44000005722,3.089900016785,1.870000004768,1.539899945259,1.460000038147,2.599900007248,1.090000033379,2.420000076294,2.259900093079,2.900000095367,1.129899978638,3.789900064468,3.799900054932,3.0,1.389899969101,5.159900188446,1.700000047684,1.330000042915,0.7400000095367,1.049900054932,1.809900045395,0.3898999989033,0.0,0.9300000071526,0.5,2.700000047684,0.0,0.1098999977112,0.5,0.0,1.200000047684,0.2599000036716,0.1199000030756}";
//
////        String c = "t1_est(1,2)";
////          System.out.println(Arrays.asList(parseArrayElement(c)));
//
//        String c = "t1_est(1  ,2) ; basin; abc(1)";
////        System.out.println(Arrays.asList(parseArrayElement(c)));
//
//        String t[] = c.split("\\s*;\\s*");
//        for (String string : t) {
//            System.out.println("string '" + string + "'");
//        }
//        //this is a comment
//        //this is a comment
//
//        Object arr = convert(b, double[][][].class);
//        System.out.println(arr);
//        System.out.println(java.util.Arrays.toString(((double[]) arr)));
//////      System.out.println(Arrays.toString(((String[])new P(content1).getArray(String.class))));
//    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy