| 1 28 package net.sf.jasperreports.engine.design; 29 30 import java.util.ArrayList ; 31 import java.util.Arrays ; 32 import java.util.Collection ; 33 import java.util.Comparator ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Map ; 38 39 import net.sf.jasperreports.charts.JRCategoryDataset; 40 import net.sf.jasperreports.charts.JRCategorySeries; 41 import net.sf.jasperreports.charts.JRHighLowDataset; 42 import net.sf.jasperreports.charts.JRPieDataset; 43 import net.sf.jasperreports.charts.JRTimePeriodDataset; 44 import net.sf.jasperreports.charts.JRTimePeriodSeries; 45 import net.sf.jasperreports.charts.JRTimeSeries; 46 import net.sf.jasperreports.charts.JRTimeSeriesDataset; 47 import net.sf.jasperreports.charts.JRValueDataset; 48 import net.sf.jasperreports.charts.JRXyDataset; 49 import net.sf.jasperreports.charts.JRXySeries; 50 import net.sf.jasperreports.charts.JRXyzDataset; 51 import net.sf.jasperreports.charts.JRXyzSeries; 52 import net.sf.jasperreports.crosstabs.JRCellContents; 53 import net.sf.jasperreports.crosstabs.JRCrosstab; 54 import net.sf.jasperreports.crosstabs.JRCrosstabBucket; 55 import net.sf.jasperreports.crosstabs.JRCrosstabCell; 56 import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup; 57 import net.sf.jasperreports.crosstabs.JRCrosstabDataset; 58 import net.sf.jasperreports.crosstabs.JRCrosstabGroup; 59 import net.sf.jasperreports.crosstabs.JRCrosstabMeasure; 60 import net.sf.jasperreports.crosstabs.JRCrosstabParameter; 61 import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup; 62 import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab; 63 import net.sf.jasperreports.crosstabs.fill.JRPercentageCalculator; 64 import net.sf.jasperreports.crosstabs.fill.JRPercentageCalculatorFactory; 65 import net.sf.jasperreports.engine.JRAnchor; 66 import net.sf.jasperreports.engine.JRBand; 67 import net.sf.jasperreports.engine.JRBox; 68 import net.sf.jasperreports.engine.JRChart; 69 import net.sf.jasperreports.engine.JRChartDataset; 70 import net.sf.jasperreports.engine.JRDataset; 71 import net.sf.jasperreports.engine.JRDatasetParameter; 72 import net.sf.jasperreports.engine.JRDatasetRun; 73 import net.sf.jasperreports.engine.JRElement; 74 import net.sf.jasperreports.engine.JRElementDataset; 75 import net.sf.jasperreports.engine.JRException; 76 import net.sf.jasperreports.engine.JRExpression; 77 import net.sf.jasperreports.engine.JRExpressionChunk; 78 import net.sf.jasperreports.engine.JRExpressionCollector; 79 import net.sf.jasperreports.engine.JRField; 80 import net.sf.jasperreports.engine.JRFont; 81 import net.sf.jasperreports.engine.JRFrame; 82 import net.sf.jasperreports.engine.JRGroup; 83 import net.sf.jasperreports.engine.JRHyperlink; 84 import net.sf.jasperreports.engine.JRHyperlinkParameter; 85 import net.sf.jasperreports.engine.JRImage; 86 import net.sf.jasperreports.engine.JRParameter; 87 import net.sf.jasperreports.engine.JRQuery; 88 import net.sf.jasperreports.engine.JRQueryChunk; 89 import net.sf.jasperreports.engine.JRReportFont; 90 import net.sf.jasperreports.engine.JRSortField; 91 import net.sf.jasperreports.engine.JRStaticText; 92 import net.sf.jasperreports.engine.JRStyle; 93 import net.sf.jasperreports.engine.JRSubreport; 94 import net.sf.jasperreports.engine.JRSubreportParameter; 95 import net.sf.jasperreports.engine.JRSubreportReturnValue; 96 import net.sf.jasperreports.engine.JRTextField; 97 import net.sf.jasperreports.engine.JRVariable; 98 import net.sf.jasperreports.engine.fill.JRExtendedIncrementerFactory; 99 import net.sf.jasperreports.engine.query.JRQueryExecuterFactory; 100 import net.sf.jasperreports.engine.util.JRQueryExecuterUtils; 101 102 103 107 public class JRVerifier 108 { 109 110 111 114 private static String [] textFieldClassNames = null; 115 private static String [] imageClassNames = null; 116 private static String [] subreportClassNames = null; 117 118 121 private JasperDesign jasperDesign = null; 122 private Collection brokenRules = null; 123 124 private JRExpressionCollector expressionCollector; 125 126 127 130 protected JRVerifier(JasperDesign jrDesign) 131 { 132 this(jrDesign, null); 133 } 134 135 136 protected JRVerifier(JasperDesign jrDesign, JRExpressionCollector expressionCollector) 137 { 138 jasperDesign = jrDesign; 139 brokenRules = new ArrayList (); 140 141 if (expressionCollector != null) 142 { 143 this.expressionCollector = expressionCollector; 144 } 145 else 146 { 147 this.expressionCollector = JRExpressionCollector.collector(jasperDesign); 148 } 149 } 150 151 152 155 public static Collection verifyDesign(JasperDesign jasperDesign, JRExpressionCollector expressionCollector) 156 { 157 JRVerifier verifier = new JRVerifier(jasperDesign, expressionCollector); 158 return verifier.verifyDesign(); 159 } 160 161 public static Collection verifyDesign(JasperDesign jasperDesign) 162 { 163 return verifyDesign(jasperDesign, null); 164 } 165 166 169 protected Collection verifyDesign() 170 { 171 172 jasperDesign.preprocess(); 174 175 verifyDesignAttributes(); 176 177 178 verifyReportFonts(); 179 180 verifyDataset(jasperDesign.getMainDesignDataset()); 181 182 verifyDatasets(); 183 184 185 verifyStyles(); 186 187 188 verifyBand(jasperDesign.getBackground()); 189 verifyBand(jasperDesign.getTitle()); 190 verifyBand(jasperDesign.getPageHeader()); 191 verifyBand(jasperDesign.getColumnHeader()); 192 verifyBand(jasperDesign.getDetail()); 193 verifyBand(jasperDesign.getColumnFooter()); 194 verifyBand(jasperDesign.getPageFooter()); 195 verifyBand(jasperDesign.getLastPageFooter()); 196 verifyBand(jasperDesign.getSummary()); 197 198 return brokenRules; 199 } 200 201 202 205 private void verifyDesignAttributes() 206 { 207 if (jasperDesign.getName() == null || jasperDesign.getName().trim().length() == 0) 208 { 209 brokenRules.add("Report name is missing."); 210 } 211 212 if (jasperDesign.getColumnCount() <= 0) 213 { 214 brokenRules.add("Column count must be greater than zero."); 215 } 216 217 if (jasperDesign.getPageWidth() < 0) 218 { 219 brokenRules.add("Page width must be positive."); 220 } 221 222 if (jasperDesign.getPageHeight() < 0) 223 { 224 brokenRules.add("Page height must be positive."); 225 } 226 227 if (jasperDesign.getColumnWidth() < 0) 228 { 229 brokenRules.add("Column width must be positive."); 230 } 231 232 if (jasperDesign.getColumnSpacing() < 0) 233 { 234 brokenRules.add("Column spacing must be positive."); 235 } 236 237 if (jasperDesign.getLeftMargin() < 0) 238 { 239 brokenRules.add("Left margin must be positive."); 240 } 241 242 if (jasperDesign.getRightMargin() < 0) 243 { 244 brokenRules.add("Right margin must be positive."); 245 } 246 247 if (jasperDesign.getTopMargin() < 0) 248 { 249 brokenRules.add("Top margin must be positive."); 250 } 251 252 if (jasperDesign.getBottomMargin() < 0) 253 { 254 brokenRules.add("Bottom margin must be positive."); 255 } 256 257 if ( 258 jasperDesign.getLeftMargin() + 259 jasperDesign.getColumnCount() * jasperDesign.getColumnWidth() + 260 (jasperDesign.getColumnCount() - 1) * jasperDesign.getColumnSpacing() + 261 jasperDesign.getRightMargin() > 262 jasperDesign.getPageWidth() 263 ) 264 { 265 brokenRules.add("The columns and the margins do not fit the page width."); 266 } 267 268 if ( 269 jasperDesign.getTopMargin() + 270 (jasperDesign.getBackground() != null ? jasperDesign.getBackground().getHeight() : 0) + 271 jasperDesign.getBottomMargin() > 272 jasperDesign.getPageHeight() 273 ) 274 { 275 brokenRules.add("The background section and the margins do not fit the page height."); 276 } 277 278 if (jasperDesign.isTitleNewPage()) 279 { 280 if ( 281 jasperDesign.getTopMargin() + 282 (jasperDesign.getTitle() != null ? jasperDesign.getTitle().getHeight() : 0) + 283 jasperDesign.getBottomMargin() > 284 jasperDesign.getPageHeight() 285 ) 286 { 287 brokenRules.add("The title section and the margins do not fit the page height."); 288 } 289 } 290 else 291 { 292 if ( 293 jasperDesign.getTopMargin() + 294 (jasperDesign.getTitle() != null ? jasperDesign.getTitle().getHeight() : 0) + 295 (jasperDesign.getPageHeader() != null ? jasperDesign.getPageHeader().getHeight() : 0) + 296 (jasperDesign.getColumnHeader() != null ? jasperDesign.getColumnHeader().getHeight() : 0) + 297 (jasperDesign.getColumnFooter() != null ? jasperDesign.getColumnFooter().getHeight() : 0) + 298 (jasperDesign.getPageFooter() != null ? jasperDesign.getPageFooter().getHeight() : 0) + 299 jasperDesign.getBottomMargin() > 300 jasperDesign.getPageHeight() 301 ) 302 { 303 brokenRules.add("The title section, the page and column headers and footers and the margins do not fit the page height."); 304 } 305 } 306 307 if ( 308 jasperDesign.getTopMargin() + 309 (jasperDesign.getPageHeader() != null ? jasperDesign.getPageHeader().getHeight() : 0) + 310 (jasperDesign.getColumnHeader() != null ? jasperDesign.getColumnHeader().getHeight() : 0) + 311 (jasperDesign.getColumnFooter() != null ? jasperDesign.getColumnFooter().getHeight() : 0) + 312 (jasperDesign.getPageFooter() != null ? jasperDesign.getPageFooter().getHeight() : 0) + 313 jasperDesign.getBottomMargin() > 314 jasperDesign.getPageHeight() 315 ) 316 { 317 brokenRules.add("The page and column headers and footers and the margins do not fit the page height."); 318 } 319 320 if ( 321 jasperDesign.getTopMargin() + 322 (jasperDesign.getPageHeader() != null ? jasperDesign.getPageHeader().getHeight() : 0) + 323 (jasperDesign.getColumnHeader() != null ? jasperDesign.getColumnHeader().getHeight() : 0) + 324 (jasperDesign.getColumnFooter() != null ? jasperDesign.getColumnFooter().getHeight() : 0) + 325 (jasperDesign.getLastPageFooter() != null ? jasperDesign.getLastPageFooter().getHeight() : 0) + 326 jasperDesign.getBottomMargin() > 327 jasperDesign.getPageHeight() 328 ) 329 { 330 brokenRules.add("The page and column headers and footers and the margins do not fit the last page height."); 331 } 332 333 if ( 334 jasperDesign.getTopMargin() + 335 (jasperDesign.getSummary() != null ? jasperDesign.getSummary().getHeight() : 0) + 336 jasperDesign.getBottomMargin() > 337 jasperDesign.getPageHeight() 338 ) 339 { 340 brokenRules.add("The summary section and the margins do not fit the page height."); 341 } 342 343 if ( 344 jasperDesign.getTopMargin() + 345 (jasperDesign.getPageHeader() != null ? jasperDesign.getPageHeader().getHeight() : 0) + 346 (jasperDesign.getColumnHeader() != null ? jasperDesign.getColumnHeader().getHeight() : 0) + 347 (jasperDesign.getDetail() != null ? jasperDesign.getDetail().getHeight() : 0) + 348 (jasperDesign.getColumnFooter() != null ? jasperDesign.getColumnFooter().getHeight() : 0) + 349 (jasperDesign.getPageFooter() != null ? jasperDesign.getPageFooter().getHeight() : 0) + 350 jasperDesign.getBottomMargin() > 351 jasperDesign.getPageHeight() 352 ) 353 { 354 brokenRules.add("The detail section, the page and column headers and footers and the margins do not fit the page height."); 355 } 356 } 357 358 359 362 private void verifyQuery(JRDesignDataset dataset) 363 { 364 JRQuery query = dataset.getQuery(); 365 if (query != null) 366 { 367 String language = query.getLanguage(); 368 JRQueryExecuterFactory queryExecuterFactory = null; 369 if (language == null || language.length() == 0) 370 { 371 brokenRules.add("Query language not set."); 372 } 373 else 374 { 375 try 376 { 377 queryExecuterFactory = JRQueryExecuterUtils.getQueryExecuterFactory(query.getLanguage()); 378 } 379 catch (JRException e1) 380 { 381 brokenRules.add("Query executer factory for " + language + " cannot be created."); 382 } 383 } 384 385 386 JRQueryChunk[] chunks = query.getChunks(); 387 if (chunks != null && chunks.length > 0) 388 { 389 Map parametersMap = dataset.getParametersMap(); 390 391 for(int j = 0; j < chunks.length; j++) 392 { 393 JRQueryChunk queryChunk = chunks[j]; 394 switch (queryChunk.getType()) 395 { 396 case JRQueryChunk.TYPE_PARAMETER : 397 { 398 JRParameter parameter = (JRParameter)parametersMap.get(queryChunk.getText()); 399 if ( parameter == null ) 400 { 401 brokenRules.add("Query parameter not found : " + queryChunk.getText()); 402 } 403 else if (queryExecuterFactory != null) 404 { 405 if (!queryExecuterFactory.supportsQueryParameterType(parameter.getValueClassName())) 406 { 407 brokenRules.add("Parameter type not supported in query : " + queryChunk.getText() + " class " + parameter.getValueClassName()); 408 } 409 } 410 411 break; 412 } 413 case JRQueryChunk.TYPE_PARAMETER_CLAUSE : 414 { 415 if (!parametersMap.containsKey(queryChunk.getText())) 416 { 417 brokenRules.add("Query parameter not found : " + queryChunk.getText()); 418 } 419 break; 420 } 421 case JRQueryChunk.TYPE_TEXT : 422 default : 423 { 424 } 425 } 426 } 427 } 428 } 429 } 430 431 432 435 private void verifyExpressions(List expressions, Map parametersMap, Map fieldsMap, Map variablesMap) 436 { 437 if (expressions != null && expressions.size() > 0) 438 { 439 for(Iterator it = expressions.iterator(); it.hasNext();) 440 { 441 JRExpression expression = (JRExpression)it.next(); 442 JRExpressionChunk[] chunks = expression.getChunks(); 443 if (chunks != null && chunks.length > 0) 444 { 445 for(int j = 0; j < chunks.length; j++) 446 { 447 JRExpressionChunk expressionChunk = chunks[j]; 448 switch (expressionChunk.getType()) 449 { 450 case JRExpressionChunk.TYPE_VARIABLE : 451 { 452 if ( !variablesMap.containsKey(expressionChunk.getText()) ) 453 { 454 brokenRules.add("Variable not found : " + expressionChunk.getText()); 455 } 456 break; 457 } 458 case JRExpressionChunk.TYPE_FIELD : 459 { 460 if ( !fieldsMap.containsKey(expressionChunk.getText()) ) 461 { 462 brokenRules.add("Field not found : " + expressionChunk.getText()); 463 } 464 break; 465 } 466 case JRExpressionChunk.TYPE_PARAMETER : 467 { 468 if ( !parametersMap.containsKey(expressionChunk.getText()) ) 469 { 470 brokenRules.add("Parameter not found : " + expressionChunk.getText()); 471 } 472 break; 473 } 474 case JRExpressionChunk.TYPE_RESOURCE : 475 case JRExpressionChunk.TYPE_TEXT : 476 default : 477 { 478 } 479 } 480 } 481 } 482 } 483 } 484 } 485 486 487 private void verifyExpressions(JRDesignDataset dataset) 488 { 489 verifyExpressions( 490 expressionCollector.getExpressions(dataset), 491 dataset.getParametersMap(), 492 dataset.getFieldsMap(), 493 dataset.getVariablesMap()); 494 } 495 496 499 private void verifyReportFonts() 500 { 501 JRReportFont[] fonts = jasperDesign.getFonts(); 502 if (fonts != null && fonts.length > 0) 503 { 504 for(int index = 0; index < fonts.length; index++) 505 { 506 JRReportFont font = fonts[index]; 507 508 if (font.getName() == null || font.getName().trim().length() == 0) 509 { 510 brokenRules.add("Report font name missing."); 511 } 512 } 513 } 514 } 515 516 517 520 private void verifyStyles() 521 { 522 JRStyle[] styles = jasperDesign.getStyles(); 523 if (styles != null && styles.length > 0) 524 { 525 for(int index = 0; index < styles.length; index++) 526 { 527 JRStyle style = styles[index]; 528 529 if (style.getName() == null || style.getName().trim().length() == 0) 530 { 531 brokenRules.add("Report style name missing."); 532 } 533 } 534 } 535 } 536 537 538 541 private void verifyParameters(JRDesignDataset dataset) 542 { 543 JRParameter[] parameters = dataset.getParameters(); 544 if (parameters != null && parameters.length > 0) 545 { 546 for(int index = 0; index < parameters.length; index++) 547 { 548 JRParameter parameter = parameters[index]; 549 550 if (parameter.getName() == null || parameter.getName().trim().length() == 0) 551 { 552 brokenRules.add("Parameter name missing."); 553 } 554 555 if (parameter.getValueClassName() == null) 556 { 557 brokenRules.add("Class not set for parameter : " + parameter.getName()); 558 } 559 else 560 { 561 JRExpression expression = parameter.getDefaultValueExpression(); 562 if (expression != null) 563 { 564 if (expression.getValueClass() == null) { 565 brokenRules.add("No value class defined for the expression in parameter: "+parameter.getName()); 566 } 567 else { 568 if ( 569 !parameter.getValueClass().isAssignableFrom( 570 expression.getValueClass() 571 ) 572 ) 573 { 574 brokenRules.add("The parameter default value expression class is not compatible with the parameter's class : " + parameter.getName()); 575 } 576 } 577 } 578 } 579 } 580 } 581 } 582 583 584 587 private void verifyFields(JRDesignDataset dataset) 588 { 589 JRField[] fields = dataset.getFields(); 590 if (fields != null && fields.length > 0) 591 { 592 for(int index = 0; index < fields.length; index++) 593 { 594 JRField field = fields[index]; 595 596 if (field.getName() == null || field.getName().trim().length() == 0) 597 { 598 brokenRules.add("Field name missing."); 599 } 600 601 String className = field.getValueClassName(); 602 603 if (className == null) 604 { 605 brokenRules.add("Class not set for field : " + field.getName()); 606 } 607 } 608 } 609 } 610 611 612 615 private void verifySortFields(JRDesignDataset dataset) 616 { 617 JRField[] fields = dataset.getFields(); 618 JRSortField[] sortFields = dataset.getSortFields(); 619 if (sortFields != null && sortFields.length > 0) 620 { 621 for(int index = 0; index < sortFields.length; index++) 622 { 623 JRSortField sortField = sortFields[index]; 624 String sortFieldName = sortField.getName(); 625 626 if (sortFieldName == null || sortFieldName.trim().length() == 0) 627 { 628 brokenRules.add("Sort field name missing."); 629 } 630 else 631 { 632 boolean isFound = false; 633 634 int j = 0; 635 while (!isFound && j < fields.length) 636 { 637 isFound = sortFieldName.equals(fields[j].getName()); 638 j++; 639 } 640 641 if (!isFound) 642 { 643 brokenRules.add("Sort field \"" + sortFieldName + "\" not declared."); 644 } 645 } 646 } 647 } 648 } 649 650 651 654 private void verifyVariables(JRDesignDataset dataset) 655 { 656 JRVariable[] variables = dataset.getVariables(); 657 if (variables != null && variables.length > 0) 658 { 659 boolean isMainDataset = dataset.isMainDataset(); 660 for(int index = 0; index < variables.length; index++) 661 { 662 JRVariable variable = variables[index]; 663 664 if (variable.getName() == null || variable.getName().trim().length() == 0) 665 { 666 brokenRules.add("Variable name missing."); 667 } 668 669 Class valueClass = variable.getValueClass(); 670 671 if (valueClass == null) 672 { 673 brokenRules.add("Class not set for variable : " + variable.getName()); 674 } 675 else 676 { 677 JRExpression expression = variable.getExpression(); 678 if (expression != null) 679 { 680 if (expression.getValueClass() == null) { 681 brokenRules.add("No value class for the expression has been set in variable: "+variable.getName()); 682 } 683 else { 684 if ( 685 variable.getCalculation() != JRVariable.CALCULATION_COUNT 686 && variable.getCalculation() != JRVariable.CALCULATION_DISTINCT_COUNT 687 && variable.getCalculation() != JRVariable.CALCULATION_SYSTEM 688 && !valueClass.isAssignableFrom( 689 expression.getValueClass() 690 ) 691 ) 692 { 693 brokenRules.add("The variable expression class is not compatible with the variable's class : " + variable.getName()); 694 } 695 } 696 } 697 698 if (variable.getInitialValueExpression() != null) 699 { 700 if ( 701 !valueClass.isAssignableFrom( 702 variable.getInitialValueExpression().getValueClass() 703 ) 704 ) 705 { 706 brokenRules.add("The initial value class is not compatible with the variable's class : " + variable.getName()); 707 } 708 } 709 } 710 711 byte resetType = variable.getResetType(); 712 if (resetType == JRVariable.RESET_TYPE_GROUP) 713 { 714 if (variable.getResetGroup() == null) 715 { 716 brokenRules.add("Reset group missing for variable : " + variable.getName()); 717 } 718 else 719 { 720 Map groupsMap = dataset.getGroupsMap(); 721 722 if (!groupsMap.containsKey(variable.getResetGroup().getName())) 723 { 724 brokenRules.add("Reset group \"" + variable.getResetGroup().getName() + "\" not found for variable : " + variable.getName()); 725 } 726 } 727 } 728 729 byte incrementType = variable.getIncrementType(); 730 if (incrementType == JRVariable.RESET_TYPE_GROUP) 731 { 732 if (variable.getIncrementGroup() == null) 733 { 734 brokenRules.add("Increment group missing for variable : " + variable.getName()); 735 } 736 else 737 &nbs
|