1 package org.apache.myfaces.component.html.ext; 2 3 import javax.faces.component.EditableValueHolder; 4 import javax.faces.component.UIComponent; 5 import javax.faces.component.UIData; 6 import javax.faces.context.FacesContext; 7 import javax.faces.el.ValueBinding; 8 import javax.faces.model.*; 9 import javax.servlet.jsp.jstl.sql.Result; 10 import java.io.Serializable ; 11 import java.sql.ResultSet ; 12 import java.util.ArrayList ; 13 import java.util.HashMap ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 17 24 abstract class HtmlDataTableHack 25 extends javax.faces.component.html.HtmlDataTable 26 { 27 protected DataModel _dataModel = null; 28 protected HashMap _dataModelMap = null; 29 30 transient protected boolean _saveDescendantStates = false; 32 33 34 37 private static final Class OBJECT_ARRAY_CLASS = (new Object [0]).getClass(); 38 39 private static final Integer INTEGER_MINUS1 = new Integer (-1); 40 41 private int _rowIndex = -1; 42 private Object [] _descendantStates; 43 private int _descendantEditableValueHolderCount = -1; 44 45 private Boolean _isEmbeddedUIData = null; 46 private UIData _embeddingUIData = null; 47 48 49 public boolean isRowAvailable() 50 { 51 return getDataModel().isRowAvailable(); 52 } 53 54 public int getRowCount() 55 { 56 return getDataModel().getRowCount(); 57 } 58 59 public Object getRowData() 60 { 61 return getDataModel().getRowData(); 62 } 63 64 public int getRowIndex() 65 { 66 return _rowIndex; 67 } 68 69 public void setRowIndex(int rowIndex) 70 { 71 saveDescendantComponentStates(); 72 73 _rowIndex = rowIndex; 74 75 DataModel dataModel = getDataModel(); 76 dataModel.setRowIndex(rowIndex); 77 78 String var = getVar(); 79 if (rowIndex == -1) 80 { 81 if (var != null) 82 { 83 getFacesContext().getExternalContext().getRequestMap().remove(var); 84 } 85 } 86 else 87 { 88 if (var != null) 89 { 90 if (isRowAvailable()) 91 { 92 Object rowData = dataModel.getRowData(); 93 getFacesContext().getExternalContext().getRequestMap().put(var, rowData); 94 } 95 else 96 { 97 getFacesContext().getExternalContext().getRequestMap().remove(var); 98 } 99 } 100 } 101 102 restoreDescendantComponentStates(); 103 } 104 105 106 private int getDescendantStatesRowIndex() 107 { 108 int rowIndex = getRowIndex(); 109 if (rowIndex == -1) 110 { 111 return 0; 112 } 113 else 114 { 115 return rowIndex - getFirst() + 1; 116 } 117 } 118 119 124 private void saveDescendantComponentStates() 125 { 126 if (_descendantEditableValueHolderCount == -1) 127 { 128 refreshDescendantDataStates(); 130 } 131 else if (_descendantEditableValueHolderCount == 0) 132 { 133 return; 135 } 136 else 137 { 138 int rowIndex = getDescendantStatesRowIndex(); 139 EditableValueHolderState[] rowState; 140 if(rowIndex < _descendantStates.length) { 144 rowState = (EditableValueHolderState[])_descendantStates[rowIndex]; 145 } else { 146 refreshDescendantDataStates(); 148 rowState = (EditableValueHolderState[])_descendantStates[rowIndex]; 149 } 150 if (rowState == null) 151 { 152 rowState = new EditableValueHolderState[_descendantEditableValueHolderCount]; 153 _descendantStates[rowIndex] = rowState; 154 } 155 saveDescendantComponentStates(this, rowState, 0, 0); 156 } 157 } 158 159 private void refreshDescendantDataStates() { 160 List list = new ArrayList (); 161 saveDescendantComponentStates(this, list,0); 162 _descendantEditableValueHolderCount = list.size(); 163 if (_descendantEditableValueHolderCount > 0) 164 { 165 EditableValueHolderState[] rowState 166 = (EditableValueHolderState[])list.toArray(new EditableValueHolderState[list.size()]); 167 int rows = getRows(); 168 if (rows <= 0) 169 { 170 rows = getRowCount() - getFirst(); 171 } 172 _descendantStates = new Object [rows + 1]; 173 int rowIndex = getDescendantStatesRowIndex(); 174 _descendantStates[rowIndex] = rowState; 175 } 176 } 177 178 private static void saveDescendantComponentStates(UIComponent component, List list, int level) 179 { 180 for (Iterator it=getChildrenAndOptionalFacetsIterator(level, component); it.hasNext();) 181 { 182 UIComponent child = (UIComponent)it.next(); 183 if (child instanceof EditableValueHolder) 184 { 185 list.add(new EditableValueHolderState((EditableValueHolder)child)); 186 } 187 saveDescendantComponentStates(child, list, level+1); 188 } 189 } 190 191 private static int saveDescendantComponentStates(UIComponent component, 192 EditableValueHolderState[] states, 193 int counter, int level) 194 { 195 for (Iterator it=getChildrenAndOptionalFacetsIterator(level, component); it.hasNext();) 196 { 197 UIComponent child = (UIComponent)it.next(); 198 if (child instanceof EditableValueHolder) 199 { 200 states[counter++] = new EditableValueHolderState((EditableValueHolder)child); 201 } 202 counter = saveDescendantComponentStates(child, states, counter, level+1); 203 } 204 return counter; 205 } 206 207 private void restoreDescendantComponentStates() 208 { 209 if (_descendantEditableValueHolderCount == -1) 210 { 211 throw new IllegalStateException ("saveDescendantComponentStates not called yet?"); 212 } 213 else if (_descendantEditableValueHolderCount > 0) 214 { 215 217 int zeroBasedRowIdx = getDescendantStatesRowIndex(); 219 220 int stateRowsCount = _descendantStates.length; 225 226 EditableValueHolderState[] initialStates = null; 227 if (stateRowsCount > 0) 228 { 229 initialStates = (EditableValueHolderState[]) _descendantStates[0]; 231 } 232 233 if (zeroBasedRowIdx < stateRowsCount) 234 { 235 EditableValueHolderState[] rowState = 237 (EditableValueHolderState[]) _descendantStates[zeroBasedRowIdx]; 238 restoreDescendantComponentStates(this, rowState, initialStates, 0,0); 239 } 240 else 241 { 242 restoreDescendantComponentStates(this, initialStates, initialStates, 0,0); 244 } 245 } 246 else 247 { 248 restoreDescendantComponentStates(this, null, null, 0,0); 251 } 252 } 253 254 private static int restoreDescendantComponentStates(UIComponent component, 255 EditableValueHolderState[] states, 256 EditableValueHolderState[] initialStates, 257 int counter, int level) 258 { 259 for (Iterator it=getChildrenAndOptionalFacetsIterator(level, component); it.hasNext();) 260 { 261 UIComponent child = (UIComponent)it.next(); 262 child.setId(child.getId()); if (child instanceof EditableValueHolder) 265 { 266 if (states != null) 267 { 268 states[counter].restore((EditableValueHolder)child); 269 } 270 else if (initialStates != null) 271 { 272 initialStates[counter].restore((EditableValueHolder)child); 273 } 274 else 275 { 276 ((EditableValueHolder)child).setValue(null); 280 ((EditableValueHolder)child).setLocalValueSet(false); 281 ((EditableValueHolder)child).setValid(true); 282 ((EditableValueHolder)child).setSubmittedValue(null); 283 } 284 counter++; 285 } 286 counter = restoreDescendantComponentStates(child, states, initialStates, counter,level+1); 287 } 288 return counter; 289 } 290 291 private static Iterator getChildrenAndOptionalFacetsIterator(int level, UIComponent component) 292 { 293 Iterator it; 294 295 if(level>1) 296 { 297 it = component.getFacetsAndChildren(); 298 } 299 else 300 { 301 it = component.getChildren().iterator(); 302 } 303 return it; 304 } 305 306 307 public void setValueBinding(String name, 308 ValueBinding binding) 309 { 310 if (name == null) 311 { 312 throw new NullPointerException ("name"); 313 } 314 else if (name.equals("value")) 315 { 316 _dataModel = null; 317 } 318 else if (name.equals("var") || name.equals("rowIndex")) 319 { 320 throw new IllegalArgumentException ("name " + name); 321 } 322 super.setValueBinding(name, binding); 323 } 324 325 326 private DataModel getDataModel() 327 { 328 UIData embeddingUIData = getEmbeddingUIData(); 329 if (embeddingUIData != null) 330 { 331 if (_dataModelMap == null) 337 { 338 _dataModelMap = new HashMap (); 339 } 340 String embeddingClientId = embeddingUIData.getClientId(FacesContext.getCurrentInstance()); 341 DataModel dataModel = (DataModel) _dataModelMap.get(embeddingClientId); 342 if (dataModel == null) 343 { 344 dataModel = createDataModel(); 345 _dataModelMap.put(embeddingClientId, dataModel); 346 } 347 return dataModel; 348 } 349 else 350 { 351 if (_dataModel == null) 354 { 355 _dataModel = createDataModel(); 356 } 357 return _dataModel; 358 } 359 } 360 361 364 private DataModel createDataModel() 365 { 366 Object value = getValue(); 367 if (value == null) 368 { 369 return EMPTY_DATA_MODEL; 370 } 371 else if (value instanceof DataModel) 372 { 373 return (DataModel)value; 374 } 375 else if (value instanceof List ) 376 { 377 return new ListDataModel((List )value); 378 } 379 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass())) 380 { 381 return new ArrayDataModel((Object [])value); 382 } 383 else if (value instanceof ResultSet ) 384 { 385 return new ResultSetDataModel((ResultSet )value); 386 } 387 else if (value instanceof Result) 388 { 389 return new ResultDataModel((Result)value); 390 } 391 else 392 { 393 return new ScalarDataModel(value); 394 } 395 } 396 397 401 private UIData getEmbeddingUIData() 402 { 403 if (_isEmbeddedUIData == null) 404 { 405 UIComponent findParentUIData = getParent(); 406 while (findParentUIData != null && 407 !(findParentUIData instanceof UIData)) 408 { 409 findParentUIData = findParentUIData.getParent(); 410 } 411 if (findParentUIData != null) 412 { 413 _embeddingUIData = (UIData)findParentUIData; 414 _isEmbeddedUIData = Boolean.TRUE; 415 } 416 else 417 { 418 _isEmbeddedUIData = Boolean.FALSE; 419 } 420 } 421 422 if (_isEmbeddedUIData.booleanValue()) 423 { 424 return _embeddingUIData; 425 } 426 else 427 { 428 return null; 429 } 430 } 431 432 433 private static final DataModel EMPTY_DATA_MODEL = new DataModel() 434 { 435 public boolean isRowAvailable() 436 { 437 return false; 438 } 439 440 public int getRowCount() 441 { 442 return 0; 443 } 444 445 public Object getRowData() 446 { 447 throw new IllegalArgumentException (); 448 } 449 450 public int getRowIndex() 451 { 452 return -1; 453 } 454 455 public void setRowIndex(int i) 456 { 457 if (i < -1) throw new IllegalArgumentException (); 458 } 459 460 public Object getWrappedData() 461 { 462 return null; 463 } 464 465 public void setWrappedData(Object obj) 466 { 467 if (obj == null) return; throw new UnsupportedOperationException (this.getClass().getName() + " UnsupportedOperationException"); 469 } 470 }; 471 472 473 private static class EditableValueHolderState 474 implements Serializable 475 { 476 private Object _localValue; 477 private boolean _localValueSet; 478 private boolean _valid; 479 private Object _submittedValue; 480 481 public EditableValueHolderState(EditableValueHolder vh) 482 { 483 _localValue = vh.getLocalValue(); 484 _localValueSet = vh.isLocalValueSet(); 485 _valid = vh.isValid(); 486 _submittedValue = vh.getSubmittedValue(); 487 } 488 489 public void restore(EditableValueHolder vh) 490 { 491 vh.setValue(_localValue); 492 vh.setLocalValueSet(_localValueSet); 493 vh.setValid(_valid); 494 vh.setSubmittedValue(_submittedValue); 495 } 496 } 497 498 499 public Object saveState(FacesContext context) 500 { 501 Object values[] = new Object [7]; 502 values[0] = super.saveState(context); 503 values[1] = _saveDescendantStates ? _descendantStates : null; 504 values[2] = _saveDescendantStates ? new Integer (_descendantEditableValueHolderCount) : INTEGER_MINUS1; 505 return values; 506 } 507 508 public void restoreState(FacesContext context, Object state) 509 { 510 Object values[] = (Object [])state; 511 super.restoreState(context, values[0]); 512 _descendantStates = (Object [])values[1]; 513 _descendantEditableValueHolderCount = ((Integer )values[2]).intValue(); 514 } 515 516 } 517 | Popular Tags |