View Javadoc

1   package fr.in2p3.jsaga.helpers;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   /* ***************************************************
7   * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
8   * ***             http://cc.in2p3.fr/             ***
9   * ***************************************************
10  * File:   ASCIITableFormatter
11  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
12  * Date:   3 ao�t 2007
13  * ***************************************************
14  * Description:                                      */
15  /**
16   * Format appended data as an ASCII table.
17   * Notes: the number of columns can vary, then missing columns are ignored and additional columns are displayed unformatted.
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              // update maxLength
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          // reduce column widths
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          // dump
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 }