1 | package net.sourceforge.retroweaver.runtime.java.util; |
2 | |
3 | import java.util.Locale; |
4 | import java.lang.reflect.Method; |
5 | import java.lang.reflect.InvocationTargetException; |
6 | import java.io.IOException; |
7 | |
8 | public class Formatter { |
9 | |
10 | public Formatter() { this(new StringBuilder(), Locale.getDefault()); } |
11 | |
12 | public Formatter(Appendable a) { this(a, Locale.getDefault()); } |
13 | |
14 | public Formatter(Locale l) { this(new StringBuilder(), l); } |
15 | |
16 | public Formatter(Appendable a, Locale l) { |
17 | buffer = a == null?new StringBuilder():a; |
18 | |
19 | try { |
20 | appendMethod = buffer.getClass().getMethod("append", new Class[] { String.class }); |
21 | } catch (NoSuchMethodException e) { |
22 | throw new RuntimeException(e); |
23 | } |
24 | locale = l; |
25 | } |
26 | |
27 | private Appendable buffer; |
28 | |
29 | private Method appendMethod; |
30 | |
31 | private Locale locale; |
32 | |
33 | private boolean closed; |
34 | |
35 | private IOException ioe; |
36 | |
37 | public Locale locale() { |
38 | if (closed) { |
39 | throw new FormatterClosedException(); |
40 | } |
41 | return locale; |
42 | } |
43 | |
44 | public Appendable out() { |
45 | if (closed) { |
46 | throw new FormatterClosedException(); |
47 | } |
48 | return buffer; |
49 | } |
50 | |
51 | public String toString() { |
52 | if (closed) { |
53 | throw new FormatterClosedException(); |
54 | } |
55 | return buffer.toString(); |
56 | } |
57 | |
58 | public void flush() { |
59 | if (closed) { |
60 | throw new FormatterClosedException(); |
61 | } |
62 | |
63 | // Flushable is 1.5+ |
64 | try { |
65 | Method m = buffer.getClass().getMethod("flush", new Class<?>[0]); |
66 | m.invoke(buffer, new Object[0]); |
67 | } catch (Exception e) { |
68 | // ignored; |
69 | } |
70 | } |
71 | |
72 | public void close() { |
73 | if (!closed) { |
74 | closed = true; |
75 | |
76 | // Closeable is 1.5+ |
77 | try { |
78 | Method m = buffer.getClass().getMethod("close", new Class<?>[0]); |
79 | m.invoke(buffer, new Object[0]); |
80 | } catch (Exception e) { |
81 | // ignored; |
82 | } |
83 | } |
84 | } |
85 | |
86 | public IOException ioException() { |
87 | return ioe; |
88 | } |
89 | |
90 | public Formatter format(String format, Object... args) throws IllegalFormatException, FormatterClosedException { |
91 | return format(locale, format, args); |
92 | } |
93 | |
94 | public Formatter format(Locale l, String format, Object... args) throws IllegalFormatException, FormatterClosedException { |
95 | if (closed) { |
96 | throw new FormatterClosedException(); |
97 | } |
98 | |
99 | //System.err.println("Format: " + format + ' ' + args.length); |
100 | //for (Object a: args) System.err.println("\t" + a.getClass() + ": " + a); |
101 | |
102 | int start = 0; |
103 | int end; |
104 | int argIndex = 0; |
105 | |
106 | while (true) { |
107 | try { |
108 | end = format.indexOf('%', start); |
109 | if (end == -1) { |
110 | append(format.substring(start, format.length())); |
111 | break; |
112 | } |
113 | append(format.substring(start, end)); |
114 | if (end == format.length()) { |
115 | throw new IllegalFormatException(); |
116 | } |
117 | char c = format.charAt(end+1); |
118 | switch (c) { |
119 | case '%': |
120 | append("%"); |
121 | break; |
122 | case 's': |
123 | Object o = args[argIndex++]; |
124 | append(o==null?null:o.toString()); |
125 | break; |
126 | case 'd': |
127 | o = args[argIndex++]; |
128 | append(o.toString()); |
129 | break; |
130 | default: |
131 | throw new IllegalFormatException(); |
132 | } |
133 | start = end + 2; |
134 | } catch (IOException ioe) { |
135 | this.ioe = ioe; |
136 | } |
137 | } |
138 | |
139 | return this; |
140 | } |
141 | |
142 | private void append(String s) throws IOException { |
143 | try { |
144 | appendMethod.invoke(buffer, s); |
145 | } catch (InvocationTargetException ite) { |
146 | if (ite.getCause() instanceof IOException) { |
147 | throw (IOException) ite.getCause(); |
148 | } |
149 | } catch (Exception e) { |
150 | throw new RuntimeException(e); |
151 | } |
152 | } |
153 | |
154 | } |
155 | |