1
2/*
3 *******************************************************************************
4 * Copyright (C) 2002-2012, International Business Machines Corporation and    *
5 * others. All Rights Reserved.                                                *
6 *******************************************************************************
7 */
8package com.ibm.icu.dev.util;
9
10import java.util.ArrayList;
11import java.util.List;
12
13public abstract class Tabber {
14    public static final byte LEFT = 0, CENTER = 1, RIGHT = 2;
15    private static final String[] ALIGNMENT_NAMES = {"Left", "Center", "Right"};
16
17    /**
18     * Repeats a string n times
19     * @param source
20     * @param times
21     */
22    // TODO - optimize repeats using doubling?
23    public static String repeat(String source, int times) {
24        if (times <= 0) return "";
25        if (times == 1) return source;
26        StringBuffer result = new StringBuffer();
27        for (; times > 0; --times) {
28            result.append(source);
29        }
30        return result.toString();
31    }
32
33    public String process(String source) {
34        StringBuffer result = new StringBuffer();
35        int lastPos = 0;
36        for (int count = 0; lastPos < source.length(); ++count) {
37            int pos = source.indexOf('\t', lastPos);
38            if (pos < 0) pos = source.length();
39            process_field(count, source, lastPos, pos, result);
40            lastPos = pos+1;
41        }
42        return prefix + result.toString() + postfix;
43    }
44
45    private String prefix = "";
46    private String postfix = "";
47
48    public abstract void process_field(int count, String source, int start, int limit, StringBuffer output);
49
50    public Tabber clear() {
51        return this;
52    }
53
54    public static class MonoTabber extends Tabber {
55        int minGap = 0;
56
57        private List stops = new ArrayList();
58        private List types = new ArrayList();
59
60        public Tabber clear() {
61            stops.clear();
62            types.clear();
63            minGap = 0;
64            return this;
65        }
66
67        public String toString() {
68            StringBuffer buffer = new StringBuffer();
69            for (int i = 0; i < stops.size(); ++i) {
70                if (i != 0) buffer.append("; ");
71                buffer
72                .append(ALIGNMENT_NAMES[((Integer)types.get(i)).intValue()])
73                .append(",")
74                .append(stops.get(i));
75            }
76            return buffer.toString();
77        }
78
79        /**
80         * Adds tab stop and how to align the text UP TO that stop
81         * @param tabPos
82         * @param type
83         */
84        public MonoTabber addAbsolute(int tabPos, int type) {
85            stops.add(new Integer(tabPos));
86            types.add(new Integer(type));
87            return this;
88        }
89
90        /**
91         * Adds relative tab stop and how to align the text UP TO that stop
92         */
93        public Tabber add(int fieldWidth, byte type) {
94            int last = getStop(stops.size()-1);
95            stops.add(new Integer(last + fieldWidth));
96            types.add(new Integer(type));
97            return this;
98        }
99
100        public int getStop(int fieldNumber) {
101            if (fieldNumber < 0) return 0;
102            if (fieldNumber >= stops.size()) fieldNumber = stops.size() - 1;
103            return ((Integer)stops.get(fieldNumber)).intValue();
104        }
105        public int getType(int fieldNumber) {
106            if (fieldNumber < 0) return LEFT;
107            if (fieldNumber >= stops.size()) return LEFT;
108            return ((Integer)types.get(fieldNumber)).intValue();
109        }
110        /*
111        public String process(String source) {
112            StringBuffer result = new StringBuffer();
113            int lastPos = 0;
114            int count = 0;
115            for (count = 0; lastPos < source.length() && count < stops.size(); count++) {
116                int pos = source.indexOf('\t', lastPos);
117                if (pos < 0) pos = source.length();
118                String piece = source.substring(lastPos, pos);
119                int stopPos = getStop(count);
120                if (result.length() < stopPos) {
121                    result.append(repeat(" ", stopPos - result.length()));
122                    // TODO fix type
123                }
124                result.append(piece);
125                lastPos = pos+1;
126            }
127            if (lastPos < source.length()) {
128                result.append(source.substring(lastPos));
129            }
130            return result.toString();
131        }
132        */
133
134        public void process_field(int count, String source, int start, int limit, StringBuffer output) {
135            String piece = source.substring(start, limit);
136            int startPos = getStop(count-1);
137            int endPos = getStop(count) - minGap;
138            int type = getType(count);
139            switch (type) {
140                case LEFT:
141                    break;
142                case RIGHT:
143                    startPos = endPos - piece.length();
144                    break;
145                case CENTER:
146                    startPos = (startPos + endPos - piece.length() + 1)/2;
147                    break;
148            }
149
150            int gap = startPos - output.length();
151            if (count != 0 && gap < minGap) gap = minGap;
152            if (gap > 0) output.append(repeat(" ", gap));
153            output.append(piece);
154        }
155
156    }
157
158    public static Tabber NULL_TABBER = new Tabber() {
159        public void process_field(int count, String source, int start, int limit, StringBuffer output) {
160            if (count > 0) output.append( "\t");
161            output.append(source.substring(start, limit));
162        }
163    };
164
165    public static class HTMLTabber extends Tabber {
166        private List<String> parameters = new ArrayList();
167        private String element = "td";
168        {
169            setPrefix("<tr>");
170            setPostfix("</tr>");
171        }
172        public HTMLTabber setParameters(int count, String params) {
173            // fill in
174            while (parameters.size() <= count) {
175                parameters.add(null);
176            }
177            parameters.set(count,params);
178            return this;
179        }
180
181        public String getElement() {
182            return element;
183        }
184
185        public HTMLTabber setElement(String element) {
186            this.element = element;
187            return this;
188        }
189
190        public void process_field(int count, String source, int start, int limit, StringBuffer output) {
191            output.append("<" + element);
192            String params = null;
193            if (count < parameters.size()) {
194                params = parameters.get(count);
195            }
196            if (params != null) {
197                output.append(' ');
198                output.append(params);
199            }
200            output.append(">");
201            output.append(source.substring(start, limit));
202            // TODO Quote string
203            output.append("</" + element + ">");
204        }
205    }
206    /**
207     */
208    public String getPostfix() {
209        return postfix;
210    }
211
212    /**
213     */
214    public String getPrefix() {
215        return prefix;
216    }
217
218    /**
219     * @param string
220     */
221    public Tabber setPostfix(String string) {
222        postfix = string;
223        return this;
224    }
225
226    /**
227     * @param string
228     */
229    public Tabber setPrefix(String string) {
230        prefix = string;
231        return this;
232    }
233
234    public Tabber add(int i, byte left2) {
235        // does nothing unless overridden
236        return this;
237    }
238
239}
240