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