/*
 *******************************************************************************
 * Copyright (C) 2004, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 */

package com.ibm.icu.dev.tool.docs;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

/**
 * Compare ICU4J and JDK APIS.
 *
 * TODO: compare protected APIs.  Reflection on Class allows you
 * to either get all inherited methods with public access, or get methods
 * on the particular class with any access, but no way to get all
 * inherited methods with any access.  Go figure.  
 */
public class ICUJDKCompare {
    static final boolean DEBUG = false;

    static final Class[] pairClasses = {
        com.ibm.icu.lang.UCharacter.class, java.lang.Character.class,
        com.ibm.icu.lang.UCharacter.UnicodeBlock.class, java.lang.Character.UnicodeBlock.class,
        com.ibm.icu.text.BreakIterator.class, java.text.BreakIterator.class,
        com.ibm.icu.text.Collator.class, java.text.Collator.class,
        com.ibm.icu.text.DateFormat.class, java.text.DateFormat.class,
        com.ibm.icu.text.DateFormatSymbols.class, java.text.DateFormatSymbols.class,
        com.ibm.icu.text.DecimalFormat.class, java.text.DecimalFormat.class,
        com.ibm.icu.text.DecimalFormatSymbols.class, java.text.DecimalFormatSymbols.class,
        com.ibm.icu.text.UFormat.class, java.text.Format.class,
        com.ibm.icu.text.MessageFormat.class, java.text.MessageFormat.class,
        com.ibm.icu.text.NumberFormat.class, java.text.NumberFormat.class,
        com.ibm.icu.text.SimpleDateFormat.class, java.text.SimpleDateFormat.class,
        com.ibm.icu.util.Calendar.class, java.util.Calendar.class,
        com.ibm.icu.util.Currency.class, java.util.Currency.class,
        com.ibm.icu.util.GregorianCalendar.class, java.util.GregorianCalendar.class,
        com.ibm.icu.util.SimpleTimeZone.class, java.util.SimpleTimeZone.class,
        com.ibm.icu.util.TimeZone.class, java.util.TimeZone.class,
        com.ibm.icu.util.ULocale.class, java.util.Locale.class,
        com.ibm.icu.util.UResourceBundle.class, java.util.ResourceBundle.class
    };

    static final String[] pairs = new String[pairClasses.length];
    static {
        for (int i = 0; i < pairs.length; ++i) {
            pairs[i] = pairClasses[i].getName();
        }
    }

    public static void main(String[] args) {
        System.out.println("ICU and Java API Comparison");
	System.out.println("ICU Version " + com.ibm.icu.util.VersionInfo.ICU_VERSION);
        System.out.println("JDK Version " + System.getProperty("java.version"));

        for (int i = 0; i < pairs.length; i += 2) {
            try {
                compare(pairClasses[i], pairClasses[i+1]);
            }
            catch (Exception e) {
                System.out.println("exception: " + e);
                System.out.println("between " + pairs[i] + " and " + pairs[i+1]);
                e.printStackTrace();
            }
        }
    }

    static class MorC {
        private Method mref;
        private Constructor cref;

        MorC(Method m) {
            mref = m;
        }

        MorC(Constructor c) {
            cref = c;
        }

        int getModifiers() {
            return mref == null ? cref.getModifiers() : mref.getModifiers();
        }

        Class getReturnType() {
            return mref == null ? void.class : mref.getReturnType();
        }

        Class[] getParameterTypes() {
            return mref == null ? cref.getParameterTypes() : mref.getParameterTypes();
        }

        String getName() {
            return mref == null ? "<init>" : mref.getName();
        }
    }
    
    static void compare(Class class1, Class class2) throws Exception {
        String n1 = class1.getName();
        String n2 = class2.getName();

        MorC[] conss1 = getMorCArray(class1.getConstructors());
        MorC[] conss2 = getMorCArray(class2.getConstructors());

        Map cmap1 = getMethodMap(conss1);
        Map cmap2 = getMethodMap(conss2);

        MorC[] meths1 = getMorCArray(class1.getMethods());
        MorC[] meths2 = getMorCArray(class2.getMethods());

        Map map1 = getMethodMap(meths1);
        Map map2 = getMethodMap(meths2);

        Field[] fields1 = class1.getFields();
        Field[] fields2 = class2.getFields();

        Set set1 = getFieldSet(fields1);
        Set set2 = getFieldSet(fields2);

        PrintWriter pw = new PrintWriter(System.out);

	Map diffConss = diffMethodMaps(cmap2, cmap1);
	Map diffMeths = diffMethodMaps(map2, map1);
	Set diffFields = diffFieldSets(set2, set1);
	
	if (diffConss.size() + diffMeths.size() + diffFields.size() > 0) {
	    pw.println("\n============\nAPI in " + n2 + " missing from " + n1);
	    if (diffConss.size() > 0) {
		pw.println("\nCONSTRUCTORS");
		dumpMethodMap(diffConss, pw);
	    }
	    if (diffMeths.size() > 0) {
		pw.println("\nMETHODS");
		dumpMethodMap(diffMeths, pw);
	    }
	    if (diffFields.size() > 0) {
		pw.println("\nFIELDS");
		dumpFieldSet(diffFields, pw);
	    }
	} else {
	    pw.println("\n" + n1 + " OK");
	}
    }

