1 package com.sun.facelets.component; 2 3 import java.io.IOException ; 4 import java.io.Serializable ; 5 import java.sql.ResultSet ; 6 import java.util.Collections ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 12 import javax.faces.FacesException; 13 import javax.faces.application.FacesMessage; 14 import javax.faces.component.EditableValueHolder; 15 import javax.faces.component.NamingContainer; 16 import javax.faces.component.UIComponent; 17 import javax.faces.component.UIComponentBase; 18 import javax.faces.component.UIData; 19 import javax.faces.context.FacesContext; 20 import javax.faces.el.ValueBinding; 21 import javax.faces.event.AbortProcessingException; 22 import javax.faces.event.FacesEvent; 23 import javax.faces.event.FacesListener; 24 import javax.faces.event.PhaseId; 25 import javax.faces.model.ArrayDataModel; 26 import javax.faces.model.DataModel; 27 import javax.faces.model.ListDataModel; 28 import javax.faces.model.ResultSetDataModel; 29 import javax.faces.model.ScalarDataModel; 30 import javax.faces.render.Renderer; 31 32 import com.sun.facelets.tag.jsf.ComponentSupport; 33 import com.sun.facelets.util.FacesAPI; 34 35 public class UIRepeat extends UIComponentBase implements NamingContainer { 36 37 public static final String COMPONENT_TYPE = "facelets.ui.Repeat"; 38 39 public static final String COMPONENT_FAMILY = "facelets"; 40 41 private final static DataModel EMPTY_MODEL = new ListDataModel( 42 Collections.EMPTY_LIST); 43 44 private Object value; 46 47 private transient DataModel model; 48 49 private String var; 51 52 private String varStatus; 53 54 private int index = -1; 55 56 private int offset = -1; 58 59 private int size = -1; 60 61 public UIRepeat() { 62 this.setRendererType("facelets.ui.Repeat"); 63 } 64 65 public String getFamily() { 66 return COMPONENT_FAMILY; 67 } 68 69 public int getOffset() { 70 if (this.offset != -1) { 71 return this.offset; 72 } 73 ValueBinding vb = this.getValueBinding("offset"); 74 if (vb != null) { 75 return ((Integer ) vb.getValue(FacesContext.getCurrentInstance())) 76 .intValue(); 77 } 78 return 0; 79 } 80 81 public void setOffset(int offset) { 82 this.offset = offset; 83 } 84 85 public int getSize() { 86 if (this.size != -1) { 87 return this.size; 88 } 89 ValueBinding vb = this.getValueBinding("size"); 90 if (vb != null) { 91 return ((Integer ) vb.getValue(FacesContext.getCurrentInstance())) 92 .intValue(); 93 } 94 return -1; 95 } 96 97 public void setSize(int size) { 98 this.size = size; 99 } 100 101 public String getVar() { 102 return this.var; 103 } 104 105 public void setVar(String var) { 106 this.var = var; 107 } 108 109 private void resetDataModel() { 110 if (this.isNestedInIterator()) { 111 this.setDataModel(null); 112 } 113 } 114 115 private void setDataModel(DataModel model) { 116 this.model = model; 117 } 118 119 private DataModel getDataModel() { 120 if (this.model == null) { 121 Object val = this.getValue(); 122 if (val == null) { 123 this.model = EMPTY_MODEL; 124 } else if (val instanceof DataModel) { 125 this.model = (DataModel) val; 126 } else if (val instanceof List ) { 127 this.model = new ListDataModel((List ) val); 128 } else if (Object [].class.isAssignableFrom(val.getClass())) { 129 this.model = new ArrayDataModel((Object []) val); 130 } else if (val instanceof ResultSet ) { 131 this.model = new ResultSetDataModel((ResultSet ) val); 132 } else { 133 this.model = new ScalarDataModel(val); 134 } 135 } 136 return this.model; 137 } 138 139 public Object getValue() { 140 if (this.value == null) { 141 ValueBinding vb = this.getValueBinding("value"); 142 if (vb != null) { 143 return vb.getValue(FacesContext.getCurrentInstance()); 144 } 145 } 146 return this.value; 147 } 148 149 public void setValue(Object value) { 150 this.value = value; 151 } 152 153 private transient StringBuffer buffer; 154 155 private StringBuffer getBuffer() { 156 if (this.buffer == null) { 157 this.buffer = new StringBuffer (); 158 } 159 this.buffer.setLength(0); 160 return this.buffer; 161 } 162 163 public String getClientId(FacesContext faces) { 164 String id = super.getClientId(faces); 165 if (this.index >= 0) { 166 id = this.getBuffer().append(id).append( 167 NamingContainer.SEPARATOR_CHAR).append(this.index) 168 .toString(); 169 } 170 return id; 171 } 172 173 private transient Object origValue; 174 175 private void captureOrigValue() { 176 if (this.var != null) { 177 FacesContext faces = FacesContext.getCurrentInstance(); 178 Map attrs = faces.getExternalContext().getRequestMap(); 179 this.origValue = attrs.get(this.var); 180 } 181 } 182 183 private void restoreOrigValue() { 184 if (this.var != null) { 185 FacesContext faces = FacesContext.getCurrentInstance(); 186 Map attrs = faces.getExternalContext().getRequestMap(); 187 if (this.origValue != null) { 188 attrs.put(this.var, this.origValue); 189 } else { 190 attrs.remove(this.var); 191 } 192 } 193 } 194 195 private Map childState; 196 197 private Map getChildState() { 198 if (this.childState == null) { 199 this.childState = new HashMap (); 200 } 201 return this.childState; 202 } 203 204 private void saveChildState() { 205 if (this.getChildCount() > 0) { 206 207 FacesContext faces = FacesContext.getCurrentInstance(); 208 209 Iterator itr = this.getChildren().iterator(); 210 while (itr.hasNext()) { 211 this.saveChildState(faces, (UIComponent) itr.next()); 212 } 213 } 214 } 215 216 private void saveChildState(FacesContext faces, UIComponent c) { 217 218 if (c instanceof EditableValueHolder && !c.isTransient()) { 219 String clientId = c.getClientId(faces); 220 SavedState ss = (SavedState) this.getChildState().get(clientId); 221 if (ss == null) { 222 ss = new SavedState(); 223 this.getChildState().put(clientId, ss); 224 } 225 ss.populate((EditableValueHolder) c); 226 } 227 228 Iterator itr = c.getFacetsAndChildren(); 230 while (itr.hasNext()) { 231 saveChildState(faces, (UIComponent) itr.next()); 232 } 233 } 234 235 private void restoreChildState() { 236 if (this.getChildCount() > 0) { 237 238 FacesContext faces = FacesContext.getCurrentInstance(); 239 240 Iterator itr = this.getChildren().iterator(); 241 while (itr.hasNext()) { 242 this.restoreChildState(faces, (UIComponent) itr.next()); 243 } 244 } 245 } 246 247 private void restoreChildState(FacesContext faces, UIComponent c) { 248 String id = c.getId(); 250 c.setId(id); 251 252 if (c instanceof EditableValueHolder) { 254 EditableValueHolder evh = (EditableValueHolder) c; 255 String clientId = c.getClientId(faces); 256 SavedState ss = (SavedState) this.getChildState().get(clientId); 257 if (ss != null) { 258 ss.apply(evh); 259 } else { 260 NullState.apply(evh); 261 } 262 } 263 264 Iterator itr = c.getFacetsAndChildren(); 266 while (itr.hasNext()) { 267 restoreChildState(faces, (UIComponent) itr.next()); 268 } 269 } 270 271 private boolean keepSaved(FacesContext context) { 272 273 Iterator clientIds = this.getChildState().keySet().iterator(); 274 while (clientIds.hasNext()) { 275 String clientId = (String ) clientIds.next(); 276 Iterator messages = context.getMessages(clientId); 277 while (messages.hasNext()) { 278 FacesMessage message = (FacesMessage) messages.next(); 279 if (message.getSeverity() 280 .compareTo(FacesMessage.SEVERITY_ERROR) >= 0) { 281 return (true); 282 } 283 } 284 } 285 return (isNestedInIterator()); 286 } 287 288 private boolean isNestedInIterator() { 289 UIComponent parent = this.getParent(); 290 while (parent != null) { 291 if (parent instanceof UIData || parent instanceof UIRepeat) { 292 return true; 293 } 294 parent = parent.getParent(); 295 } 296 return false; 297 } 298 299 private void setIndex(int index) { 300 301 this.saveChildState(); 303 304 this.index = index; 305 DataModel localModel = getDataModel(); 306 localModel.setRowIndex(index); 307 308 if (this.index != -1 && this.var != null && localModel.isRowAvailable()) { 309 FacesContext faces = FacesContext.getCurrentInstance(); 310 Map attrs = faces.getExternalContext().getRequestMap(); 311 attrs.put(var, localModel.getRowData()); 312 } 313 314 this.restoreChildState(); 316 } 317 318 private boolean isIndexAvailable() { 319 return this.getDataModel().isRowAvailable(); 320 } 321 322 public void process(FacesContext faces, PhaseId phase) { 323 324 if (!this.isRendered()) 326 return; 327 328 this.resetDataModel(); 330 331 this.captureOrigValue(); 333 this.setIndex(-1); 334 335 try { 336 if (this.getChildCount() > 0) { 338 Iterator itr; 339 UIComponent c; 340 341 int i = this.getOffset(); 342 int end = this.getSize(); 343 end = (end >= 0) ? i + end : Integer.MAX_VALUE; 344 345 String rendererType = getRendererType(); 347 Renderer renderer = null; 348 if (rendererType != null) { 349 renderer = getRenderer(faces); 350 } 351 352 this.setIndex(i); 353 while (i <= end && this.isIndexAvailable()) { 354 355 if (PhaseId.RENDER_RESPONSE.equals(phase) 356 && renderer != null) { 357 renderer.encodeChildren(faces, this); 358 } else { 359 itr = this.getChildren().iterator(); 360 while (itr.hasNext()) { 361 c = (UIComponent) itr.next(); 362 if (PhaseId.APPLY_REQUEST_VALUES.equals(phase)) { 363 c.processDecodes(faces); 364 } else if (PhaseId.PROCESS_VALIDATIONS 365 .equals(phase)) { 366 c.processValidators(faces); 367 } else if (PhaseId.UPDATE_MODEL_VALUES 368 .equals(phase)) { 369 c.processUpdates(faces); 370 } else if (PhaseId.RENDER_RESPONSE.equals(phase)) { 371 if (FacesAPI.getVersion() >= 12) { 372 c.encodeAll(faces); 373 } else { 374 ComponentSupport.encodeRecursive(faces, c); 375 } 376 } 377 } 378 } 379 i++; 380 this.setIndex(i); 381 } 382 } 383 } catch (IOException e) { 384 throw new FacesException(e); 385 } finally { 386 this.setIndex(-1); 387 this.restoreOrigValue(); 388 } 389 } 390 391 429 public void processDecodes(FacesContext faces) { 430 if (!this.isRendered()) 431 return; 432 this.setDataModel(null); 433 if (!this.keepSaved(faces)) this.childState = null; 434 this.process(faces, PhaseId.APPLY_REQUEST_VALUES); 435 this.decode(faces); 436 } 437 438 public void processUpdates(FacesContext faces) { 439 if (!this.isRendered()) return; 440 this.resetDataModel(); 441 this.process(faces, PhaseId.UPDATE_MODEL_VALUES); 442 } 443 444 public void processValidators(FacesContext faces) { 445 if (!this.isRendered()) return; 446 this.resetDataModel(); 447 this.process(faces, PhaseId.PROCESS_VALIDATIONS); 448 } 449 450 private final static SavedState NullState = new SavedState(); 451 452 private final static class SavedState implements Serializable { 454 455 private Object submittedValue; 456 457 private static final long serialVersionUID = 2920252657338389849L; 458 459 Object getSubmittedValue() { 460 return (this.submittedValue); 461 } 462 463 void setSubmittedValue(Object submittedValue) { 464 this.submittedValue = submittedValue; 465 } 466 467 private boolean valid = true; 468 469 boolean isValid() { 470 return (this.valid); 471 } 472 473 void setValid(boolean valid) { 474 this.valid = valid; 475 } 476 477 private Object value; 478 479 Object getValue() { 480 return (this.value); 481 } 482 483 public void setValue(Object value) { 484 this.value = value; 485 } 486 487 private boolean localValueSet; 488 489 boolean isLocalValueSet() { 490 return (this.localValueSet); 491 } 492 493 public void setLocalValueSet(boolean localValueSet) { 494 this.localValueSet = localValueSet; 495 } 496 497 public String toString() { 498 return ("submittedValue: " + submittedValue + " value: " + value 499 + " localValueSet: " + localValueSet); 500 } 501 502 public void populate(EditableValueHolder evh) { 503 this.value = evh.getValue(); 504 this.valid = evh.isValid(); 505 this.submittedValue = evh.getSubmittedValue(); 506 this.localValueSet = evh.isLocalValueSet(); 507 } 508 509 public void apply(EditableValueHolder evh) { 510 evh.setValue(this.value); 511 evh.setValid(this.valid); 512 evh.setSubmittedValue(this.submittedValue); 513 evh.setLocalValueSet(this.localValueSet); 514 } 515 516 } 517 518 private final class IndexedEvent extends FacesEvent { 519 520 private final FacesEvent target; 521 522 private final int index; 523 524 public IndexedEvent(UIRepeat owner, FacesEvent target, int index) { 525 super(owner); 526 this.target = target; 527 this.index = index; 528 } 529 530 public PhaseId getPhaseId() { 531 return (this.target.getPhaseId()); 532 } 533 534 public void setPhaseId(PhaseId phaseId) { 535 this.target.setPhaseId(phaseId); 536 } 537 538 public boolean isAppropriateListener(FacesListener listener) { 539 return this.target.isAppropriateListener(listener); 540 } 541 542 public void processListener(FacesListener listener) { 543 UIRepeat owner = (UIRepeat) this.getComponent(); 544 int prevIndex = owner.index; 545 try { 546 owner.setIndex(this.index); 547 if (owner.isIndexAvailable()) { 548 this.target.processListener(listener); 549 } 550 } finally { 551 owner.setIndex(prevIndex); 552 } 553 } 554 555 public int getIndex() { 556 return index; 557 } 558 559 public FacesEvent getTarget() { 560 return target; 561 } 562 563 } 564 565 public void broadcast(FacesEvent event) throws AbortProcessingException { 566 if (event instanceof IndexedEvent) { 567 IndexedEvent idxEvent = (IndexedEvent) event; 568 this.resetDataModel(); 569 int prevIndex = this.index; 570 try { 571 this.setIndex(idxEvent.getIndex()); 572 if (this.isIndexAvailable()) { 573 FacesEvent target = idxEvent.getTarget(); 574 target.getComponent().broadcast(target); 575 } 576 } finally { 577 this.setIndex(prevIndex); 578 } 579 } else { 580 super.broadcast(event); 581 } 582 } 583 584 public void queueEvent(FacesEvent event) { 585 super.queueEvent(new IndexedEvent(this, event, this.index)); 586 } 587 588 public void restoreState(FacesContext faces, Object object) { 589 Object [] state = (Object []) object; 590 super.restoreState(faces, state[0]); 591 this.childState = (Map ) state[1]; 592 this.offset = ((Integer ) state[2]).intValue(); 593 this.size = ((Integer ) state[3]).intValue(); 594 this.var = (String ) state[4]; 595 this.value = state[5]; 596 } 597 598 public Object saveState(FacesContext faces) { 599 Object [] state = new Object [6]; 600 state[0] = super.saveState(faces); 601 state[1] = this.childState; 602 state[2] = new Integer (this.offset); 603 state[3] = new Integer (this.size); 604 state[4] = this.var; 605 state[5] = this.value; 606 return state; 607 } 608 609 public void encodeChildren(FacesContext faces) throws IOException { 610 if (!isRendered()) { 611 return; 612 } 613 this.setDataModel(null); 614 if (!this.keepSaved(faces)) { 615 this.childState = null; 616 } 617 this.process(faces, PhaseId.RENDER_RESPONSE); 618 } 619 620 public boolean getRendersChildren() { 621 Renderer renderer = null; 622 if (getRendererType() != null) { 623 if (null != (renderer = getRenderer(getFacesContext()))) { 624 return renderer.getRendersChildren(); 625 } 626 } 627 return true; 628 } 629 } 630 | Popular Tags |