1 18 package org.apache.beehive.netui.tags.databinding.cellrepeater; 19 20 import java.util.ArrayList ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Collections ; 24 import javax.servlet.jsp.JspException ; 25 import javax.servlet.jsp.tagext.TryCatchFinally ; 26 import javax.servlet.jsp.tagext.SimpleTagSupport ; 27 import javax.servlet.ServletRequest ; 28 29 import org.apache.beehive.netui.script.common.IDataAccessProvider; 30 import org.apache.beehive.netui.script.common.DataAccessProviderStack; 31 import org.apache.beehive.netui.tags.AbstractClassicTag; 32 import org.apache.beehive.netui.tags.ExpressionHandling; 33 import org.apache.beehive.netui.tags.rendering.TagRenderingBase; 34 import org.apache.beehive.netui.tags.rendering.TableTag; 35 import org.apache.beehive.netui.tags.rendering.TdTag; 36 import org.apache.beehive.netui.tags.rendering.TrTag; 37 import org.apache.beehive.netui.tags.rendering.AbstractRenderAppender; 38 import org.apache.beehive.netui.tags.rendering.StringBuilderRenderAppender; 39 import org.apache.beehive.netui.tags.rendering.ConstantRendering; 40 import org.apache.beehive.netui.util.Bundle; 41 import org.apache.beehive.netui.util.exception.LocalizedUnsupportedOperationException; 42 import org.apache.beehive.netui.util.internal.InternalStringBuilder; 43 import org.apache.beehive.netui.util.iterator.IteratorFactory; 44 import org.apache.beehive.netui.util.logging.Logger; 45 46 150 public class CellRepeater 151 extends AbstractClassicTag 152 implements IDataAccessProvider, TryCatchFinally { 153 154 private static final Logger LOGGER = Logger.getInstance(CellRepeater.class); 155 private static final int DIMENSION_DEFAULT_VALUE = -1; 156 private static final TableTag.State STATE_TABLE = new TableTag.State(); 157 private static final TrTag.State STATE_TR = new TrTag.State(); 158 private static final TdTag.State STATE_TD = new TdTag.State(); 159 160 private boolean _valid = true; 161 private boolean _verticalRepeat = false; 162 private boolean _containerInPageContext = false; 163 private int _columns = DIMENSION_DEFAULT_VALUE; 164 private int _rows = DIMENSION_DEFAULT_VALUE; 165 private int _currentIndex = -1; 166 private int _currentRow = -1; 167 private int _currentColumn = -1; 168 169 private ArrayList _dataList = null; 170 private Object _currentItem = null; 171 private String _dataSource = null; 172 private String _altCellClass = null; 173 private String _cellClass = null; 174 private ConstantRendering _htmlConstantRendering = null; 175 private TagRenderingBase _tableRenderer = null; 176 private TagRenderingBase _trRenderer = null; 177 private TagRenderingBase _tdRenderer = null; 178 private TableTag.State _tableState = null; 179 private TdTag.State _tdState = null; 180 private TrTag.State _trState = null; 181 private InternalStringBuilder _sb = null; 182 private AbstractRenderAppender _appender = null; 183 184 190 public String getTagName() { 191 return "CellRepeater"; 192 } 193 194 211 public void setTableClass(String tableClass) { 212 if("".equals(tableClass)) 213 return; 214 _tableState = new TableTag.State(); 215 _tableState.styleClass = tableClass; 216 } 217 218 237 public void setRowClass(String rowClass) { 238 if("".equals(rowClass)) 239 return; 240 _trState = new TrTag.State(); 241 _trState.styleClass = rowClass; 242 } 243 244 263 public void setCellClass(String cellClass) { 264 if("".equals(cellClass)) 265 return; 266 _cellClass = cellClass; 267 } 268 269 291 public void setAlternatingCellClass(String alternatingCellClass) { 292 if("".equals(alternatingCellClass)) 293 return; 294 _altCellClass = alternatingCellClass; 295 } 296 297 313 public void setVerticalRepeat(boolean verticalRepeat) { 314 _verticalRepeat = verticalRepeat; 315 } 316 317 332 public void setColumns(int columns) { 333 _columns = columns; 334 } 335 336 352 public void setRows(int rows) { 353 _rows = rows; 354 } 355 356 403 public void setDataSource(String dataSource) { 404 _dataSource = dataSource; 405 } 406 407 417 public int doStartTag() 418 throws JspException { 419 ServletRequest request = pageContext.getRequest(); 420 421 _tableRenderer = TagRenderingBase.Factory.getRendering(TagRenderingBase.TABLE_TAG, request); 422 _trRenderer = TagRenderingBase.Factory.getRendering(TagRenderingBase.TR_TAG, request); 423 _tdRenderer = TagRenderingBase.Factory.getRendering(TagRenderingBase.TD_TAG, request); 424 _htmlConstantRendering = TagRenderingBase.Factory.getConstantRendering(request); 425 426 _sb = new InternalStringBuilder(1024); 427 _appender = new StringBuilderRenderAppender(_sb); 428 429 Object source = evaluateDataSource(); 430 431 if(hasErrors()) 432 return SKIP_BODY; 433 434 if(source != null) { 435 Iterator iterator = IteratorFactory.createIterator(source); 436 if(iterator == null) { 437 LOGGER.info("CellRepeater: The data structure from which to create an iterator is null."); 438 iterator = Collections.EMPTY_LIST.iterator(); 439 } 440 441 if(iterator != null) { 442 _dataList = new ArrayList (); 443 while(iterator.hasNext()) { 444 _dataList.add(iterator.next()); 445 } 446 } 447 } 448 449 if(_rows == DIMENSION_DEFAULT_VALUE || _columns == DIMENSION_DEFAULT_VALUE) { 450 451 if(_dataList != null && _dataList.size() > 0) { 452 guessDimensions(_dataList); 453 454 if(hasErrors()) 455 return SKIP_BODY; 456 } 457 458 else { 459 _valid = false; 460 return SKIP_BODY; 461 } 462 } 463 464 465 if(_rows <= 0) { 466 String msg = Bundle.getString("Tags_CellRepeater_invalidRowValue", new Object []{getTagName(), new Integer (_rows)}); 467 registerTagError(msg, null); 468 } 469 470 if(_columns <= 0) { 471 String msg = Bundle.getString("Tags_CellRepeater_invalidColumnValue", new Object []{getTagName(), new Integer (_columns)}); 472 registerTagError(msg, null); 473 } 474 475 if(hasErrors()) 476 return SKIP_BODY; 477 478 openTableTag(_appender, _tableState); 479 480 _currentRow = 0; 481 _currentColumn = 0; 482 483 DataAccessProviderStack.addDataAccessProvider(this, pageContext); 484 _containerInPageContext = true; 485 486 boolean haveItem = ensureItem(0, _dataList); 487 if(haveItem) { 488 openRowTag(_appender, _trState); 489 openCellTag(_appender, _currentColumn); 490 return EVAL_BODY_BUFFERED; 491 } 492 else { 493 for(int i = 0; i < _rows; i++) { 495 openRowTag(_appender, _trState); 496 for(int j = 0; j < _columns; j++) { 497 openCellTag(_appender, computeStyleIndex(i, j)); 498 _htmlConstantRendering.NBSP(_appender); 499 closeCellTag(_appender); 500 } 501 closeRowTag(_appender); 502 _appender.append("\n"); 503 } 504 _currentRow = _rows; 505 _currentColumn = _columns; 506 return SKIP_BODY; 507 } 508 } 509 510 519 public int doAfterBody() { 520 if(bodyContent != null) { 521 _appender.append(bodyContent.getString()); 522 bodyContent.clearBody(); 523 } 524 525 530 boolean haveNext = false; 531 while(!haveNext) { 532 _currentColumn++; 533 534 535 closeCellTag(_appender); 536 537 538 if(_currentColumn == _columns) { 539 _currentRow++; 540 _currentColumn = 0; 541 closeRowTag(_appender); 542 _appender.append("\n"); 543 } 544 545 546 if(_currentRow == _rows) 547 return SKIP_BODY; 548 549 if(_currentColumn == 0) 550 openRowTag(_appender, _trState != null ? _trState : STATE_TR); 551 552 int itemIndex = -1; 553 if(_verticalRepeat) 554 itemIndex = _currentColumn * _rows + _currentRow; 555 else itemIndex = _currentRow * _columns + _currentColumn; 556 557 haveNext = ensureItem(itemIndex, _dataList); 558 559 openCellTag(_appender, computeStyleIndex(_currentRow, _currentColumn)) ; 560 561 562 if(!haveNext) 563 _htmlConstantRendering.NBSP(_appender); 564 565 else return EVAL_BODY_AGAIN; 566 } 567 568 569 return SKIP_BODY; 570 } 571 572 579 public int doEndTag() 580 throws JspException { 581 if(hasErrors()) 582 reportErrors(); 583 else if(_valid) { 584 closeTableTag(_appender); 585 write(_sb.toString()); 586 } 587 588 return EVAL_PAGE; 589 } 590 591 public void doFinally() { 592 localRelease(); 593 } 594 595 public void doCatch(Throwable t) 596 throws Throwable { 597 throw t; 598 } 599 600 604 public String getDataSource() { 605 return "{" + _dataSource + "}"; 606 } 607 608 618 public int getCurrentIndex() { 619 return _currentIndex; 620 } 621 622 632 public Object getCurrentItem() { 633 return _currentItem; 634 } 635 636 643 public Object getCurrentMetadata() { 644 LocalizedUnsupportedOperationException uoe = 645 new LocalizedUnsupportedOperationException("The " + getTagName() + "does not export metadata for its iterated items."); 646 uoe.setLocalizedMessage(Bundle.getErrorString("Tags_DataAccessProvider_metadataUnsupported", new Object []{getTagName()})); 647 throw uoe; 648 } 649 650 660 public IDataAccessProvider getProviderParent() { 661 return (IDataAccessProvider)SimpleTagSupport.findAncestorWithClass(this, IDataAccessProvider.class); 662 } 663 664 667 protected void localRelease() { 668 super.localRelease(); 669 670 if(bodyContent != null) 671 bodyContent.clearBody(); 672 673 _rows = DIMENSION_DEFAULT_VALUE; 674 _columns = DIMENSION_DEFAULT_VALUE; 675 _currentRow = -1; 676 _currentColumn = -1; 677 _currentIndex = -1; 678 _verticalRepeat = false; 679 _dataList = null; 680 _currentItem = null; 681 _valid = true; 682 _dataSource = null; 683 684 if(_tdState != null) 685 _tdState.clear(); 686 if(_trState != null) 687 _trState.clear(); 688 if(_tableState != null) 689 _tableState.clear(); 690 691 _tableRenderer = null; 692 _tdRenderer = null; 693 _trRenderer = null; 694 695 _sb = null; 696 _appender = null; 697 698 if(_containerInPageContext) { 699 DataAccessProviderStack.removeDataAccessProvider(pageContext); 700 _containerInPageContext = false; 701 } 702 } 703 704 private final void guessDimensions(ArrayList data) 705 throws JspException { 706 707 if(_rows == 0 || _columns == 0) 708 registerTagError(Bundle.getString("Tags_CellRepeater_missingRowsOrColumns"), null); 709 710 if(data == null) 711 return; 712 713 int dataSize = data.size(); 714 if(_rows == DIMENSION_DEFAULT_VALUE && _columns == DIMENSION_DEFAULT_VALUE) { 715 registerTagError(Bundle.getString("Tags_CellRepeater_invalidRowOrColumn"), null); 716 } 717 else if(_rows == DIMENSION_DEFAULT_VALUE) { 718 int remainder = dataSize % _columns; 719 _rows = (dataSize / _columns) + (remainder > 0 ? 1 : 0); 720 LOGGER.debug("guessed row size: " + _rows); 721 } 722 else if(_columns == DIMENSION_DEFAULT_VALUE) { 723 int remainder = dataSize % _rows; 724 _columns = (dataSize / _rows) + (remainder > 0 ? 1 : 0); 725 LOGGER.debug("guessed column size: " + _columns); 726 } 727 } 728 729 private final void openTableTag(AbstractRenderAppender appender, TableTag.State tableState) { 730 if(tableState == null) 731 tableState = STATE_TABLE; 732 _tableRenderer.doStartTag(appender, tableState); 733 } 734 735 private final void closeTableTag(AbstractRenderAppender appender) { 736 assert appender != null; 737 assert _tableRenderer != null; 738 _tableRenderer.doEndTag(appender); 739 } 740 741 private final void openRowTag(AbstractRenderAppender appender, TrTag.State trState) { 742 if(trState == null) 743 trState = STATE_TR; 744 _trRenderer.doStartTag(appender, trState); 745 } 746 747 private final void closeRowTag(AbstractRenderAppender appender) { 748 assert _trRenderer != null; 749 assert appender != null; 750 _trRenderer.doEndTag(appender); 751 } 752 753 private final void openCellTag(AbstractRenderAppender appender, int index) { 754 assert appender != null; 755 assert index >= 0; 756 assert _tdRenderer != null; 757 758 TdTag.State tdState = STATE_TD; 759 if(_cellClass != null) { 760 if(_tdState != null) 761 _tdState.clear(); 762 else _tdState = new TdTag.State(); 763 if(index % 2 == 0) 764 _tdState.styleClass = _cellClass; 765 else _tdState.styleClass = (_altCellClass != null ? _altCellClass : _cellClass); 766 tdState = _tdState; 767 } 768 769 _tdRenderer.doStartTag(appender, tdState); 770 } 771 772 private final void closeCellTag(AbstractRenderAppender appender) { 773 assert _tdRenderer != null; 774 assert appender != null; 775 _tdRenderer.doEndTag(appender); 776 } 777 778 private final int computeStyleIndex(int r, int c) { 779 return c + (r % 2); 780 } 781 782 private boolean ensureItem(int index, ArrayList data) { 783 LOGGER.debug("item: " + 0 + " data: " + (data == null ? "null data" : 784 (index < data.size() ? "" + index : "index out of bounds for size " + data.size()))); 785 786 if(data != null && index < data.size()) { 787 _currentItem = data.get(index); 788 _currentIndex = index; 789 return true; 790 } 791 else return false; 792 } 793 794 800 protected List getNamingChain() { 801 return AbstractClassicTag.DefaultNamingChain; 802 } 803 804 809 private Object evaluateDataSource() 810 throws JspException { 811 ExpressionHandling expr = new ExpressionHandling(this); 812 String dataSource = getDataSource(); 813 String ds = expr.ensureValidExpression(dataSource, "dataSource", "DataSourceError"); 814 if (ds == null) 815 return null; 816 817 Object o = expr.evaluateExpression(dataSource, "dataSource", pageContext); 818 return o; 819 } 820 } 821 | Popular Tags |