    static final class MethodRecord {
        MorC[] overrides;

        MethodRecord(MorC m) {
            overrides = new MorC[] { m };
        }

        MethodRecord(MorC[] ms) {
            overrides = ms;
        }

        MethodRecord copy() {
            return new MethodRecord((MorC[])overrides.clone());
        }

        int count() {
            for (int i = 0; i < overrides.length; ++i) {
                if (overrides[i] == null) {
                    return i;
                }
            }
            return overrides.length;
        }

        void add(MorC m) {
            MorC[] temp = new MorC[overrides.length + 1];
            for (int i = 0; i < overrides.length; ++i) {
                temp[i] = overrides[i];
            }
            temp[overrides.length] = m;
            overrides = temp;
        }

        void remove(int index) {
            int i = index;
            while (overrides[i] != null && i < overrides.length-1) {
                overrides[i] = overrides[i+1];
                ++i;
            }
            overrides[i] = null;
        }

        // if a call to a method can be handled by a call to t, remove the
        // method from our list, and return true
        boolean removeOverridden(MorC t) {
            boolean result = false;
            int i = 0;
            while (i < overrides.length) {
                MorC m = overrides[i];
                if (m == null) {
                    break;
                }
                if (handles(t, m)) {
                    remove(i);
                    result = true;
                } else {
                    ++i;
                }
            }
            return result;
        }

        // remove all methods handled by any method of mr
        boolean removeOverridden(MethodRecord mr) {
            boolean result = false;
            for (int i = 0; i < mr.overrides.length; ++i) {
                MorC t = mr.overrides[i];
                if (t == null) {
                    // this shouldn't happen, as the target record should not have been modified
                    throw new InternalError();
                }
                if (removeOverridden(t)) {
                    result = true;
                }
            }
            return result;
        }

        void msg(MorC t, MorC m, String msg) {
            StringBuffer buf = new StringBuffer();
            buf.append(t.getName());
            buf.append(" ");
            buf.append(msg);
            buf.append("\n   ");
            toString(t, buf);
            buf.append("\n   ");
            toString(m, buf);
            System.out.println(buf.toString());
        }

        boolean handles(MorC t, MorC m) {
            // relevant modifiers must match
            if ((t.getModifiers() & MOD_MASK) != (m.getModifiers() & MOD_MASK)) {
                if (DEBUG) msg(t, m, "modifier mismatch");
                return false;
            }

            Class tr = pairClassEquivalent(t.getReturnType());
            Class mr = pairClassEquivalent(m.getReturnType());
            if (!assignableFrom(mr, tr)) { // t return type must be same or narrower than m
                if (DEBUG) msg(t, m, "return value mismatch");
                return false;
            }
            Class[] tts = t.getParameterTypes();
            Class[] mts = m.getParameterTypes();
            if (tts.length != mts.length) {
                if (DEBUG) msg(t, m, "param count mismatch");
                return false;
            }

            for (int i = 0; i < tts.length; ++i) {
                Class tc = pairClassEquivalent(tts[i]);
                Class mc = pairClassEquivalent(mts[i]);
                if (!assignableFrom(tc, mc)) { // m param must be same or narrower than t
                    if (DEBUG) msg(t, m, "parameter " + i + " mismatch, " + 
                                   tts[i].getName() + " not assignable from " + mts[i].getName());
                    return false;
                }
            }
            return true;
        }

        public void toString(MorC m, StringBuffer buf) {
            int mod = m.getModifiers();
            if (mod != 0) {
                buf.append(Modifier.toString(mod) + " ");
            }
            buf.append(m.getReturnType().getName() + " (");
            Class[] ptypes = m.getParameterTypes();
            for (int j = 0; j < ptypes.length; ++j) {
                if (j > 0) {
                    buf.append(", ");
                }
                buf.append(ptypes[j].getName());
            }
            buf.append(')');
        }

        public String toString() {
            StringBuffer buf = new StringBuffer();
            buf.append(overrides[0].getName());
            for (int i = 0; i < overrides.length; ++i) {
                MorC m = overrides[i];
                if (m == null) {
                    break;
                }
                buf.append("\n   ");
                toString(m, buf);
            }
            return buf.toString();
        }
    }

