1 package jimm.datavision; 2 import jimm.datavision.field.*; 3 import jimm.datavision.source.*; 4 import jimm.datavision.source.sql.*; 5 import jimm.datavision.source.charsep.CharSepSource; 6 import jimm.datavision.source.ncsql.NCDatabase; 7 import jimm.util.I18N; 8 import java.io.*; 9 import java.util.*; 10 import java.awt.Color ; 11 12 import javax.xml.parsers.SAXParserFactory ; 13 14 import org.xml.sax.*; 15 import org.xml.sax.helpers.DefaultHandler ; 16 17 22 public class ReportReader extends DefaultHandler { 23 24 38 static class FormulaConversion { 39 Formula formula; 40 String expression; 41 FormulaConversion(Formula f, String expr) { 42 formula = f; 43 expression = expr; 44 } 45 } 46 48 53 protected static final double DEFAULT_DTD_VERSION = 0.2; 54 55 59 protected static final double DTD_VERSION_FORMULA_IDS = 0.2; 60 61 protected Stack tagNameStack; 62 protected Report report; 63 protected Subreport subreport; 64 protected Parameter parameter; 65 protected Formula formula; 66 protected UserColumn usercol; 67 protected Section section; 68 protected Group group; 69 protected Field field; 70 protected String textData; 71 protected Border border; 72 protected Line line; 73 protected double dtdVersion; 74 protected HashMap formulasToConvert; 75 protected int nextSectionLocation; 76 protected boolean missingColumnSeen; 77 protected boolean inSubreportJoins; 78 79 84 public ReportReader(Report report) { 85 this.report = report; 86 tagNameStack = new Stack(); 87 dtdVersion = DEFAULT_DTD_VERSION; 88 } 89 90 97 public void read(InputSource in) throws Exception { 98 removeReportSections(); 99 SAXParserFactory.newInstance().newSAXParser().parse(in, this); 100 postParse(); 101 } 102 103 108 public void read(File f) throws Exception { 109 removeReportSections(); 110 SAXParserFactory.newInstance().newSAXParser().parse(f, this); 111 postParse(); 112 } 113 114 117 protected void removeReportSections() { 118 getReport().headers().clear(); 119 getReport().pageHeaders().clear(); 120 getReport().pageFooters().clear(); 121 getReport().footers().clear(); 122 getReport().details().clear(); 123 } 124 125 129 protected void postParse() throws SAXException { 130 convertFormulas(); 131 132 ensureNotEmpty(report.headers()); 134 ensureNotEmpty(report.pageHeaders()); 135 ensureNotEmpty(report.details()); 136 ensureNotEmpty(report.footers()); 137 ensureNotEmpty(report.pageFooters()); 138 139 for (Iterator iter = report.subreports(); iter.hasNext(); ) 140 ensureNotEmpty(((Subreport)iter.next()).details()); 141 } 142 143 150 protected void ensureNotEmpty(SectionArea area) { 151 if (area.isEmpty()) { 152 Section s = new Section(report); 153 s.getSuppressionProc().setHidden(true); 154 area.add(s); 155 } 156 } 157 158 protected Report getReport() { 159 return subreport != null ? subreport : report; 160 } 161 162 public void startElement(final String namespaceURI, final String localName, 163 final String qName, final Attributes attributes) 164 throws SAXException 165 { 166 String tagName = localName; 167 if (tagName == null || tagName.length() == 0) 168 tagName = qName; 169 170 String parentTag = tagNameStack.empty() ? null 171 : (String )tagNameStack.peek(); 172 tagNameStack.push(new String (tagName)); 173 174 if (textData == null || textData.length() > 0) 176 textData = new String (); 177 178 if ("report".equals(tagName)) report(attributes); 179 else if ("bean-scripting-framework".equals(tagName)) 180 defaultLanguage(attributes); 181 else if ("language".equals(tagName)) language(attributes); 182 else if ("database".equals(tagName)) database(attributes); 183 else if ("query".equals(tagName)) query(attributes); 184 else if ("charsep".equals(tagName)) charSepSource(attributes); 185 else if ("nc-database".equals(tagName)) ncDatabaseSource(attributes); 186 else if ("column".equals(tagName)) column(attributes); 187 else if ("subreport-joins".equals(tagName)) inSubreportJoins = true; 188 else if ("join".equals(tagName)) join(attributes); 189 else if ("sort".equals(tagName)) sort(attributes); 190 else if ("subreport".equals(tagName)) subreport(attributes); 191 else if ("parameter".equals(tagName)) parameter(attributes); 192 else if ("formula".equals(tagName)) formula(parentTag, attributes); 193 else if ("usercol".equals(tagName)) usercol(attributes); 194 else if ("headers".equals(tagName)) header(parentTag); 195 else if ("footers".equals(tagName)) footer(parentTag); 196 else if ("group".equals(tagName)) group(attributes); 197 else if ("details".equals(tagName)) 198 nextSectionLocation = SectionArea.DETAIL; 199 else if ("section".equals(tagName)) section(attributes); 200 else if ("field".equals(tagName)) field(attributes); 201 else if ("bounds".equals(tagName)) bounds(attributes); 202 else if ("edge".equals(tagName)) edge(attributes); 203 else if ("format".equals(tagName)) format(attributes); 204 else if ("border".equals(tagName)) border(attributes); 205 else if ("line".equals(tagName)) line(attributes); 206 else if ("point".equals(tagName)) point(attributes); 207 else if ("paper".equals(tagName)) paper(attributes); 208 else if ("suppression-proc".equals(tagName)) suppressionProc(attributes); 209 } 210 211 protected void header(String parentTag) { 212 if ("report".equals(parentTag)) 213 nextSectionLocation = SectionArea.REPORT_HEADER; 214 else if ("page".equals(parentTag)) 215 nextSectionLocation = SectionArea.PAGE_HEADER; 216 else if ("group".equals(parentTag)) 217 nextSectionLocation = SectionArea.GROUP_HEADER; 218 } 219 220 protected void footer(String parentTag) { 221 if ("report".equals(parentTag)) 222 nextSectionLocation = SectionArea.REPORT_FOOTER; 223 else if ("page".equals(parentTag)) 224 nextSectionLocation = SectionArea.PAGE_FOOTER; 225 else if ("group".equals(parentTag)) 226 nextSectionLocation = SectionArea.GROUP_FOOTER; 227 } 228 229 232 public void endElement(final String namespaceURI, final String localName, 233 final String qName) 234 throws SAXException 235 { 236 String tagName = localName; 237 if (tagName == null || tagName.length() == 0) 238 tagName = qName; 239 240 tagNameStack.pop(); 243 244 if ("description".equals(tagName)) 245 getReport().setDescription(textData); 246 else if ("subreport".equals(tagName)) 247 subreport = null; 248 else if ("subreport-joins".equals(tagName)) 249 inSubreportJoins = false; 250 else if ("default".equals(tagName) && parameter != null) 251 parameter.addDefaultValue(textData); 252 else if ("formula".equals(tagName)) { 253 formula.setExpression(textData); 254 if (formulasToConvert != null) { 257 FormulaConversion fc = 258 (FormulaConversion)formulasToConvert.get(formula.getName()); 259 if (fc != null) 260 fc.expression = new String (textData); 261 } 262 formula = null; 263 } 264 else if ("usercol".equals(tagName)) { 265 usercol.setExpression(textData); 266 usercol = null; 267 } 268 else if ("text".equals(tagName) && field != null) 269 field.setValue(textData); 270 else if ("where".equals(tagName)) 271 getReport().getDataSource().getQuery().setWhereClause(textData); 272 else if ("metadata-url".equals(tagName)) { 273 try { 274 getReport().getDataSource().readMetadataFrom(textData); 275 } 276 catch (Exception e) { 277 throw new SAXException(e); 278 } 279 } 280 } 281 282 286 public void characters(char ch[], int start, int length) { 287 textData += new String (ch, start, length); 288 } 289 290 293 protected void report(Attributes attributes) { 294 String dtdVersionString = attributes.getValue("dtd-version"); 295 dtdVersion = (dtdVersionString == null) 296 ? DEFAULT_DTD_VERSION : Double.parseDouble(dtdVersionString); 297 298 getReport().setName(attributes.getValue("name")); 299 getReport().setTitle(attributes.getValue("title")); 300 getReport().setAuthor(attributes.getValue("author")); 301 } 302 303 protected void defaultLanguage(Attributes attributes) { 304 String lang = rubyLanguageNameHack(attributes.getValue("default-language")); 305 getReport().getScripting().setDefaultLanguage(lang); 306 } 307 308 protected void language(Attributes attributes) { 309 String lang = rubyLanguageNameHack(attributes.getValue("name")); 310 getReport().getScripting().addLanguage(lang, attributes.getValue("class")); 311 } 312 313 protected String rubyLanguageNameHack(String lang) { 314 return "ruby".equals(lang) ? "Ruby" : lang; 317 } 318 319 328 protected void database(Attributes attributes) { 329 if (getReport().hasDataSource()) 330 return; 331 332 try { 333 Database db = new Database(attributes.getValue("driverClassName"), 334 attributes.getValue("connInfo"), 335 getReport(), 336 attributes.getValue("name"), 337 attributes.getValue("username")); 338 getReport().setDataSource(db); 339 } 340 catch (UserCancellationException iae) { 341 throw iae; 344 } 345 catch (Exception e) { 346 ErrorHandler.error(I18N.get("ReportReader.db_err"), e, 347 I18N.get("ReportReader.db_err_title")); 348 } 349 } 350 351 355 protected void query(Attributes attributes) { 356 } 357 358 361 protected void charSepSource(Attributes attributes) { 362 if (getReport().hasDataSource()) 363 return; 364 365 CharSepSource charSepSource = new CharSepSource(getReport()); 366 String charString = attributes.getValue("sep-char"); 367 if (charString != null) 368 charSepSource.setSepChar(charString.charAt(0)); 369 370 getReport().setDataSource(charSepSource); 371 } 372 373 376 protected void ncDatabaseSource(Attributes attributes) { 377 if (!getReport().hasDataSource()) 378 getReport().setDataSource(new NCDatabase(getReport())); 379 } 380 381 protected void column(Attributes attributes) { 382 String name = attributes.getValue("name"); 383 int type = Column.typeFromString(attributes.getValue("type")); 384 Column col = new Column(name, name, type); 385 col.setDateParseFormat(attributes.getValue("date-format")); 386 387 getReport().getDataSource().addColumn(col); 388 } 389 390 protected void join(Attributes attributes) { 391 Column from = findColumn(attributes.getValue("from")); 392 Column to = findColumn(attributes.getValue("to")); 393 if (from != null && to != null) { 394 Join join = new Join(from, attributes.getValue("relation"), to); 395 if (inSubreportJoins) 396 ((Subreport)getReport()).addJoin(join); 397 else 398 getReport().getDataSource().getQuery().addJoin(join); 399 } 400 } 401 402 protected void sort(Attributes attributes) { 403 String oldColumnIdStr = attributes.getValue("column"); 404 Selectable selectable = null; 405 if (oldColumnIdStr != null) { selectable = findColumn(oldColumnIdStr.trim()); 407 if (selectable == null) { 408 group = null; 409 return; 410 } 411 } 412 else { 413 selectable = 414 findSelectable(attributes.getValue("groupable-id").trim(), 415 attributes.getValue("groupable-type").trim()); 416 } 417 418 if (selectable != null) { 419 String str = attributes.getValue("order"); 420 int val = (str != null && str.length() > 0 && str.charAt(0) == 'd') 421 ? Query.SORT_DESCENDING : Query.SORT_ASCENDING; 422 getReport().getDataSource().getQuery().addSort(selectable, val); 423 } 424 } 425 426 protected void subreport(Attributes attributes) { 427 subreport = new Subreport(report, new Long (attributes.getValue("id"))); 428 430 removeReportSections(); 432 try { 433 Database db = (Database)report.getDataSource(); 434 subreport.setDataSource(new SubreportDatabase(db.getConnection(), 435 subreport)); 436 } 437 catch (Exception e) { 438 ErrorHandler.error(I18N.get("ReportReader.db_err"), e, 439 I18N.get("ReportReader.db_err_title")); 440 } 441 } 442 443 protected void parameter(Attributes attributes) throws SAXException { 444 parameter = new Parameter(new Long (attributes.getValue("id")), 445 getReport(), 446 attributes.getValue("type"), 447 attributes.getValue("name"), 448 attributes.getValue("question"), 449 attributes.getValue("arity")); 450 getReport().addParameter(parameter); 451 } 452 453 458 protected void formula(String parentTag, Attributes attributes) 459 throws SAXException 460 { 461 String idString = attributes.getValue("id"); 462 String name = attributes.getValue("name"); 463 Long id = null; 464 if (idString == null) { 465 if (dtdVersion >= DTD_VERSION_FORMULA_IDS) { 466 String str = I18N.get("ReportReader.the_formula") 467 + ' ' + name + ' ' 468 + I18N.get("ReportReader.formula_missing_id_err"); 469 throw new SAXException(str); 470 } 471 } 473 else 474 id = new Long (idString); 475 476 if ("formulas".equals(parentTag)) { 477 formula = new Formula(id, getReport(), name, null); 478 getReport().addFormula(formula); 479 } 480 else if ("suppression-proc".equals(parentTag)) { 481 formula = section.getSuppressionProc().getFormula(); 483 } 484 else { 485 formula = new Formula(id, getReport(), name, null); 486 getReport().setStartFormula(formula); 487 } 488 489 if (id == null) { 492 if (formulasToConvert == null) 493 formulasToConvert = new HashMap(); 494 FormulaConversion fc = new FormulaConversion(formula, null); 495 formulasToConvert.put(formula.getName(), fc); 496 } 497 498 String language = attributes.getValue("language"); 499 if (language != null) 500 formula.setLanguage(language); 501 } 502 503 506 protected void usercol(Attributes attributes) throws SAXException { 507 usercol = new UserColumn(new Long (attributes.getValue("id")), getReport(), 508 attributes.getValue("name"), null); 509 getReport().addUserColumn(usercol); 510 } 511 512 516 protected void convertFormulas() throws SAXException { 517 if (formulasToConvert != null) { 518 for (Iterator iter = formulasToConvert.values().iterator(); 519 iter.hasNext(); ) 520 { 521 FormulaConversion fc = (FormulaConversion)iter.next(); 522 Formula f = fc.formula; 523 try { 524 f.setEditableExpression(fc.expression); 525 } 526 catch (IllegalArgumentException iae) { 527 String msg = I18N.get("ReportReader.the_formula") 528 + ' ' + f.getName() + ' ' 529 + I18N.get("ReportReader.formula_unknown_name"); 530 throw new SAXException(msg); 531 } 532 } 533 } 534 } 535 536 537 protected void group(Attributes attributes) { 538 String oldColumnIdStr = attributes.getValue("column"); 539 Selectable selectable = null; 540 if (oldColumnIdStr != null) { selectable = findColumn(oldColumnIdStr.trim()); 542 if (selectable == null) { 543 group = null; 544 return; 545 } 546 } 547 else { 548 selectable = 549 findSelectable(attributes.getValue("groupable-id").trim(), 550 attributes.getValue("groupable-type").trim()); 551 } 552 553 group = new Group(getReport(), selectable); 554 555 String sortOrderString = attributes.getValue("sort-order"); if (sortOrderString != null) 557 group.setSortOrder(Group.sortOrderStringToInt(sortOrderString.trim())); 558 559 getReport().groups.add(group); 560 } 561 562 563 protected void section(Attributes attributes) { 564 section = new Section(getReport()); 565 section.setMinHeight(Double.parseDouble(attributes.getValue("height"))); 566 567 String boolValString = attributes.getValue("suppressed"); 569 if ("true".equals(boolValString)) 570 section.getSuppressionProc().setHidden(true); 571 572 boolValString = attributes.getValue("pagebreak"); 573 section.setPageBreak("true".equals(boolValString)); 574 575 addSectionToReport(); 576 } 577 578 582 protected void addSectionToReport() { 583 switch (nextSectionLocation) { 584 case SectionArea.GROUP_HEADER: 585 if (group != null) 586 group.headers().add(section); 587 break; 588 case SectionArea.GROUP_FOOTER: 589 if (group != null) 590 group.footers().add(section); 591 break; 592 default: 593 getReport().getSectionArea(nextSectionLocation).add(section); 594 break; 595 } 596 } 597 598 603 protected void field(Attributes attributes) { 604 if (section == null) { field = report.getDefaultField(); 606 return; 607 } 608 609 String id = attributes.getValue("id"); 610 String type = attributes.getValue("type"); 611 Object value = attributes.getValue("value"); 612 String visibleString = attributes.getValue("visible"); 613 614 boolean visible = true; 615 if (visibleString != null) { 616 visibleString = visibleString.trim().toLowerCase(); 617 if (visibleString.length() > 0) 618 visible = "true".equals(visibleString); 619 } 620 621 if ("column".equals(type) && findColumn(value.toString()) == null) { 623 field = null; 624 return; 625 } 626 627 if ("formula".equals(type) && formulasToConvert != null && value != null) { 631 Formula f = ((FormulaConversion)formulasToConvert.get(value)).formula; 632 if (f != null) 633 value = f.getId(); 634 } 635 636 field = 637 Field.create(new Long (id), getReport(), section, type, value, visible); 638 if (field instanceof AggregateField && group != null) 639 ((AggregateField)field).setGroup(group); 640 641 section.addField(field); 642 } 643 644 645 protected void bounds(Attributes attributes) { 646 if (field != null) 647 field.getBounds() 648 .setBounds(Double.parseDouble(attributes.getValue("x")), 649 Double.parseDouble(attributes.getValue("y")), 650 Double.parseDouble(attributes.getValue("width")), 651 Double.parseDouble(attributes.getValue("height"))); 652 } 653 654 655 protected void format(Attributes attributes) { 656 if (field == null) 657 return; 658 659 Format format = field.getFormat(); 660 String val; 661 662 if ((val = attributes.getValue("font")) != null) 663 format.setFontFamilyName(val); 664 if ((val = attributes.getValue("size")) != null) 665 format.setSize(Double.parseDouble(val)); 666 if ((val = attributes.getValue("bold")) != null) 667 format.setBold("true".equals(val)); 668 if ((val = attributes.getValue("italic")) != null) 669 format.setItalic("true".equals(val)); 670 if ((val = attributes.getValue("underline")) != null) 671 format.setUnderline("true".equals(val)); 672 if ((val = attributes.getValue("wrap")) != null) 673 format.setWrap("true".equals(val)); 674 if ((val = attributes.getValue("align")) != null) 675 format.setAlign(Format.alignFromString(val)); 676 if ((val = attributes.getValue("color")) != null) 677 format.setColor(parseColor(val)); 678 if ((val = attributes.getValue("format")) != null) 679 format.setFormat(val); 680 } 681 682 683 protected Color parseColor(String val) { 684 StringTokenizer tok = new StringTokenizer(val, ";"); 685 int r = Integer.parseInt(tok.nextToken().trim()); 686 int g = Integer.parseInt(tok.nextToken().trim()); 687 int b = Integer.parseInt(tok.nextToken().trim()); 688 int a = Integer.parseInt(tok.nextToken().trim()); 689 return new Color (r, g, b, a); 690 } 691 692 693 protected void border(Attributes attributes) { 694 if (field != null) { 695 border = new Border(field); 696 field.setBorder(border); 697 698 String val = attributes.getValue("color"); 699 if (val != null) 700 border.setColor(parseColor(val)); 701 } 702 } 703 704 705 protected void edge(Attributes attributes) { 706 if (field == null) 707 return; 708 709 String val = attributes.getValue("style"); 710 int style = BorderEdge.styleFromString(val); 711 712 val = attributes.getValue("thickness"); 713 double thickness = (val == null) 714 ? BorderEdge.DEFAULT_THICKNESS : Double.parseDouble(val); 715 716 val = attributes.getValue("number"); 717 int num = (val == null) 718 ? BorderEdge.DEFAULT_NUMBER : Integer.parseInt(val); 719 720 BorderEdge edge = new BorderEdge(style, thickness, num); 721 722 String loc = attributes.getValue("location"); 723 if ("top".equals(loc)) border.setTop(edge); 724 else if ("bottom".equals(loc)) border.setBottom(edge); 725 else if ("left".equals(loc)) border.setLeft(edge); 726 else if ("right".equals(loc)) border.setRight(edge); 727 } 728 729 730 protected void line(Attributes attributes) { 731 String val = attributes.getValue("thickness"); 732 double thickness = (val == null) ? 1.0 : Double.parseDouble(val); 733 Color color = null; 734 if ((val = attributes.getValue("color")) != null) 735 color = parseColor(val); 736 737 val = attributes.getValue("visible"); 738 boolean visible = true; 739 if (val != null) { 740 val = val.trim().toLowerCase(); 741 if (val.length() > 0) 742 visible = "true".equals(val); 743 } 744 745 section.lines.add(line = new Line(getReport(), section, thickness, color, 746 visible)); 747 } 748 749 750 protected void point(Attributes attributes) { 751 line.addEndPoint(Double.parseDouble(attributes.getValue("x")), 752 Double.parseDouble(attributes.getValue("y"))); 753 } 754 755 756 protected void paper(Attributes attributes) { 757 int orientation = PaperFormat.PORTRAIT; String orientationStr = attributes.getValue("orientation"); 759 if (orientationStr != null 760 && "landscape".equals(orientationStr.toLowerCase())) 761 orientation = PaperFormat.LANDSCAPE; 762 763 PaperFormat pf = 764 PaperFormat.get(orientation, attributes.getValue("name")); 765 if (pf != null) 766 getReport().setPaperFormat(pf); 767 } 768 769 770 protected void suppressionProc(Attributes attributes) { 771 String state = attributes.getValue("hide"); 772 if (state != null && state.length() > 0) { 773 SuppressionProc sp = section.getSuppressionProc(); 774 state = state.trim().toLowerCase(); 775 if ("true".equals(state)) sp.setHidden(true); 776 } 777 } 778 779 786 protected Column findColumn(String fullName) { 787 Column col = getReport().findColumn(fullName); 788 if (col == null && !missingColumnSeen) { 789 missingColumnSeen = true; 790 ErrorHandler.error(I18N.get("ReportReader.the_column") 791 + ' ' + fullName + ' ' 792 + I18N.get("ReportReader.column_unknown")); 793 } 794 return col; 795 } 796 797 805 protected Selectable findSelectable(String idStr, String typeStr) { 806 Selectable g = getReport().findSelectable(idStr, typeStr); 807 if (g == null && !missingColumnSeen) { 808 missingColumnSeen = true; 809 ErrorHandler.error(I18N.get("ReportReader.the_column") 810 + ' ' + idStr + " (" + typeStr + ") " 811 + I18N.get("ReportReader.column_unknown")); 812 } 813 return g; 814 } 815 816 } 817 | Popular Tags |