1aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
4aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/*
5aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
6aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Copyright (C) 1996-2014, International Business Machines Corporation and
7aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * others. All Rights Reserved.
8aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
9aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *
10aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
11aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
12aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpackage android.icu.dev.test.serializable;
13aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
14f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.ByteArrayInputStream;
15f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.ByteArrayOutputStream;
16f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.File;
17f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.FileInputStream;
18f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.FileOutputStream;
19f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.IOException;
20f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.InputStream;
21f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.ObjectInputStream;
22f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.io.ObjectOutputStream;
23f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.lang.reflect.Modifier;
24f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.net.URL;
25f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.util.ArrayList;
26aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Date;
27f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.util.Enumeration;
28aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.HashMap;
29f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.util.List;
30aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Locale;
31aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
32aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.format.MeasureUnitTest;
33aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.format.PluralRulesTest;
34aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.JavaTimeZone;
35aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.OlsonTimeZone;
36aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.TimeZoneAdapter;
37f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.impl.URLHandler;
38aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Utility;
39aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.math.BigDecimal;
40aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.math.MathContext;
41aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.AnnualTimeZoneRule;
42aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.Calendar;
43aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.Currency;
44aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.DateInterval;
45aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.DateTimeRule;
46aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.GregorianCalendar;
47aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ICUCloneNotSupportedException;
48aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ICUException;
49aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ICUUncheckedIOException;
50aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.InitialTimeZoneRule;
51aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.RuleBasedTimeZone;
52aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.SimpleTimeZone;
53aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.TimeArrayTimeZoneRule;
54aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.TimeZone;
55aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.TimeZoneRule;
56aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ULocale;
57aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.VTimeZone;
58aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
59aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/**
60aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @author emader
61aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *
62aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * TODO To change the template for this generated type comment go to
63aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Window - Preferences - Java - Code Style - Code Templates
64aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
65f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertpublic class SerializableTestUtility {
66f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static Class serializable;
67f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static {
68f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        try {
69f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            serializable = Class.forName("java.io.Serializable");
70f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        } catch (ClassNotFoundException e) {
71f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            // TODO Auto-generated catch block
72f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            e.printStackTrace();
73f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
74f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
75f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
76aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public interface Handler
77aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
78aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects();
79f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
80aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b);
81aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
82f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
83aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static Handler getHandler(String className)
84aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
85aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return (Handler) map.get(className);
86aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
87f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
88aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class TimeZoneHandler implements Handler
89aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
90aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[] ZONES = { "GMT", "MET", "IST" };
91aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
92f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
93aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
94aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
95aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZone zones[] = new TimeZone[ZONES.length];
96f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
97aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for(int z = 0; z < ZONES.length; z += 1) {
98aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zones[z] = TimeZone.getTimeZone(ZONES[z]);
99aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
100f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return zones;
102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
103f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
104f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZone zone_a = (TimeZone) a;
108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZone zone_b = (TimeZone) b;
109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!(zone_a.getDisplayName().equals(zone_b.getDisplayName()))) {
111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return false;
112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int a_offsets[] = {0, 0};
115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int b_offsets[] = {0, 0};
116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean bSame = true;
118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < sampleTimes.length; i++) {
119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zone_a.getOffset(sampleTimes[i], false, a_offsets);
120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zone_b.getOffset(sampleTimes[i], false, b_offsets);
121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) {
122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = false;
123aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bSame;
127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
128aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
129f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static Locale locales[] = {
131f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.CANADA, Locale.CANADA_FRENCH, Locale.CHINA,
132f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.CHINESE, Locale.ENGLISH, Locale.FRANCE, Locale.FRENCH,
133f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.GERMAN, Locale.GERMANY, Locale.ITALIAN, Locale.ITALY,
134f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.JAPAN, Locale.JAPANESE, Locale.KOREA, Locale.KOREAN,
135f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.PRC, Locale.SIMPLIFIED_CHINESE, Locale.TAIWAN,
136aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Locale.TRADITIONAL_CHINESE, Locale.UK, Locale.US
137aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
138f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
139aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static Locale places[] = {
140f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.CANADA, Locale.CANADA_FRENCH, Locale.CHINA,
141f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.FRANCE, Locale.GERMANY, Locale.ITALY,
142f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.JAPAN, Locale.KOREA, Locale.PRC, Locale.TAIWAN,
143aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Locale.UK, Locale.US
144aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
145f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
146aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static Locale[] getLocales()
147aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
148aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return locales;
149aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
150f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
151aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static boolean compareStrings(String a[], String b[])
152aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (a.length != b.length) {
154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return false;
155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
156f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
157aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < a.length; i += 1) {
158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (! a[i].equals(b[i])) {
159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return false;
160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
161aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
162f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return true;
164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
165f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static boolean compareChars(char a[], char b[])
167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
168aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (a.length != b.length) {
169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return false;
170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
171f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < a.length; i += 1) {
173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (a[i] != b[i]) {
174aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return false;
175aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
177f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
178aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return true;
179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
181aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class SimpleTimeZoneHandler extends TimeZoneHandler
182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
183f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            SimpleTimeZone simpleTimeZones[] = new SimpleTimeZone[6];
187f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[0] = new SimpleTimeZone(32400000, "MyTimeZone");
189f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[1] = new SimpleTimeZone(32400000, "Asia/Tokyo");
191f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
192aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[2] = new SimpleTimeZone(32400000, "Asia/Tokyo");
193aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[2].setRawOffset(0);
194f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
195aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[3] = new SimpleTimeZone(32400000, "Asia/Tokyo");
196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[3].setStartYear(100);
197f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
198aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[4] = new SimpleTimeZone(32400000, "Asia/Tokyo");
199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[4].setStartYear(1000);
200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[4].setDSTSavings(1800000);
201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[4].setStartRule(3, 4, 180000);
202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[4].setEndRule(6, 3, 4, 360000);
203f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[5] = new SimpleTimeZone(32400000, "Asia/Tokyo");
205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[5].setStartRule(2, 3, 4, 360000);
206aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            simpleTimeZones[5].setEndRule(6, 3, 4, 360000);
207f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
208aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return simpleTimeZones;
209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
211aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
212aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class VTimeZoneHandler extends TimeZoneHandler {
213f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
214aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
215aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //TODO
216aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            VTimeZone[] vtzs = new VTimeZone[1];
217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            vtzs[0] = VTimeZone.create("America/New_York");
218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return vtzs;
219aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
220aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
221aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
222aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final int HOUR = 60*60*1000;
223aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final AnnualTimeZoneRule[] TEST_US_EASTERN = {
224aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EST", -5*HOUR, 0,
225aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME),
226aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1967, 2006),
227f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EST", -5*HOUR, 0,
229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME),
230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                2007, AnnualTimeZoneRule.MAX_YEAR),
231f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME),
234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1967, 1973),
235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.JANUARY, 6, 2*HOUR, DateTimeRule.WALL_TIME),
238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1974, 1974),
239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
240aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
241aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.FEBRUARY, 23, 2*HOUR, DateTimeRule.WALL_TIME),
242aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1975, 1975),
243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
245aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME),
246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1976, 1986),
247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME),
250aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                1987, 2006),
251aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
252aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR,
253aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME),
254aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                2007, AnnualTimeZoneRule.MAX_YEAR)
255aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
256aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
257aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class RuleBasedTimeZoneHandler extends TimeZoneHandler
258aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
259f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
260aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
261aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
262aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            RuleBasedTimeZone ruleBasedTimeZones[] = new RuleBasedTimeZone[2];
263aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
264aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            InitialTimeZoneRule ir = new InitialTimeZoneRule("GMT-5", -5*HOUR, 0);
265aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
266aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // GMT-5, no transition
267aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ruleBasedTimeZones[0] = new RuleBasedTimeZone("GMT-5", ir);
268aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
269aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
270aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // US Eastern since 1967
271aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ruleBasedTimeZones[1] = new RuleBasedTimeZone("US_East", ir);
272aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < TEST_US_EASTERN.length; i++) {
273aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ruleBasedTimeZones[1].addTransitionRule(TEST_US_EASTERN[i]);
274aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
275aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return ruleBasedTimeZones;
276aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
277aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
278aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
279aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class DateTimeRuleHandler implements Handler {
280f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
281aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
282aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            DateTimeRule[] rules = new DateTimeRule[4];
283aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
284aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // DOM + UTC
285aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[0] = new DateTimeRule(Calendar.OCTOBER, 10, 13*HOUR, DateTimeRule.UTC_TIME);
286aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
287aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // DOW + WALL
288aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[1] = new DateTimeRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME);
289aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
290aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // DOW_GEQ_DOM + STD
291aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[2] = new DateTimeRule(Calendar.MAY, 1, Calendar.MONDAY, true, 0*HOUR, DateTimeRule.STANDARD_TIME);
292aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
293aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // DOW_LEQ_DOM + WALL
294aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[3] = new DateTimeRule(Calendar.AUGUST, 31, Calendar.SATURDAY, false, 1*HOUR, DateTimeRule.WALL_TIME);
295aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
296aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return rules;
297aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
298aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
299f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
300aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
301aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return hasSameRule((DateTimeRule)a, (DateTimeRule)b);
302aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
303aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
304aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        static boolean hasSameRule(DateTimeRule dtra, DateTimeRule dtrb) {
305aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean bSame = false;
306aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (dtra.getDateRuleType() == dtrb.getDateRuleType()
307aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    && dtra.getRuleMonth() == dtrb.getRuleMonth()
308aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    && dtra.getTimeRuleType() == dtrb.getTimeRuleType()
309aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    && dtra.getRuleMillisInDay() == dtrb.getRuleMillisInDay()) {
310aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                switch (dtra.getDateRuleType()) {
311aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                case DateTimeRule.DOM:
312aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = (dtra.getRuleDayOfMonth() == dtrb.getRuleDayOfMonth());
313aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
314aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                case DateTimeRule.DOW:
315aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = (dtra.getRuleDayOfWeek() == dtrb.getRuleDayOfWeek() &&
316aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                dtra.getRuleWeekInMonth() == dtrb.getRuleWeekInMonth());
317aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
318aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                case DateTimeRule.DOW_GEQ_DOM:
319aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                case DateTimeRule.DOW_LEQ_DOM:
320aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = (dtra.getRuleDayOfMonth() == dtrb.getRuleDayOfMonth() &&
321aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                dtra.getRuleDayOfWeek() == dtrb.getRuleDayOfWeek());
322aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
323aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
324aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
325f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return bSame;
326aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
327aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
328aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
329aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static boolean compareTimeZoneRules(TimeZoneRule ra, TimeZoneRule rb) {
330aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (ra.getName().equals(rb.getName()) &&
331aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ra.getRawOffset() == rb.getRawOffset() &&
332aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ra.getDSTSavings() == rb.getDSTSavings()) {
333aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return true;
334aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
335f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return false;
336aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
337aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
338aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class AnnualTimeZoneRuleHandler implements Handler {
339f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
340aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
341aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return TEST_US_EASTERN;
342aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
343aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
344f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
345aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
346aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            AnnualTimeZoneRule ra = (AnnualTimeZoneRule)a;
347aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            AnnualTimeZoneRule rb = (AnnualTimeZoneRule)b;
348aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (DateTimeRuleHandler.hasSameRule(ra.getRule(), rb.getRule()) &&
349aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    ra.getStartYear() == rb.getStartYear() &&
350aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    ra.getEndYear() == rb.getEndYear()) {
351aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return compareTimeZoneRules(ra, rb);
352aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
353aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return false;
354aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
355aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
356aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
357aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class InitialTimeZoneRuleHandler implements Handler {
358f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
359aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
360aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZoneRule[] rules = new TimeZoneRule[2];
361aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[0] = new InitialTimeZoneRule("EST", -5*HOUR, 0);
362aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[1] = new InitialTimeZoneRule("PST", -8*HOUR, 0);
363aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return rules;
364aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
365aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
366f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
367aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
368aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return compareTimeZoneRules((TimeZoneRule)a, (TimeZoneRule)b);
369aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
370aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
371aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
372aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class TimeArrayTimeZoneRuleHandler implements Handler {
373f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
374aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
375aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeArrayTimeZoneRule[] rules = new TimeArrayTimeZoneRule[1];
376aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            long[] ttime = new long[] {-631152000000L, 0L, 946684800000L}; /* {1950-1-1, 1970-1-1, 2000-1-1} */
377aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            rules[0] = new TimeArrayTimeZoneRule("Foo", 1*HOUR, 1*HOUR, ttime, DateTimeRule.UTC_TIME);
378aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
379aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return rules;
380aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
381f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
382aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
383aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeArrayTimeZoneRule ra = (TimeArrayTimeZoneRule)a;
384aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeArrayTimeZoneRule rb = (TimeArrayTimeZoneRule)b;
385aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
386aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Date da = ra.getFirstStart(0, 0);
387aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Date db = rb.getFirstStart(0, 0);
388aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            long t = da.getTime();
389aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (da.equals(db)) {
390aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                da = ra.getFinalStart(0, 0);
391aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                db = rb.getFinalStart(0, 0);
392aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                long end = da.getTime();
393aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (da.equals(db)) {
394aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    while (t < end) {
395aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        da = ra.getNextStart(t, 0, 0, false);
396aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        db = ra.getNextStart(t, 0, 0, false);
397aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        if (da == null || db == null || !da.equals(db)) {
398aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            break;
399aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        }
400aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        t = da.getTime();
401aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
402aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    return compareTimeZoneRules(ra, rb);
403aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
404aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
405aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return false;
406aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
407aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
408aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
409aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class ULocaleHandler implements Handler
410aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
411f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
412aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
413aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
414aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ULocale uLocales[] = new ULocale[locales.length];
415f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
416aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < locales.length; i += 1) {
417aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                uLocales[i] = ULocale.forLocale(locales[i]);
418aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
419f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
420aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return uLocales;
421aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
422f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
423f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
424aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
425aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
426aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ULocale uloc_a = (ULocale) a;
427aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ULocale uloc_b = (ULocale) b;
428f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
429aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return uloc_a.getName().equals(uloc_b.getName());
430aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
431aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
432f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
433aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static class DateIntervalHandler implements Handler
434aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
435aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        private DateInterval dateInterval[] = {
436aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new DateInterval(0L, 1164931200000L/*20061201T000000Z*/)
437aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
438f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
439aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
440aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
441aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return dateInterval;
442aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
443aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
444f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
445aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
446aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
447aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return a.equals(b);
448aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
449aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
450aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
451aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class CurrencyHandler implements Handler
452aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
453f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
454aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
455aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
456aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Currency currencies[] = new Currency[places.length];
457f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
458aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < places.length; i += 1) {
459aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                currencies[i] = Currency.getInstance(places[i]);
460aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
461f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
462aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return currencies;
463aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
464f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
465f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
466aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
467aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
468f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
469aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Currency curr_a = (Currency) a;
470aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Currency curr_b = (Currency) b;
471f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
472f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return a == b
473f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    || a != null && b != null
474aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    && curr_a.getCurrencyCode() != null
475aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    && curr_a.getCurrencyCode().equals(curr_b.getCurrencyCode());
476f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
477aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
478aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
479aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
480aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static String zoneIDs[] = {
481aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Pacific/Honolulu", "America/Anchorage", "America/Los_Angeles", "America/Denver",
482aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "America/Chicago", "America/New_York", "Africa/Cairo", "Africa/Addis_Ababa", "Africa/Dar_es_Salaam",
483aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Africa/Freetown", "Africa/Johannesburg", "Africa/Nairobi", "Asia/Bangkok", "Asia/Baghdad",
484aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Asia/Calcutta", "Asia/Hong_Kong", "Asia/Jakarta", "Asia/Jerusalem", "Asia/Manila", "Asia/Tokyo",
485aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Europe/Amsterdam", "Europe/Athens", "Europe/Berlin", "Europe/London", "Europe/Malta", "Europe/Moscow",
486aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Europe/Paris", "Europe/Rome"
487aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
488f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
489aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static long sampleTimes[] = {
490aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1136073600000L, // 20060101T000000Z
491aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1138752000000L, // 20060201T000000Z
492aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1141171200000L, // 20060301T000000Z
493aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1143849600000L, // 20060401T000000Z
494aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1146441600000L, // 20060501T000000Z
495aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1149120000000L, // 20060601T000000Z
496aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1151712000000L, // 20060701T000000Z
497aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1154390400000L, // 20060801T000000Z
498aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1157068800000L, // 20060901T000000Z
499aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1159660800000L, // 20061001T000000Z
500aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1162339200000L, // 20061101T000000Z
501aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        1164931200000L, // 20061201T000000Z
502aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
503aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
504aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class OlsonTimeZoneHandler implements Handler
505aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
506f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
507aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
508aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
509aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            OlsonTimeZone timeZones[] = new OlsonTimeZone[zoneIDs.length];
510f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
511aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < zoneIDs.length; i += 1) {
512aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                timeZones[i] = new OlsonTimeZone(zoneIDs[i]);
513aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
514f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
515aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return timeZones;
516f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
517aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
518f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
519f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
520aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
521aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
522aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            OlsonTimeZone otz_a = (OlsonTimeZone) a;
523aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            OlsonTimeZone otz_b = (OlsonTimeZone) b;
524aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int a_offsets[] = {0, 0};
525aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int b_offsets[] = {0, 0};
526aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
527aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean bSame = true;
528aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < sampleTimes.length; i++) {
529aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                otz_a.getOffset(sampleTimes[i], false, a_offsets);
530aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                otz_b.getOffset(sampleTimes[i], false, b_offsets);
531aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) {
532aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = false;
533aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
534aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
535aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
536aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bSame;
537aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
538aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
539aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
540aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class TimeZoneAdapterHandler implements Handler
541aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
542f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
543aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
544aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
545aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZoneAdapter timeZones[] = new TimeZoneAdapter[zoneIDs.length];
546f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
547aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < zoneIDs.length; i += 1) {
548aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                timeZones[i] = new TimeZoneAdapter(TimeZone.getTimeZone(zoneIDs[i]));
549aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
550f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
551aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return timeZones;
552f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
553aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
554f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
555f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
556aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
557aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
558aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            GregorianCalendar cal = new GregorianCalendar();
559aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZoneAdapter tza_a = (TimeZoneAdapter) a;
560aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZoneAdapter tza_b = (TimeZoneAdapter) b;
561f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
562aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int a_offset, b_offset;
563aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean a_dst, b_dst;
564aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean bSame = true;
565aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < sampleTimes.length; i++) {
566aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                cal.setTimeInMillis(sampleTimes[i]);
567aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int era = cal.get(Calendar.ERA);
568aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int year = cal.get(Calendar.YEAR);
569aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int month = cal.get(Calendar.MONTH);
570aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int day = cal.get(Calendar.DAY_OF_MONTH);
571aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int dow = cal.get(Calendar.DAY_OF_WEEK);
572aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int mid = cal.get(Calendar.MILLISECONDS_IN_DAY);
573aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                a_offset = tza_a.getOffset(era, year, month, day, dow, mid);
574aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                b_offset = tza_b.getOffset(era, year, month, day, dow, mid);
575aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                Date d = new Date(sampleTimes[i]);
576aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                a_dst = tza_a.inDaylightTime(d);
577aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                b_dst = tza_b.inDaylightTime(d);
578aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (a_offset != b_offset || a_dst != b_dst) {
579aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = false;
580aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
581aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
582aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
583aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bSame;
584aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
585aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
586aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
587aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class JavaTimeZoneHandler implements Handler {
588aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[] ZONES = { "GMT", "America/New_York", "GMT+05:45" };
589aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
590f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
591aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
592aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            JavaTimeZone zones[] = new JavaTimeZone[ZONES.length];
593aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for(int z = 0; z < ZONES.length; z += 1) {
594aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                java.util.TimeZone tz = java.util.TimeZone.getTimeZone(ZONES[z]);
595aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zones[z] = new JavaTimeZone(tz, ZONES[z]);
596aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
597aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return zones;
598aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
599f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
600f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
601aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
602aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
603aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZone zone_a = (TimeZone) a;
604aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TimeZone zone_b = (TimeZone) b;
605aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
606aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!(TimeZone.getCanonicalID(zone_a.getID()).equals(TimeZone.getCanonicalID(zone_b.getID())))) {
607aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return false;
608aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
609aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
610aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int a_offsets[] = {0, 0};
611aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int b_offsets[] = {0, 0};
612aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
613aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean bSame = true;
614aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < sampleTimes.length; i++) {
615aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zone_a.getOffset(sampleTimes[i], false, a_offsets);
616aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                zone_b.getOffset(sampleTimes[i], false, b_offsets);
617aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) {
618aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bSame = false;
619aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
620aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
621aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
622aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bSame;
623aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
624aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
625aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
626aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class BigDecimalHandler implements Handler
627aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
628aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String values[] = {
629aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "1234567890.",
630aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "123456789.0",
631aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "12345678.90",
632aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "1234567.890",
633aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "123456.7890",
634aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "12345.67890",
635aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "1234.567890",
636aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "123.4567890",
637aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "12.34567890",
638aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "1.234567890",
639aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ".1234567890"};
640f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
641f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
642aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
643aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
644aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            BigDecimal bds[] = new BigDecimal[values.length];
645f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
646aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 0; i < values.length; i += 1) {
647aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                bds[i] = new BigDecimal(values[i]);
648aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
649f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
650aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bds;
651aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
652f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
653f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
654aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
655aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            BigDecimal bda = (BigDecimal) a;
656aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            BigDecimal bdb = (BigDecimal) b;
657f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
658aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return bda.toString().equals(bdb.toString());
659aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
660aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
661f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
662aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class MathContextHandler implements Handler
663aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
664aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int forms[] = {MathContext.PLAIN, MathContext.ENGINEERING, MathContext.SCIENTIFIC};
665aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int rounds[] = {
666aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext.ROUND_CEILING, MathContext.ROUND_DOWN, MathContext.ROUND_FLOOR,
667aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext.ROUND_HALF_DOWN, MathContext.ROUND_HALF_EVEN, MathContext.ROUND_HALF_UP,
668aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext.ROUND_UNNECESSARY, MathContext.ROUND_UP};
669aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
670f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
671aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects()
672aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
673aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int objectCount = forms.length * rounds.length;
674aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext contexts[] = new MathContext[objectCount];
675aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int i = 0;
676f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
677aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int f = 0; f < forms.length; f += 1) {
678aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int r = 0; r < rounds.length; r += 1) {
679aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    int digits = f * r;
680aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    boolean lostDigits = (r & 1) != 0;
681f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
682aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    contexts[i++] = new MathContext(digits, forms[f], lostDigits, rounds[r]);
683aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
684aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
685f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
686aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return contexts;
687aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
688f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
689f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
690aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b)
691aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
692aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext mca = (MathContext) a;
693aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            MathContext mcb = (MathContext) b;
694f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
695aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return mca.toString().equals(mcb.toString());
696aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
697aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
698aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
699aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static abstract class ExceptionHandlerBase implements Handler {
700f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
701aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public boolean hasSameBehavior(Object a, Object b) {
702aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return sameThrowable((Exception) a, (Exception) b);
703aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
704aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
705aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Exception.equals() does not seem to work.
706aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        private static final boolean sameThrowable(Throwable a, Throwable b) {
707f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return a == null ? b == null :
708aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    b == null ? false :
709aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            a.getClass().equals(b.getClass()) &&
710aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            Utility.objectEquals(a.getMessage(), b.getMessage()) &&
711aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            sameThrowable(a.getCause(), b.getCause());
712aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
713aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
714aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
715aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class ICUExceptionHandler extends ExceptionHandlerBase {
716f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
717aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
718aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return new ICUException[] {
719aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUException(),
720aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUException("msg1"),
721aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUException(new RuntimeException("rte1")),
722aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUException("msg2", new RuntimeException("rte2"))
723aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
724aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
725aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
726aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
727aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class ICUUncheckedIOExceptionHandler extends ExceptionHandlerBase {
728f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
729aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
730aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return new ICUUncheckedIOException[] {
731aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUUncheckedIOException(),
732aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUUncheckedIOException("msg1"),
733aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUUncheckedIOException(new RuntimeException("rte1")),
734aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUUncheckedIOException("msg2", new RuntimeException("rte2"))
735aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
736aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
737aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
738aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
739aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static class ICUCloneNotSupportedExceptionHandler extends ExceptionHandlerBase {
740f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
741aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        public Object[] getTestObjects() {
742aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return new ICUCloneNotSupportedException[] {
743aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUCloneNotSupportedException(),
744aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUCloneNotSupportedException("msg1"),
745aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUCloneNotSupportedException(new RuntimeException("rte1")),
746aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    new ICUCloneNotSupportedException("msg2", new RuntimeException("rte2"))
747aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
748aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
749aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
750aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
751aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static HashMap map = new HashMap();
752f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
753aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    static {
754aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.TimeZone", new TimeZoneHandler());
755aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.SimpleTimeZone", new SimpleTimeZoneHandler());
756aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.RuleBasedTimeZone", new RuleBasedTimeZoneHandler());
757aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.VTimeZone", new VTimeZoneHandler());
758aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.DateTimeRule", new DateTimeRuleHandler());
759aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.AnnualTimeZoneRule", new AnnualTimeZoneRuleHandler());
760aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.InitialTimeZoneRule", new InitialTimeZoneRuleHandler());
761aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.TimeArrayTimeZoneRule", new TimeArrayTimeZoneRuleHandler());
762aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.ULocale", new ULocaleHandler());
763aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.Currency", new CurrencyHandler());
764aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.impl.JavaTimeZone", new JavaTimeZoneHandler());
765aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.impl.OlsonTimeZone", new OlsonTimeZoneHandler());
766aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.impl.TimeZoneAdapter", new TimeZoneAdapterHandler());
767aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.math.BigDecimal", new BigDecimalHandler());
768aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.math.MathContext", new MathContextHandler());
769f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
770f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.NumberFormat", new FormatHandler.NumberFormatHandler());
771f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DecimalFormat", new FormatHandler.DecimalFormatHandler());
772f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.CompactDecimalFormat", new FormatHandler.CompactDecimalFormatHandler());
773f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.RuleBasedNumberFormat", new FormatHandler.RuleBasedNumberFormatHandler());
774f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.CurrencyPluralInfo", new FormatHandler.CurrencyPluralInfoHandler());
775f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DecimalFormatSymbols", new FormatHandler.DecimalFormatSymbolsHandler());
776f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.MessageFormat", new FormatHandler.MessageFormatHandler());
777f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateFormat", new FormatHandler.DateFormatHandler());
778f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateFormatSymbols", new FormatHandler.DateFormatSymbolsHandler());
779aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.DateInterval", new DateIntervalHandler());
780f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateIntervalFormat", new FormatHandler.DateIntervalFormatHandler());
781f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateIntervalInfo", new FormatHandler.DateIntervalInfoHandler());
782f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateIntervalInfo$PatternInfo", new FormatHandler.PatternInfoHandler());
783f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.SimpleDateFormat", new FormatHandler.SimpleDateFormatHandler());
784f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.ChineseDateFormat", new FormatHandler.ChineseDateFormatHandler());
785f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.ChineseDateFormatSymbols", new FormatHandler.ChineseDateFormatSymbolsHandler());
786f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.DateNumberFormat", new FormatHandler.DateNumberFormatHandler());
787f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.PluralFormat", new FormatHandler.PluralFormatHandler());
788f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.PluralRules", new FormatHandler.PluralRulesHandler());
789f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.PluralRulesSerialProxy", new FormatHandler.PluralRulesSerialProxyHandler());
790f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.TimeUnitFormat", new FormatHandler.TimeUnitFormatHandler());
791f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.SelectFormat", new FormatHandler.SelectFormatHandler());
792f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.TimeZoneNamesImpl", new FormatHandler.TimeZoneNamesHandler());
793f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.TimeZoneFormat", new FormatHandler.TimeZoneFormatHandler());
794f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.TimeZoneGenericNames", new FormatHandler.TimeZoneGenericNamesHandler());
795f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.TZDBTimeZoneNames", new FormatHandler.TZDBTimeZoneNamesHandler());
796f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
797f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.Calendar", new CalendarHandler.BasicCalendarHandler());
798f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.BuddhistCalendar", new CalendarHandler.BuddhistCalendarHandler());
799f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.ChineseCalendar", new CalendarHandler.ChineseCalendarHandler());
800f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.CopticCalendar", new CalendarHandler.CopticCalendarHandler());
801f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.DangiCalendar", new CalendarHandler.DangiCalendarHandler());
802f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.EthiopicCalendar", new CalendarHandler.EthiopicCalendarHandler());
803f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.GregorianCalendar", new CalendarHandler.GregorianCalendarHandler());
804f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.HebrewCalendar", new CalendarHandler.HebrewCalendarHandler());
805f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.IndianCalendar", new CalendarHandler.IndianCalendarHandler());
806f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.IslamicCalendar", new CalendarHandler.IslamicCalendarHandler());
807f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.JapaneseCalendar", new CalendarHandler.JapaneseCalendarHandler());
808f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.PersianCalendar", new CalendarHandler.PersianCalendarHandler());
809f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.TaiwanCalendar", new CalendarHandler.TaiwanCalendarHandler());
810f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
811f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.ArabicShapingException", new ExceptionHandler.ArabicShapingExceptionHandler());
812f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.StringPrepParseException", new ExceptionHandler.StringPrepParseExceptionHandler());
813f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.UResourceTypeMismatchException", new ExceptionHandler.UResourceTypeMismatchExceptionHandler());
814f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.InvalidFormatException", new ExceptionHandler.InvalidFormatExceptionHandler());
815f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
816f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.NumberFormat$Field", new FormatHandler.NumberFormatFieldHandler());
817f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.DateFormat$Field", new FormatHandler.DateFormatFieldHandler());
818f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.ChineseDateFormat$Field", new FormatHandler.ChineseDateFormatFieldHandler());
819f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.text.MessageFormat$Field", new FormatHandler.MessageFormatFieldHandler());
820f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
821f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.duration.BasicDurationFormat", new FormatHandler.BasicDurationFormatHandler());
822f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.RelativeDateFormat", new FormatHandler.RelativeDateFormatHandler());
823f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.util.IllformedLocaleException", new ExceptionHandler.IllformedLocaleExceptionHandler());
824f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.locale.LocaleSyntaxException", new ExceptionHandler.LocaleSyntaxExceptionHandler());
825f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        map.put("android.icu.impl.IllegalIcuArgumentException", new ExceptionHandler.IllegalIcuArgumentExceptionHandler());
826aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
827aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.text.PluralRules$FixedDecimal", new PluralRulesTest.FixedDecimalHandler());
828aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.MeasureUnit", new MeasureUnitTest.MeasureUnitHandler());
829aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.TimeUnit", new MeasureUnitTest.MeasureUnitHandler());
830aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.text.MeasureFormat", new MeasureUnitTest.MeasureFormatHandler());
831aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
832aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.ICUException", new ICUExceptionHandler());
833aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.ICUUncheckedIOException", new ICUUncheckedIOExceptionHandler());
834aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        map.put("android.icu.util.ICUCloneNotSupportedException", new ICUCloneNotSupportedExceptionHandler());
835aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
836f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
837f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /*
838f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Serialization Helpers
839f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
840f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static Object[] getSerializedObjects(byte[] serializedBytes) throws ClassNotFoundException, IOException {
841f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ByteArrayInputStream bis = new ByteArrayInputStream(serializedBytes);
842f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ObjectInputStream ois = new ObjectInputStream(bis);
843f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Object inputObjects[] = (Object[]) ois.readObject();
844f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
845f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ois.close();
846f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return inputObjects;
847aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
848aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
849f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static byte[] getSerializedBytes(Object[] objectsOut) throws IOException {
850f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ByteArrayOutputStream bos = new ByteArrayOutputStream();
851f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ObjectOutputStream oos = new ObjectOutputStream(bos);
852f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        oos.writeObject(objectsOut);
853aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
854f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        byte[] serializedBytes = bos.toByteArray();
855f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        oos.close();
856f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return serializedBytes;
857f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
858f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
859f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static Object[] getSerializedObjects(File testFile) throws IOException, ClassNotFoundException {
860f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        FileInputStream fis = new FileInputStream(testFile);
861f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ObjectInputStream ois = new ObjectInputStream(fis);
862f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Object[] objects = (Object[]) ois.readObject();
863f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        fis.close();
864f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return objects;
865f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
866f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
867f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static byte[] copyStreamBytes(InputStream is) throws IOException {
868f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        byte[] buffer = new byte[1024];
869f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
870f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ByteArrayOutputStream bos = new ByteArrayOutputStream();
871f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        int len;
872f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        while((len = is.read(buffer, 0, buffer.length)) >= 0) {
873f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            bos.write(buffer, 0, len);
874f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
875f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return bos.toByteArray();
876f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
877f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
878f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static List<String> getSerializationClassList(Object caller) throws IOException {
879f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        List<String> classList = new ArrayList();
880f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Enumeration<URL> urlEnum = caller.getClass().getClassLoader().getResources("android/icu");
881f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        while (urlEnum.hasMoreElements()) {
882f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            URL url = urlEnum.nextElement();
883f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            URLHandler handler  = URLHandler.get(url);
884f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (handler == null) {
885f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                System.out.println("Unsupported URL: " + url);
886f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                continue;
887f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
888f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            CoverageClassVisitor visitor = new CoverageClassVisitor(classList);
889f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            handler.guide(visitor, true, false);
890f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
891f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return classList;
892f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
893f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
894f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static class CoverageClassVisitor implements URLHandler.URLVisitor {
895f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private List<String> classNames;
896f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
897f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public CoverageClassVisitor(List<String> classNamesList) {
898f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            this.classNames = classNamesList;
899f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
900f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
901f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        /* (non-Javadoc)
902f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert         * @see android.icu.impl.URLHandler.URLVisitor#visit(java.lang.String)
903f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert         */
904f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
905f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public void visit(String classPath) {
906f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            int ix = classPath.lastIndexOf(".class");
907f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (ix < 0) {
908f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
909f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
910f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            String className = "android.icu" + classPath.substring(0, ix).replace('/', '.');
911f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
912f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            // Skip things in android.icu.dev; they're not relevant.
913f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (className.startsWith("android.icu.dev.")) {
914f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
915f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
916f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            Class c;
917f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            try {
918f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                c = Class.forName(className);
919f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            } catch (ClassNotFoundException e) {
920f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
921f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
922f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            int m = c.getModifiers();
923f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
924f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (className.equals("android.icu.text.PluralRules$FixedDecimal")) {
925f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                // Known Issue: "10268", "Serializable interface is not implemented in PluralRules$FixedDecimal"
926f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
927f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
928f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
929f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (c.isEnum() || !serializable.isAssignableFrom(c)) {
930f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                //System.out.println("@@@ Skipping: " + className);
931f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
932f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
933f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (!Modifier.isPublic(m) || Modifier.isInterface(m)) {
934f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                //System.out.println("@@@ Skipping: " + className);
935f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return;
936f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
937f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
938f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            this.classNames.add(className);
939f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
940f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
941f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
942f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static void serializeObjects(File oof, Object[] objectsOut) throws IOException {
943f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        FileOutputStream fos = new FileOutputStream(oof);
944f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ObjectOutputStream oos = new ObjectOutputStream(fos);
945f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        oos.writeObject(objectsOut);
946f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
947f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        oos.close();
948aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
949aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin}
950