    static MorC[] getMorCArray(Constructor[] cons) {
        MorC[] result = new MorC[cons.length];
        for (int i = 0 ; i < cons.length; ++i) {
            result[i] = new MorC(cons[i]);
        }
        return result;
    }

    static MorC[] getMorCArray(Method[] meths) {
        MorC[] result = new MorC[meths.length];
        for (int i = 0 ; i < meths.length; ++i) {
            result[i] = new MorC(meths[i]);
        }
        return result;
    }

    static Map getMethodMap(MorC[] meths) {
        Map result = new TreeMap();
        for (int i = 0; i < meths.length; ++i) {
            MorC m = meths[i];
            String key = m.getName();
            MethodRecord mr = (MethodRecord)result.get(key);
            if (mr == null) {
                mr = new MethodRecord(m);
                result.put(key, mr);
            } else {
                mr.add(m);
            }
        }
        return result;
    }

    static void dumpMethodMap(Map m, PrintWriter out) {
        Iterator iter = m.entrySet().iterator();
        while (iter.hasNext()) {
            MethodRecord mr = (MethodRecord)((Map.Entry)iter.next()).getValue();
            out.println(mr);
        }
        out.flush();
    }

    static Map diffMethodMaps(Map m1, Map m2) {
        // get all the methods in m1 that aren't mentioned in m2 at all
        Map result = (Map)((TreeMap)m1).clone();
        result.keySet().removeAll(m2.keySet());
        return result;
    }

    static final boolean[][] assignmentMap = {
        // bool   char   byte  short    int   long  float double   void
        {  true, false, false, false, false, false, false, false, false }, // boolean
        { false,  true,  true,  true, false, false, false, false, false }, // char
        { false, false,  true, false, false, false, false, false, false }, // byte
        { false, false,  true,  true, false, false, false, false, false }, // short
        { false,  true,  true,  true,  true, false, false, false, false }, // int
        { false,  true,  true,  true,  true,  true, false, false, false }, // long
        { false,  true,  true,  true,  true, false,  true, false, false }, // float
        { false,  true,  true,  true,  true, false,  true,  true, false }, // double
        { false, false, false, false, false, false, false, false,  true }, // void
    };

    static final Class[] prims = {
        boolean.class, char.class, byte.class, short.class, 
        int.class, long.class, float.class, double.class, void.class
    };

    static int primIndex(Class cls) {
        for (int i = 0; i < prims.length; ++i) {
            if (cls == prims[i]) {
                return i;
            }
        }
        throw new InternalError("could not find primitive class: " + cls);
    }

    static boolean assignableFrom(Class lhs, Class rhs) {
        if (lhs == rhs) {
            return true;
        }
        if (lhs.isPrimitive()) {
            if (!rhs.isPrimitive()) {
                return false;
            }
            int lhsx = primIndex(lhs);
            int rhsx = primIndex(rhs);
            return assignmentMap[lhsx][rhsx];
        }
        return lhs.isAssignableFrom(rhs);
    }

    static String toString(Field f) {
        StringBuffer buf = new StringBuffer(f.getName());
        int mod = f.getModifiers() & MOD_MASK;
        if (mod != 0) {
            buf.append(" " + Modifier.toString(mod));
        }
        buf.append(" " + pairEquivalent(f.getType().getName()));
        return buf.toString();
    }

    static Set getFieldSet(Field[] fs) {
        Set set = new TreeSet();
        for (int i = 0; i < fs.length; ++i) {
            set.add(toString(fs[i]));
        }
        return set;
    }

    static Set diffFieldSets(Set s1, Set s2) {
        Set result = (Set)((TreeSet)s1).clone();
        result.removeAll(s2);
        return result;
    }

    static void dumpFieldSet(Set s, PrintWriter pw) {
        Iterator iter = s.iterator();
        while (iter.hasNext()) {
            pw.println(iter.next());
        }
        pw.flush();
    }

    // given a target string, if it matches the first of one of our pairs, return the second
    static String pairEquivalent(String target) {
        for (int i = 0; i < pairs.length; i += 2) {
            if (target.equals(pairs[i])) {
                return pairs[i+1];
            }
        }
        return target;
    }

    static Class pairClassEquivalent(Class target) {
        for (int i = 0; i < pairClasses.length; i += 2) {
            if (target.equals(pairClasses[i])) {
                return pairClasses[i+1];
            }
        }
        return target;
    }

    static final int MOD_MASK = ~(Modifier.FINAL|Modifier.SYNCHRONIZED|
                                  Modifier.VOLATILE|Modifier.TRANSIENT|Modifier.NATIVE);
}
