1/*
2 *******************************************************************************
3 * Copyright (C) 2002-2012, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7package com.ibm.icu.dev.util;
8
9import java.util.Collection;
10import java.util.Iterator;
11import java.util.Map;
12
13import com.ibm.icu.text.UnicodeSet;
14import com.ibm.icu.text.UnicodeSetIterator;
15
16public abstract class Visitor {
17
18    public void doAt(Object item) {
19        if (item instanceof Collection) {
20            doAt((Collection) item);
21        } else if (item instanceof Map) {
22            doAt((Map) item);
23        } else if (item instanceof Object[]) {
24            doAt((Object[]) item);
25        } else if (item instanceof UnicodeSet) {
26            doAt((UnicodeSet) item);
27        } else {
28            doSimpleAt(item);
29        }
30    }
31
32    public int count(Object item) {
33        if (item instanceof Collection) {
34            return ((Collection) item).size();
35        } else if (item instanceof Map) {
36            return ((Map) item).size();
37        } else if (item instanceof Object[]) {
38            return ((Object[]) item).length;
39        } else if (item instanceof UnicodeSet) {
40            return ((UnicodeSet) item).size();
41        } else {
42            return 1;
43        }
44    }
45
46    // the default implementation boxing
47
48    public void doAt(int o) {
49        doSimpleAt(new Integer(o));
50    }
51    public void doAt(double o) {
52        doSimpleAt(new Double(o));
53    }
54    public void doAt(char o) {
55        doSimpleAt(new Character(o));
56    }
57
58    // for subclassing
59
60    protected void doAt (Collection c) {
61        if (c.size() == 0) doBefore(c, null);
62        Iterator it = c.iterator();
63        boolean first = true;
64        Object last = null;
65        while (it.hasNext()) {
66            Object item = it.next();
67            if (first) {
68                doBefore(c, item);
69                first = false;
70            } else {
71                doBetween(c, last, item);
72            }
73            doAt(last=item);
74        }
75        doAfter(c, last);
76    }
77
78    protected void doAt (Map c) {
79        doAt(c.entrySet());
80    }
81
82    protected void doAt (UnicodeSet c) {
83        if (c.size() == 0) doBefore(c, null);
84        UnicodeSetIterator it = new UnicodeSetIterator(c);
85        boolean first = true;
86        Object last = null;
87        Object item;
88        CodePointRange cpr0 = new CodePointRange();
89        CodePointRange cpr1 = new CodePointRange();
90        CodePointRange cpr;
91
92        while(it.nextRange()) {
93            if (it.codepoint == UnicodeSetIterator.IS_STRING) {
94                item = it.string;
95            } else {
96                cpr = last == cpr0 ? cpr1 : cpr0;   // make sure we don't override last
97                cpr.codepoint = it.codepoint;
98                cpr.codepointEnd = it.codepointEnd;
99                item = cpr;
100            }
101            if (!first) {
102                doBefore(c, item);
103                first = true;
104            } else {
105                doBetween(c, last, item);
106            }
107            doAt(last = item);
108        }
109        doAfter(c, last);
110    }
111
112    protected void doAt (Object[] c) {
113        doBefore(c, c.length == 0 ? null : c[0]);
114        Object last = null;
115        for (int i = 0; i < c.length; ++i) {
116            if (i != 0) doBetween(c, last, c[i]);
117            doAt(last = c[i]);
118        }
119        doAfter(c, last);
120    }
121
122    public static class CodePointRange{
123        public int codepoint, codepointEnd;
124    }
125
126    // ===== MUST BE OVERRIDEN =====
127
128    abstract protected void doBefore(Object container, Object item);
129    abstract protected void doBetween(Object container, Object lastItem, Object nextItem);
130    abstract protected void doAfter(Object container, Object item);
131    abstract protected void doSimpleAt(Object o);
132
133}