1 13 package com.tonbeller.jpivot.table; 14 15 import java.util.ArrayList ; 16 import java.util.Collections ; 17 import java.util.HashMap ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.NoSuchElementException ; 22 23 import javax.servlet.http.HttpSession ; 24 25 import org.apache.log4j.Logger; 26 import org.w3c.dom.CDATASection ; 27 import org.w3c.dom.Document ; 28 import org.w3c.dom.Element ; 29 import org.w3c.dom.Node ; 30 31 import com.tonbeller.jpivot.core.ModelChangeEvent; 32 import com.tonbeller.jpivot.core.ModelChangeListener; 33 import com.tonbeller.jpivot.olap.model.Axis; 34 import com.tonbeller.jpivot.olap.model.Cell; 35 import com.tonbeller.jpivot.olap.model.Member; 36 import com.tonbeller.jpivot.olap.model.OlapModel; 37 import com.tonbeller.jpivot.olap.model.Position; 38 import com.tonbeller.jpivot.olap.model.Result; 39 import com.tonbeller.jpivot.olap.navi.ClickableExtension; 40 import com.tonbeller.jpivot.table.span.PropertyConfig; 41 import com.tonbeller.tbutils.res.Resources; 42 import com.tonbeller.wcf.component.Component; 43 import com.tonbeller.wcf.component.ComponentSupport; 44 import com.tonbeller.wcf.controller.RequestContext; 45 import com.tonbeller.wcf.controller.RequestListener; 46 import com.tonbeller.wcf.utils.XmlUtils; 47 48 52 public class TableComponent extends ComponentSupport implements ModelChangeListener { 53 private static Logger logger = Logger.getLogger(TableComponent.class); 54 55 CellBuilder cellBuilder; 57 CornerBuilder cornerBuilder; 58 SlicerBuilder slicerBuilder; 59 RowAxisBuilder rowAxisBuilder; 60 ColumnAxisBuilder columnAxisBuilder; 61 62 Resources resources; 63 64 List extensionList = new ArrayList (); 66 Map extensionMap = new HashMap (); 67 68 OlapModel olapModel; 70 71 Document document; 72 73 74 Result result; 75 76 Iterator cellIterator; 77 78 int dimCount; 79 80 Element rootElement; 81 82 public TableComponent(String id, Component parent) { 83 super(id, parent); 84 } 85 86 public TableComponent(String id, Component parent, OlapModel newOlapModel) { 87 super(id, parent); 88 logger.info("TableComponent"); 89 this.olapModel = newOlapModel; 90 olapModel.addModelChangeListener(this); 91 } 92 93 97 public TableComponent() { 98 super(null, null); 99 } 100 101 public void setOlapModel(OlapModel newOlapModel) { 102 logger.info("setOlapModel"); 103 if (olapModel != null) 104 olapModel.removeModelChangeListener(this); 105 olapModel = newOlapModel; 106 olapModel.addModelChangeListener(this); 107 } 108 109 112 public void initialize(RequestContext context) throws Exception { 113 logger.info("initialize"); 114 super.initialize(context); 115 resources = context.getResources(TableComponent.class); 116 for (Iterator it = extensionList.iterator(); it.hasNext();) 117 ((TableComponentExtension) it.next()).initialize(context, this); 118 columnAxisBuilder.initialize(context, this); 119 rowAxisBuilder.initialize(context, this); 120 cellBuilder.initialize(context, this); 121 cornerBuilder.initialize(context, this); 122 slicerBuilder.initialize(context, this); 123 } 124 125 128 public void destroy(HttpSession session) throws Exception { 129 logger.info("destroy"); 130 slicerBuilder.destroy(session); 131 cornerBuilder.destroy(session); 132 cellBuilder.destroy(session); 133 rowAxisBuilder.destroy(session); 134 columnAxisBuilder.destroy(session); 135 for (Iterator it = extensionList.iterator(); it.hasNext();) 136 ((TableComponentExtension) it.next()).destroy(session); 137 super.destroy(session); 138 } 139 140 public Object getBookmarkState(int levelOfDetail) { 141 logger.info("getBookmarkState"); 142 Map map = (Map ) super.getBookmarkState(levelOfDetail); 143 map.put("slicerBuilder", slicerBuilder.getBookmarkState(levelOfDetail)); 144 map.put("cornerBuilder", cornerBuilder.getBookmarkState(levelOfDetail)); 145 map.put("cellBuilder", cellBuilder.getBookmarkState(levelOfDetail)); 146 map.put("rowAxisBuilder", rowAxisBuilder.getBookmarkState(levelOfDetail)); 147 map.put("columnAxisBuilder", columnAxisBuilder.getBookmarkState(levelOfDetail)); 148 for (Iterator it = extensionList.iterator(); it.hasNext();) { 149 TableComponentExtension tce = (TableComponentExtension) it.next(); 150 map.put(tce.getId(), tce.getBookmarkState(levelOfDetail)); 151 } 152 return map; 153 } 154 155 public void setBookmarkState(Object state) { 156 if (state == null) 157 return; 158 logger.info("setBookmarkState"); 159 super.setBookmarkState(state); 160 Map map = (Map ) state; 161 slicerBuilder.setBookmarkState(map.get("slicerBuilder")); 162 cornerBuilder.setBookmarkState(map.get("cornerBuilder")); 163 cellBuilder.setBookmarkState(map.get("cellBuilder")); 164 rowAxisBuilder.setBookmarkState(map.get("rowAxisBuilder")); 165 columnAxisBuilder.setBookmarkState(map.get("columnAxisBuilder")); 166 for (Iterator it = extensionList.iterator(); it.hasNext();) { 167 TableComponentExtension tce = (TableComponentExtension) it.next(); 168 tce.setBookmarkState(map.get(tce.getId())); 169 } 170 } 171 172 public Iterator clickableIterator() { 173 ClickableExtension ce = (ClickableExtension) olapModel.getExtension(ClickableExtension.ID); 174 if (ce == null) 175 return Collections.EMPTY_LIST.iterator(); 176 return ce.getClickables().iterator(); 177 } 178 179 public void request(RequestContext context) throws Exception { 180 super.request(context); 181 for (Iterator it = clickableIterator(); it.hasNext();) 182 ((RequestListener)it.next()).request(context); 183 } 184 185 188 private void startBuild(RequestContext context) { 189 logger.info("enter startBuild"); 190 columnAxisBuilder.startBuild(context); 191 rowAxisBuilder.startBuild(context); 192 cellBuilder.startBuild(context); 193 cornerBuilder.startBuild(context); 194 slicerBuilder.startBuild(context); 195 for (Iterator it = extensionList.iterator(); it.hasNext();) 196 ((TableComponentExtension) it.next()).startBuild(context); 197 for (Iterator it = clickableIterator(); it.hasNext();) 198 ((ClickableMember) it.next()).startRendering(context, this); 199 logger.info("leave startBuild"); 200 } 201 202 205 private void stopBuild() { 206 logger.info("enter stopBuild"); 207 for (Iterator it = extensionList.iterator(); it.hasNext();) 208 ((TableComponentExtension) it.next()).stopBuild(); 209 slicerBuilder.stopBuild(); 210 cornerBuilder.stopBuild(); 211 cellBuilder.stopBuild(); 212 rowAxisBuilder.stopBuild(); 213 columnAxisBuilder.stopBuild(); 214 for (Iterator it = clickableIterator(); it.hasNext();) 215 ((ClickableMember) it.next()).stopRendering(); 216 217 result = null; 219 cellIterator = null; 220 221 logger.info("leave stopBuild"); 222 223 } 224 225 228 public Document render(RequestContext context) throws Exception { 229 logger.info("render"); 230 if (document == null) { 231 logger.info("creating document"); 232 long t1 = System.currentTimeMillis(); 233 document = XmlUtils.createDocument(); 234 Element elem = render2(context); 235 document.appendChild(elem); 236 if (logger.isInfoEnabled()) { 237 long t2 = System.currentTimeMillis(); 238 logger.info("Rendering of Table took " + (t2 - t1) + " millisec"); 239 } 240 } 241 return document; 242 } 243 244 protected Result updateOlapModel() throws Exception { 245 return olapModel.getResult(); 246 } 247 248 private Element render2(RequestContext context) throws Exception { 249 logger.info("render2"); 250 this.result = updateOlapModel(); 251 this.cellIterator = result.getCells().iterator(); 252 this.dimCount = result.getAxes().length; 253 254 rootElement = document.createElement("mdxtable"); 255 Element head = append("head", rootElement); 256 Element body = append("body", rootElement); 257 258 startBuild(context); 259 260 switch (dimCount) { 261 case 0 : 262 logger.info("0-dim data"); 263 buildRows0Dim(body); 264 break; 265 case 1 : 266 logger.info("1-dim data"); 267 buildColumns1Dim(head); 268 buildRows1Dim(body); 269 break; 270 case 2 : 271 logger.info("2-dim data"); 272 buildColumns2Dim(head); 273 buildRows2Dim(body); 274 break; 275 default : 276 logger.error("more than 2 dimensions"); 277 throw new IllegalArgumentException ("TableRenderer requires 0, 1 or 2 dimensional result"); 278 } 279 280 rootElement.appendChild(buildSlicer()); 281 282 stopBuild(); 283 284 return rootElement; 285 } 286 287 private Element buildSlicer() { 288 logger.info("buildSlicer"); 289 Element slicer = elem("slicer"); 290 Iterator pi = getResult().getSlicer().getPositions().iterator(); 291 while (pi.hasNext()) { 292 Position p = (Position) pi.next(); 293 Member[] members = p.getMembers(); 294 for (int i = 0; i < members.length; i++) { 295 Element e = slicerBuilder.build(members[i]); 296 slicer.appendChild(e); 297 } 298 } 299 return slicer; 300 } 301 302 303 304 private void buildRows0Dim(Element parent) { 305 logger.info("buildRows0Dim"); 306 if (!cellIterator.hasNext()) 308 return; 309 310 Element row = append("row", parent); 311 Cell cell = (Cell) cellIterator.next(); 312 Element cellElem = cellBuilder.build(cell, true); 313 row.appendChild(cellElem); 314 } 315 316 317 318 private void buildRows1Dim(Element parent) { 319 logger.info("buildRows1Dim"); 320 Element row = append("row", parent); 321 buildCells(row, false); 322 } 323 324 private void buildColumns1Dim(Element parent) { 325 logger.info("buildColumns1Dim"); 326 final int N = columnAxisBuilder.getRowCount(); 327 for (int i = 0; i < N; i++) { 328 Element row = append("row", parent); 329 columnAxisBuilder.buildRow(row, i); 330 } 331 } 332 333 334 335 private void buildCornerElement(Element parent, int colSpan, int rowSpan) { 336 Element corner = cornerBuilder.build(colSpan, rowSpan); 337 parent.appendChild(corner); 338 } 339 340 369 370 private void buildColumns2Dim(Element parent) { 371 logger.info("enter buildColumns2Dim"); 372 int colAxisCount = columnAxisBuilder.getRowCount(); 373 int rowAxisCount = rowAxisBuilder.getHeaderRowCount(); 374 int colAxisIndex = 0; 375 int rowAxisIndex = 0; 376 377 if (logger.isInfoEnabled()) 378 logger.info("colAxisCount = " + colAxisCount + ", rowAxisCount = " + rowAxisCount); 379 380 if (rowAxisCount > colAxisCount) { 381 logger.info("rowAxisCount > colAxisCount"); 382 int N = rowAxisCount - colAxisCount; 384 Element row = append("row", parent); 385 rowAxisBuilder.buildHeaderRow(row, rowAxisIndex++); 386 buildCornerElement(row, columnAxisBuilder.getColumnCount(), N); 387 for (int i = 1; i < N; i++) { 388 row = append("row", parent); 389 rowAxisBuilder.buildHeaderRow(row, rowAxisIndex++); 390 } 391 rowAxisCount -= N; 393 } else if (colAxisCount > rowAxisCount) { 394 logger.info("colAxisCount > rowAxisCount"); 395 int N = colAxisCount - rowAxisCount; 397 Element row = append("row", parent); 398 buildCornerElement(row, rowAxisBuilder.getColumnCount(), N); 399 columnAxisBuilder.buildRow(row, colAxisIndex++); 400 for (int i = 1; i < N; i++) { 401 row = append("row", parent); 402 columnAxisBuilder.buildRow(row, colAxisIndex++); 403 } 404 colAxisCount -= N; 406 } 407 408 logger.info("building cells"); 409 for (int i = 0; i < colAxisCount; i++) { 412 Element row = append("row", parent); 413 rowAxisBuilder.buildHeaderRow(row, rowAxisIndex++); 414 columnAxisBuilder.buildRow(row, colAxisIndex++); 415 } 416 logger.info("leave buildColumns2Dim"); 417 } 418 419 private void buildRows2Dim(Element parent) { 420 logger.info("enter buildRows2Dim"); 421 final int N = rowAxisBuilder.getRowCount(); 422 for (int i = 0; i < N; i++) { 423 boolean even = (i % 2 == 0); 424 Element row = append("row", parent); 425 rowAxisBuilder.buildRow(row, i); 426 buildCells(row, even); 427 } 428 logger.info("leave buildRows2Dim"); 429 } 430 431 432 433 private void buildCells(Element row, boolean even) { 434 final int N = columnAxisBuilder.getColumnCount(); 435 for (int i = 0; i < N; i++) { 436 try { 437 Cell cell = (Cell) cellIterator.next(); 438 Element cellElem = cellBuilder.build(cell, even); 439 row.appendChild(cellElem); 440 } catch (NoSuchElementException e) { 441 logger.error("not enough cells", e); 442 e.printStackTrace(); 443 } 444 445 } 446 } 447 448 449 450 453 public Element elem(String name) { 454 return document.createElement(name); 455 } 456 457 460 public Element append(String name, Element parent) { 461 Element elem = document.createElement(name); 462 parent.appendChild(elem); 463 return elem; 464 } 465 466 private void firstChild(Element child, Element parent) { 467 Node before = parent.getFirstChild(); 468 if (before != null) 469 parent.insertBefore(child, before); 470 else 471 parent.appendChild(child); 472 } 473 474 477 public Element insert(String name, Element parent) { 478 Element elem = document.createElement(name); 479 firstChild(elem, parent); 480 return elem; 481 } 482 483 486 public Object cdata(String content, Element parent) { 487 CDATASection section = document.createCDATASection(content); 488 parent.appendChild(section); 489 return section; 490 } 491 492 493 494 public OlapModel getOlapModel() { 495 return olapModel; 496 } 497 498 502 public void addExtension(TableComponentExtension extension) { 503 extensionList.add(extension); 504 extensionMap.put(extension.getId(), extension); 505 } 506 507 510 public Map getExtensions() { 511 return extensionMap; 512 } 513 514 517 public boolean isDirty() { 518 return document == null; 519 } 520 521 public void setDirty(boolean dirty) { 522 document = null; 523 result = null; 525 cellIterator = null; 526 rootElement = null; 527 } 528 529 public void modelChanged(ModelChangeEvent e) { 530 setDirty(true); 531 } 532 533 public void structureChanged(ModelChangeEvent e) { 534 setDirty(true); 535 } 536 537 541 public CellBuilder getCellBuilder() { 542 return cellBuilder; 543 } 544 545 549 public ColumnAxisBuilder getColumnAxisBuilder() { 550 return columnAxisBuilder; 551 } 552 553 557 public CornerBuilder getCornerBuilder() { 558 return cornerBuilder; 559 } 560 561 565 public RowAxisBuilder getRowAxisBuilder() { 566 return rowAxisBuilder; 567 } 568 569 573 public SlicerBuilder getSlicerBuilder() { 574 return slicerBuilder; 575 } 576 577 581 public void setCellBuilder(CellBuilder cellBuilder) { 582 this.cellBuilder = cellBuilder; 583 } 584 585 589 public void setColumnAxisBuilder(ColumnAxisBuilder columnAxisBuilder) { 590 this.columnAxisBuilder = columnAxisBuilder; 591 } 592 593 597 public void setCornerBuilder(CornerBuilder cornerBuilder) { 598 this.cornerBuilder = cornerBuilder; 599 } 600 601 605 public void setRowAxisBuilder(RowAxisBuilder rowAxisBuilder) { 606 this.rowAxisBuilder = rowAxisBuilder; 607 } 608 609 613 public void setSlicerBuilder(SlicerBuilder slicerBuilder) { 614 this.slicerBuilder = slicerBuilder; 615 } 616 617 620 public Result getResult() { 621 return result; 622 } 623 624 627 public int getDimCount() { 628 return dimCount; 629 } 630 631 634 public Element getRootElement() { 635 return rootElement; 636 } 637 638 641 public Axis getRowAxis() { 642 if (dimCount < 2) 643 return null; 644 return result.getAxes()[1]; 645 } 646 647 650 public Axis getColumnAxis() { 651 if (dimCount < 1) 652 return null; 653 return result.getAxes()[0]; 654 } 655 656 660 public PropertyConfig getPropertyConfig() { 661 return rowAxisBuilder.getAxisConfig().getPropertyConfig(); 662 } 663 664 } 665 | Popular Tags |