1 package fr.in2p3.jsaga.helpers;
2
3 import java.io.*;
4 import java.util.*;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 public class ASCIITableFormatter {
20 private int SCREEN_WIDTH = 79;
21 private int[] m_maxWidth;
22 private String[] m_headers;
23 private List m_data;
24
25 public ASCIITableFormatter(String[] headers) {
26 m_maxWidth = new int[headers.length];
27 for (int i=0; i<headers.length; i++) {
28 m_maxWidth[i] = (headers[i]!=null ? headers[i].length() : 0);
29 }
30 m_headers = headers;
31 m_data = new ArrayList();
32 }
33
34 public ASCIITableFormatter(int maxColumns) {
35 m_maxWidth = new int[maxColumns];
36 for (int i=0; i<m_maxWidth.length; i++) {
37 m_maxWidth[i] = 0;
38 }
39 m_headers = null;
40 m_data = new ArrayList();
41 }
42
43 public void append(String[] row) throws Exception {
44 if (row != null) {
45 if (row.length > m_maxWidth.length) {
46 throw new Exception("Number of columns out of bounds: "+row.length);
47 }
48
49 for (int i=0; i<row.length; i++) {
50 if (row[i]!=null && m_maxWidth[i]<row[i].length()) {
51 m_maxWidth[i] = row[i].length();
52 }
53 }
54 m_data.add(row);
55 }
56 }
57
58 public void dump(OutputStream stream) throws IOException {
59
60 int[] indices = sortIndicesByMaxWidth();
61 int totalWidth;
62 for (int i=0; i<indices.length && (totalWidth=getTotalWidth())>SCREEN_WIDTH; i++) {
63 int currentMaxWidth = m_maxWidth[indices[i]];
64 int nextMaxWidth = i<indices.length-1 ? m_maxWidth[indices[i+1]] : 0;
65 int newWidth = currentMaxWidth - (totalWidth - SCREEN_WIDTH);
66 if (newWidth <= nextMaxWidth) {
67 newWidth = nextMaxWidth + 1;
68 }
69 m_maxWidth[indices[i]] = newWidth;
70 }
71
72
73 PrintStream out = new PrintStream(stream);
74 for (int i=0; m_headers!=null && i<m_headers.length; i++) {
75 if(i>0) out.print(" | ");
76 if (i < m_maxWidth.length) {
77 int space = m_maxWidth[i] - m_headers[i].length();
78 int indent = space / 2;
79 fill(' ', indent, out);
80 out.print(m_headers[i]);
81 fill(' ', space - indent, out);
82 } else {
83 out.print(m_headers[i]);
84 }
85 }
86 out.println();
87 for (int i=0; i<m_maxWidth.length; i++) {
88 if(i>0) out.print("-+-");
89 fill('-', m_maxWidth[i], out);
90 }
91 out.println();
92 for (Iterator it=m_data.iterator(); it.hasNext(); ) {
93 String[] row = (String[]) it.next();
94 int heightMax = getHeightMax(row);
95 for (int h=0; h<heightMax; h++) {
96 for (int i=0; row!=null && i<row.length; i++) {
97 if(i>0) out.print(" | ");
98 if (row[i] != null) {
99 int start = h*m_maxWidth[i];
100 int end = min((h+1)*m_maxWidth[i], row[i].length());
101 String lineOfRow = row[i]!=null && start<row[i].length()
102 ? row[i].substring(start, end)
103 : null;
104 if (lineOfRow != null) {
105 out.print(lineOfRow);
106 if (i < m_maxWidth.length) {
107 fill(' ', m_maxWidth[i]-lineOfRow.length(), out);
108 }
109 } else {
110 fill(' ', m_maxWidth[i], out);
111 }
112 } else {
113 fill(' ', m_maxWidth[i], out);
114 }
115 }
116 for (int i=row.length; i<m_maxWidth.length; i++) {
117 if(i>0) out.print(" | ");
118 fill(' ', m_maxWidth[i], out);
119 }
120 out.println();
121 }
122 }
123 }
124
125 private int[] sortIndicesByMaxWidth() {
126 int[] indices = new int[m_maxWidth.length];
127 for (int i=0; i<indices.length; i++) {
128 indices[i] = getIndiceWithMaxWidth(indices);
129 }
130 return indices;
131 }
132 private int getIndiceWithMaxWidth(int[] indices) {
133 int widthMax = -1;
134 int indiceMax = -1;
135 for (int i=0; i<m_maxWidth.length; i++) {
136 if (m_maxWidth[i]>widthMax && !contains(indices,i)) {
137 widthMax = m_maxWidth[i];
138 indiceMax = i;
139 }
140 }
141 return indiceMax;
142 }
143 private boolean contains(int[] array, int value) {
144 for (int i=0; i<array.length && array[i]!=0; i++) {
145 if (array[i] == value) {
146 return true;
147 }
148 }
149 return false;
150 }
151
152 private int getTotalWidth() {
153 int totalWidth = (m_maxWidth.length-1)*3;
154 for (int i=0; i<m_maxWidth.length; i++) {
155 totalWidth += m_maxWidth[i];
156 }
157 return totalWidth;
158 }
159
160 private int getHeightMax(String[] row) {
161 int heightMax = 1;
162 for (int i=0; row!=null && i<row.length; i++) {
163 if (row[i] != null) {
164 int height = (row[i].length() + m_maxWidth[i] - 1) / m_maxWidth[i];
165 if (height > heightMax) {
166 heightMax = height;
167 }
168 }
169 }
170 return heightMax;
171 }
172
173 private int min(int v1, int v2) {
174 return (v1<v2 ? v1 : v2);
175 }
176
177 private void fill(char c, int len, PrintStream out) throws IOException {
178 for (int i=0; i<len; i++) {
179 out.print(c);
180 }
181 }
182 }