KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > meterware > httpunit > WebTable


1 /*
2  * fgiust
3  * PATCHED to add support for table rows
4  */

5 package com.meterware.httpunit;
6
7 import java.net.URL JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Enumeration JavaDoc;
10 import java.util.Hashtable JavaDoc;
11
12 import org.w3c.dom.Element JavaDoc;
13 import org.w3c.dom.Node JavaDoc;
14
15 import com.meterware.httpunit.scripting.ScriptableDelegate;
16
17
18 /**
19  * This class represents a table in an HTML page.
20  * @author <a HREF="mailto:russgold@httpunit.org">Russell Gold</a>
21  * @author <a HREF="mailto:bx@bigfoot.com">Benoit Xhenseval</a>
22  */

23 public class WebTable extends HTMLElementBase
24 {
25
26     /** Predicate to match the complete text of a table's first non-blank cell. * */
27     public final static HTMLElementPredicate MATCH_FIRST_NONBLANK_CELL;
28
29     /** Predicate to match a prefix of a table's first non-blank cell. * */
30     public final static HTMLElementPredicate MATCH_FIRST_NONBLANK_CELL_PREFIX;
31
32     /** Predicate to match a table's summary attribute. * */
33     public final static HTMLElementPredicate MATCH_SUMMARY;
34
35     /** Predicate to match a table's ID. * */
36     public final static HTMLElementPredicate MATCH_ID;
37
38     /**
39      * Returns the number of rows in the table.
40      */

41     public int getRowCount()
42     {
43         return getCells().length;
44     }
45
46     private TableCell[][] getCells()
47     {
48         if (_cells == null)
49             readTable();
50         return _cells;
51
52     }
53
54     /**
55      * Returns the number of columns in the table.
56      */

57     public int getColumnCount()
58     {
59         if (getCells().length == 0)
60             return 0;
61         return getCells()[0].length;
62     }
63
64     /**
65      * Returns the contents of the specified table cell as text. The row and column numbers are zero-based.
66      * @throws IndexOutOfBoundsException if the specified cell numbers are not valid
67      */

68     public String JavaDoc getCellAsText(int row, int column)
69     {
70         TableCell cell = getTableCell(row, column);
71         return (cell == null) ? "" : cell.getText();
72     }
73
74     /**
75      * Returns the contents of the specified table cell as text. The row and column numbers are zero-based.
76      * @throws IndexOutOfBoundsException if the specified cell numbers are not valid
77      */

78     public TableCell getTableCell(int row, int column)
79     {
80         return getCells()[row][column];
81     }
82
83     /**
84      * Returns the contents of the specified table cell with a given ID
85      * @return TableCell with given ID or null if ID is not found.
86      */

87     public TableCell getTableCellWithID(String JavaDoc id)
88     {
89         for (int i = 0; i < getRowCount(); i++)
90         {
91             for (int j = 0; j < getColumnCount(); j++)
92             {
93                 final TableCell tableCell = getCells()[i][j];
94                 if (tableCell != null && tableCell.getID().equals(id))
95                     return tableCell;
96             }
97         }
98         return null;
99     }
100
101     /**
102      * Removes all rows and all columns from this table which have no visible text in them.
103      */

104     public void purgeEmptyCells()
105     {
106         int numRowsWithText = 0;
107         int numColumnsWithText = 0;
108         boolean rowHasText[] = new boolean[getRowCount()];
109         boolean columnHasText[] = new boolean[getColumnCount()];
110         Hashtable JavaDoc spanningCells = new Hashtable JavaDoc();
111
112         // look for rows and columns with any text in a non-spanning cell
113
for (int i = 0; i < rowHasText.length; i++)
114         {
115             for (int j = 0; j < columnHasText.length; j++)
116             {
117                 if (getCellAsText(i, j).trim().length() == 0)
118                     continue;
119                 if (getTableCell(i, j).getColSpan() == 1 && getTableCell(i, j).getRowSpan() == 1)
120                 {
121                     if (!rowHasText[i])
122                         numRowsWithText++;
123                     if (!columnHasText[j])
124                         numColumnsWithText++;
125                     rowHasText[i] = columnHasText[j] = true;
126                 }
127                 else if (!spanningCells.containsKey(getTableCell(i, j)))
128                 {
129                     spanningCells.put(getTableCell(i, j), new int[]{i, j});
130                 }
131             }
132         }
133
134         // look for requirements to keep spanning cells: special processing is needed if either:
135
// none of its rows already have text, or none of its columns already have text.
136
for (Enumeration JavaDoc e = spanningCells.keys(); e.hasMoreElements();)
137         {
138             TableCell cell = (TableCell) e.nextElement();
139             int coords[] = (int[]) spanningCells.get(cell);
140             boolean neededInRow = true;
141             boolean neededInCol = true;
142             for (int i = coords[0]; neededInRow && (i < rowHasText.length) && (i < coords[0] + cell.getRowSpan()); i++)
143             {
144                 neededInRow = !rowHasText[i];
145             }
146             for (int j = coords[1]; neededInCol && (j < columnHasText.length) && (j < coords[1] + cell.getColSpan()); j++)
147             {
148                 neededInCol = !columnHasText[j];
149             }
150             if (neededInRow)
151             {
152                 rowHasText[coords[0]] = true;
153                 numRowsWithText++;
154             }
155             if (neededInCol)
156             {
157                 columnHasText[coords[1]] = true;
158                 numColumnsWithText++;
159             }
160         }
161
162         TableCell[][] remainingCells = new TableCell[numRowsWithText][numColumnsWithText];
163
164         int targetRow = 0;
165         for (int i = 0; i < rowHasText.length; i++)
166         {
167             if (!rowHasText[i])
168                 continue;
169             int targetColumn = 0;
170             for (int j = 0; j < columnHasText.length; j++)
171             {
172                 if (!columnHasText[j])
173                     continue;
174                 remainingCells[targetRow][targetColumn++] = _cells[i][j];
175             }
176             targetRow++;
177         }
178
179         _cells = remainingCells;
180
181     }
182
183     /**
184      * Returns a rendering of this table with all cells converted to text.
185      */

186     public String JavaDoc[][] asText()
187     {
188         String JavaDoc[][] result = new String JavaDoc[getRowCount()][getColumnCount()];
189
190         for (int i = 0; i < result.length; i++)
191         {
192             for (int j = 0; j < result[0].length; j++)
193             {
194                 result[i][j] = getCellAsText(i, j);
195             }
196         }
197         return result;
198     }
199
200     /**
201      * Returns the summary attribute associated with this table.
202      */

203     public String JavaDoc getSummary()
204     {
205         return NodeUtils.getNodeAttribute(_dom, "summary");
206     }
207
208     public String JavaDoc toString()
209     {
210         String JavaDoc eol = System.getProperty("line.separator");
211         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(HttpUnitUtils.DEFAULT_TEXT_BUFFER_SIZE).append("WebTable:").append(eol);
212         for (int i = 0; i < getCells().length; i++)
213         {
214             sb.append("[").append(i).append("]: ");
215             for (int j = 0; j < getCells()[i].length; j++)
216             {
217                 sb.append(" [").append(j).append("]=");
218                 if (getCells()[i][j] == null)
219                 {
220                     sb.append("null");
221                 }
222                 else
223                 {
224                     sb.append(getCells()[i][j].getText());
225                 }
226             }
227             sb.append(eol);
228         }
229         return sb.toString();
230     }
231
232     protected ScriptableDelegate newScriptable()
233     {
234         return new HTMLElementScriptable(this);
235     }
236
237     protected ScriptableDelegate getParentDelegate()
238     {
239         return _response.getScriptableObject().getDocument();
240     }
241
242     // ----------------------------------- private members -----------------------------------
243

244     private Element JavaDoc _dom;
245
246     URL JavaDoc _url;
247
248     FrameSelector _frameName;
249
250     String JavaDoc _baseTarget;
251
252     String JavaDoc _characterSet;
253
254     WebResponse _response;
255
256     private TableCell[][] _cells;
257
258     WebTable(
259         WebResponse response,
260         FrameSelector frame,
261         Node JavaDoc domTreeRoot,
262         URL JavaDoc sourceURL,
263         String JavaDoc baseTarget,
264         String JavaDoc characterSet)
265     {
266         super(domTreeRoot);
267         _response = response;
268         _frameName = frame;
269         _dom = (Element JavaDoc) domTreeRoot;
270         _url = sourceURL;
271         _baseTarget = baseTarget;
272         _characterSet = characterSet;
273     }
274
275     private void readTable()
276     {
277         TableRow[] rows = getRows();
278         int[] columnsRequired = new int[rows.length];
279
280         for (int i = 0; i < rows.length; i++)
281         {
282             TableCell[] cells = rows[i].getCells();
283             for (int j = 0; j < cells.length; j++)
284             {
285                 int spannedRows = Math.min(columnsRequired.length - i, cells[j].getRowSpan());
286                 for (int k = 0; k < spannedRows; k++)
287                 {
288                     columnsRequired[i + k] += cells[j].getColSpan();
289                 }
290             }
291         }
292         int numColumns = 0;
293         for (int i = 0; i < columnsRequired.length; i++)
294         {
295             numColumns = Math.max(numColumns, columnsRequired[i]);
296         }
297
298         _cells = new TableCell[columnsRequired.length][numColumns];
299
300         for (int i = 0; i < rows.length; i++)
301         {
302             TableCell[] cells = rows[i].getCells();
303             for (int j = 0; j < cells.length; j++)
304             {
305                 int spannedRows = Math.min(columnsRequired.length - i, cells[j].getRowSpan());
306                 for (int k = 0; k < spannedRows; k++)
307                 {
308                     for (int l = 0; l < cells[j].getColSpan(); l++)
309                     {
310                         placeCell(i + k, j + l, cells[j]);
311                     }
312                 }
313             }
314         }
315     }
316
317     private void placeCell(int row, int column, TableCell cell)
318     {
319         while (_cells[row][column] != null)
320             column++;
321         _cells[row][column] = cell;
322     }
323
324     private ArrayList JavaDoc _rows = new ArrayList JavaDoc();
325
326     void addRow(TableRow tableRow)
327     {
328         _cells = null;
329         _rows.add(tableRow);
330     }
331
332     TableRow newTableRow(Element JavaDoc element)
333     {
334         return new TableRow(_response, _frameName, element, _url, _baseTarget, _characterSet);
335     }
336
337     public TableRow[] getRows()
338     {
339         return (TableRow[]) _rows.toArray(new TableRow[_rows.size()]);
340     }
341
342     static
343     {
344         MATCH_FIRST_NONBLANK_CELL = new HTMLElementPredicate()
345         { // XXX find a way to do this w/o purging the table cells
346

347             public boolean matchesCriteria(Object JavaDoc htmlElement, Object JavaDoc criteria)
348             {
349                 WebTable table = ((WebTable) htmlElement);
350                 table.purgeEmptyCells();
351                 return table.getRowCount() > 0
352                     && HttpUnitUtils.matches(table.getCellAsText(0, 0).trim(), (String JavaDoc) criteria);
353             };
354         };
355
356         MATCH_FIRST_NONBLANK_CELL_PREFIX = new HTMLElementPredicate()
357         { // XXX find a way to do this w/o purging the table cells
358

359             public boolean matchesCriteria(Object JavaDoc htmlElement, Object JavaDoc criteria)
360             {
361                 WebTable table = ((WebTable) htmlElement);
362                 table.purgeEmptyCells();
363                 return table.getRowCount() > 0
364                     && HttpUnitUtils.hasPrefix(table.getCellAsText(0, 0).toUpperCase().trim(), (String JavaDoc) criteria);
365             };
366         };
367
368         MATCH_ID = new HTMLElementPredicate()
369         {
370
371             public boolean matchesCriteria(Object JavaDoc htmlElement, Object JavaDoc criteria)
372             {
373                 return HttpUnitUtils.matches(((WebTable) htmlElement).getID(), (String JavaDoc) criteria);
374             };
375         };
376
377         MATCH_SUMMARY = new HTMLElementPredicate()
378         {
379
380             public boolean matchesCriteria(Object JavaDoc htmlElement, Object JavaDoc criteria)
381             {
382                 return HttpUnitUtils.matches(((WebTable) htmlElement).getSummary(), (String JavaDoc) criteria);
383             };
384         };
385
386     }
387
388 }
389
Popular Tags