17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2002-2012, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.util;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collection;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSet;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSetIterator;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic abstract class Visitor {
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void doAt(Object item) {
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (item instanceof Collection) {
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt((Collection) item);
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof Map) {
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt((Map) item);
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof Object[]) {
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt((Object[]) item);
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof UnicodeSet) {
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt((UnicodeSet) item);
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doSimpleAt(item);
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int count(Object item) {
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (item instanceof Collection) {
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((Collection) item).size();
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof Map) {
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((Map) item).size();
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof Object[]) {
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((Object[]) item).length;
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (item instanceof UnicodeSet) {
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((UnicodeSet) item).size();
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 1;
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // the default implementation boxing
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void doAt(int o) {
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doSimpleAt(new Integer(o));
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void doAt(double o) {
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doSimpleAt(new Double(o));
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void doAt(char o) {
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doSimpleAt(new Character(o));
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // for subclassing
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void doAt (Collection c) {
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (c.size() == 0) doBefore(c, null);
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator it = c.iterator();
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean first = true;
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Object last = null;
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (it.hasNext()) {
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Object item = it.next();
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (first) {
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                doBefore(c, item);
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                first = false;
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                doBetween(c, last, item);
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt(last=item);
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doAfter(c, last);
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void doAt (Map c) {
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doAt(c.entrySet());
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void doAt (UnicodeSet c) {
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (c.size() == 0) doBefore(c, null);
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UnicodeSetIterator it = new UnicodeSetIterator(c);
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean first = true;
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Object last = null;
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Object item;
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CodePointRange cpr0 = new CodePointRange();
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CodePointRange cpr1 = new CodePointRange();
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CodePointRange cpr;
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while(it.nextRange()) {
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (it.codepoint == UnicodeSetIterator.IS_STRING) {
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                item = it.string;
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cpr = last == cpr0 ? cpr1 : cpr0;   // make sure we don't override last
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cpr.codepoint = it.codepoint;
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cpr.codepointEnd = it.codepointEnd;
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                item = cpr;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!first) {
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                doBefore(c, item);
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                first = true;
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                doBetween(c, last, item);
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt(last = item);
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doAfter(c, last);
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void doAt (Object[] c) {
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doBefore(c, c.length == 0 ? null : c[0]);
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Object last = null;
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < c.length; ++i) {
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (i != 0) doBetween(c, last, c[i]);
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            doAt(last = c[i]);
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        doAfter(c, last);
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static class CodePointRange{
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int codepoint, codepointEnd;
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ===== MUST BE OVERRIDEN =====
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract protected void doBefore(Object container, Object item);
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract protected void doBetween(Object container, Object lastItem, Object nextItem);
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract protected void doAfter(Object container, Object item);
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract protected void doSimpleAt(Object o);
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}