1 5 package com.meterware.httpunit; 6 7 import java.net.URL ; 8 import java.util.ArrayList ; 9 import java.util.Enumeration ; 10 import java.util.Hashtable ; 11 12 import org.w3c.dom.Element ; 13 import org.w3c.dom.Node ; 14 15 import com.meterware.httpunit.scripting.ScriptableDelegate; 16 17 18 23 public class WebTable extends HTMLElementBase 24 { 25 26 27 public final static HTMLElementPredicate MATCH_FIRST_NONBLANK_CELL; 28 29 30 public final static HTMLElementPredicate MATCH_FIRST_NONBLANK_CELL_PREFIX; 31 32 33 public final static HTMLElementPredicate MATCH_SUMMARY; 34 35 36 public final static HTMLElementPredicate MATCH_ID; 37 38 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 57 public int getColumnCount() 58 { 59 if (getCells().length == 0) 60 return 0; 61 return getCells()[0].length; 62 } 63 64 68 public String getCellAsText(int row, int column) 69 { 70 TableCell cell = getTableCell(row, column); 71 return (cell == null) ? "" : cell.getText(); 72 } 73 74 78 public TableCell getTableCell(int row, int column) 79 { 80 return getCells()[row][column]; 81 } 82 83 87 public TableCell getTableCellWithID(String 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 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 spanningCells = new Hashtable (); 111 112 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 for (Enumeration 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 186 public String [][] asText() 187 { 188 String [][] result = new String [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 203 public String getSummary() 204 { 205 return NodeUtils.getNodeAttribute(_dom, "summary"); 206 } 207 208 public String toString() 209 { 210 String eol = System.getProperty("line.separator"); 211 StringBuffer sb = new StringBuffer (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 244 private Element _dom; 245 246 URL _url; 247 248 FrameSelector _frameName; 249 250 String _baseTarget; 251 252 String _characterSet; 253 254 WebResponse _response; 255 256 private TableCell[][] _cells; 257 258 WebTable( 259 WebResponse response, 260 FrameSelector frame, 261 Node domTreeRoot, 262 URL sourceURL, 263 String baseTarget, 264 String characterSet) 265 { 266 super(domTreeRoot); 267 _response = response; 268 _frameName = frame; 269 _dom = (Element ) 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 _rows = new ArrayList (); 325 326 void addRow(TableRow tableRow) 327 { 328 _cells = null; 329 _rows.add(tableRow); 330 } 331 332 TableRow newTableRow(Element 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 { 347 public boolean matchesCriteria(Object htmlElement, Object criteria) 348 { 349 WebTable table = ((WebTable) htmlElement); 350 table.purgeEmptyCells(); 351 return table.getRowCount() > 0 352 && HttpUnitUtils.matches(table.getCellAsText(0, 0).trim(), (String ) criteria); 353 }; 354 }; 355 356 MATCH_FIRST_NONBLANK_CELL_PREFIX = new HTMLElementPredicate() 357 { 359 public boolean matchesCriteria(Object htmlElement, Object 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 ) criteria); 365 }; 366 }; 367 368 MATCH_ID = new HTMLElementPredicate() 369 { 370 371 public boolean matchesCriteria(Object htmlElement, Object criteria) 372 { 373 return HttpUnitUtils.matches(((WebTable) htmlElement).getID(), (String ) criteria); 374 }; 375 }; 376 377 MATCH_SUMMARY = new HTMLElementPredicate() 378 { 379 380 public boolean matchesCriteria(Object htmlElement, Object criteria) 381 { 382 return HttpUnitUtils.matches(((WebTable) htmlElement).getSummary(), (String ) criteria); 383 }; 384 }; 385 386 } 387 388 } 389 | Popular Tags |