0001: /*
0002: * ============================================================================
0003: * GNU Lesser General Public License
0004: * ============================================================================
0005: *
0006: * JasperReports - Free Java report-generating library.
0007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
0008: *
0009: * This library is free software; you can redistribute it and/or
0010: * modify it under the terms of the GNU Lesser General Public
0011: * License as published by the Free Software Foundation; either
0012: * version 2.1 of the License, or (at your option) any later version.
0013: *
0014: * This library is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0017: * Lesser General Public License for more details.
0018: *
0019: * You should have received a copy of the GNU Lesser General Public
0020: * License along with this library; if not, write to the Free Software
0021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
0022: *
0023: * JasperSoft Corporation
0024: * 303 Second Street, Suite 450 North
0025: * San Francisco, CA 94107
0026: * http://www.jaspersoft.com
0027: */
0028: package net.sf.jasperreports.engine.design;
0029:
0030: import java.util.ArrayList;
0031: import java.util.Arrays;
0032: import java.util.Collection;
0033: import java.util.Comparator;
0034: import java.util.HashMap;
0035: import java.util.Iterator;
0036: import java.util.List;
0037: import java.util.Map;
0038:
0039: import net.sf.jasperreports.charts.JRCategoryDataset;
0040: import net.sf.jasperreports.charts.JRCategorySeries;
0041: import net.sf.jasperreports.charts.JRHighLowDataset;
0042: import net.sf.jasperreports.charts.JRPieDataset;
0043: import net.sf.jasperreports.charts.JRTimePeriodDataset;
0044: import net.sf.jasperreports.charts.JRTimePeriodSeries;
0045: import net.sf.jasperreports.charts.JRTimeSeries;
0046: import net.sf.jasperreports.charts.JRTimeSeriesDataset;
0047: import net.sf.jasperreports.charts.JRValueDataset;
0048: import net.sf.jasperreports.charts.JRXyDataset;
0049: import net.sf.jasperreports.charts.JRXySeries;
0050: import net.sf.jasperreports.charts.JRXyzDataset;
0051: import net.sf.jasperreports.charts.JRXyzSeries;
0052: import net.sf.jasperreports.crosstabs.JRCellContents;
0053: import net.sf.jasperreports.crosstabs.JRCrosstab;
0054: import net.sf.jasperreports.crosstabs.JRCrosstabBucket;
0055: import net.sf.jasperreports.crosstabs.JRCrosstabCell;
0056: import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup;
0057: import net.sf.jasperreports.crosstabs.JRCrosstabDataset;
0058: import net.sf.jasperreports.crosstabs.JRCrosstabGroup;
0059: import net.sf.jasperreports.crosstabs.JRCrosstabMeasure;
0060: import net.sf.jasperreports.crosstabs.JRCrosstabParameter;
0061: import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup;
0062: import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab;
0063: import net.sf.jasperreports.crosstabs.fill.JRPercentageCalculator;
0064: import net.sf.jasperreports.crosstabs.fill.JRPercentageCalculatorFactory;
0065: import net.sf.jasperreports.engine.JRAnchor;
0066: import net.sf.jasperreports.engine.JRBand;
0067: import net.sf.jasperreports.engine.JRBox;
0068: import net.sf.jasperreports.engine.JRChart;
0069: import net.sf.jasperreports.engine.JRChartDataset;
0070: import net.sf.jasperreports.engine.JRDataset;
0071: import net.sf.jasperreports.engine.JRDatasetParameter;
0072: import net.sf.jasperreports.engine.JRDatasetRun;
0073: import net.sf.jasperreports.engine.JRElement;
0074: import net.sf.jasperreports.engine.JRElementDataset;
0075: import net.sf.jasperreports.engine.JRException;
0076: import net.sf.jasperreports.engine.JRExpression;
0077: import net.sf.jasperreports.engine.JRExpressionChunk;
0078: import net.sf.jasperreports.engine.JRExpressionCollector;
0079: import net.sf.jasperreports.engine.JRField;
0080: import net.sf.jasperreports.engine.JRFont;
0081: import net.sf.jasperreports.engine.JRFrame;
0082: import net.sf.jasperreports.engine.JRGroup;
0083: import net.sf.jasperreports.engine.JRHyperlink;
0084: import net.sf.jasperreports.engine.JRHyperlinkParameter;
0085: import net.sf.jasperreports.engine.JRImage;
0086: import net.sf.jasperreports.engine.JRParameter;
0087: import net.sf.jasperreports.engine.JRQuery;
0088: import net.sf.jasperreports.engine.JRQueryChunk;
0089: import net.sf.jasperreports.engine.JRReportFont;
0090: import net.sf.jasperreports.engine.JRReportTemplate;
0091: import net.sf.jasperreports.engine.JRRuntimeException;
0092: import net.sf.jasperreports.engine.JRSortField;
0093: import net.sf.jasperreports.engine.JRStaticText;
0094: import net.sf.jasperreports.engine.JRStyle;
0095: import net.sf.jasperreports.engine.JRSubreport;
0096: import net.sf.jasperreports.engine.JRSubreportParameter;
0097: import net.sf.jasperreports.engine.JRSubreportReturnValue;
0098: import net.sf.jasperreports.engine.JRTemplate;
0099: import net.sf.jasperreports.engine.JRTextField;
0100: import net.sf.jasperreports.engine.JRVariable;
0101: import net.sf.jasperreports.engine.fill.JRExtendedIncrementerFactory;
0102: import net.sf.jasperreports.engine.query.JRQueryExecuterFactory;
0103: import net.sf.jasperreports.engine.util.FormatFactory;
0104: import net.sf.jasperreports.engine.util.JRClassLoader;
0105: import net.sf.jasperreports.engine.util.JRQueryExecuterUtils;
0106:
0107: /**
0108: * @author Teodor Danciu (teodord@users.sourceforge.net)
0109: * @version $Id: JRVerifier.java 1795 2007-07-30 09:18:47Z teodord $
0110: */
0111: public class JRVerifier {
0112:
0113: /**
0114: *
0115: */
0116: private static String[] textFieldClassNames = null;
0117: private static String[] imageClassNames = null;
0118: private static String[] subreportClassNames = null;
0119:
0120: private static Class[] templateTypes = new Class[] { String.class,
0121: java.io.File.class, java.net.URL.class,
0122: java.io.InputStream.class, JRTemplate.class };
0123:
0124: /**
0125: *
0126: */
0127: private JasperDesign jasperDesign = null;
0128: private Collection brokenRules = null;
0129:
0130: private JRExpressionCollector expressionCollector;
0131:
0132: /**
0133: *
0134: */
0135: protected JRVerifier(JasperDesign jrDesign) {
0136: this (jrDesign, null);
0137: }
0138:
0139: protected JRVerifier(JasperDesign jrDesign,
0140: JRExpressionCollector expressionCollector) {
0141: jasperDesign = jrDesign;
0142: brokenRules = new ArrayList();
0143:
0144: if (expressionCollector != null) {
0145: this .expressionCollector = expressionCollector;
0146: } else {
0147: this .expressionCollector = JRExpressionCollector
0148: .collector(jasperDesign);
0149: }
0150: }
0151:
0152: protected void addBrokenRule(String message, Object source) {
0153: JRValidationFault fault = new JRValidationFault();
0154: fault.setMessage(message);
0155: fault.setSource(source);
0156: brokenRules.add(fault);
0157: }
0158:
0159: protected void addBrokenRule(Exception e, Object source) {
0160: JRValidationFault fault = new JRValidationFault();
0161: fault.setMessage(e.getMessage());
0162: fault.setSource(source);
0163: brokenRules.add(fault);
0164: }
0165:
0166: /**
0167: * Validates a {@link JasperDesign report design}.
0168: *
0169: * @param jasperDesign the report design
0170: * @param expressionCollector a collector which was used to collect expressions from the report design;
0171: * if null, a new collector will be created and used to collect the expressions
0172: *
0173: * @return a list of {@link JRValidationFault design faults};
0174: * the report design is valid iff the list is empty
0175: */
0176: public static Collection verifyDesign(JasperDesign jasperDesign,
0177: JRExpressionCollector expressionCollector) {
0178: JRVerifier verifier = new JRVerifier(jasperDesign,
0179: expressionCollector);
0180: return verifier.verifyDesign();
0181: }
0182:
0183: /**
0184: * Validates a {@link JasperDesign report design}.
0185: *
0186: * @param jasperDesign the report design
0187: *
0188: * @return a list of {@link JRValidationFault design faults};
0189: * the report design is valid iff the list is empty
0190: */
0191: public static Collection verifyDesign(JasperDesign jasperDesign) {
0192: return verifyDesign(jasperDesign, null);
0193: }
0194:
0195: /**
0196: *
0197: */
0198: protected Collection verifyDesign() {
0199: /* */
0200: jasperDesign.preprocess();//FIXME either calculate twice or use change listeners
0201:
0202: /* */
0203: verifyDesignAttributes();
0204:
0205: verifyReportTemplates();
0206:
0207: /* */
0208: verifyReportFonts();
0209:
0210: verifyDataset(jasperDesign.getMainDesignDataset());
0211:
0212: verifyDatasets();
0213:
0214: /* */
0215: verifyStyles();
0216:
0217: /* */
0218: verifyBand(jasperDesign.getBackground());
0219: verifyBand(jasperDesign.getTitle());
0220: verifyBand(jasperDesign.getPageHeader());
0221: verifyBand(jasperDesign.getColumnHeader());
0222: verifyBand(jasperDesign.getDetail());
0223: verifyBand(jasperDesign.getColumnFooter());
0224: verifyBand(jasperDesign.getPageFooter());
0225: verifyBand(jasperDesign.getLastPageFooter());
0226: verifyBand(jasperDesign.getSummary());
0227: verifyBand(jasperDesign.getNoData());
0228:
0229: return brokenRules;
0230: }
0231:
0232: /**
0233: *
0234: */
0235: private void verifyDesignAttributes() {
0236: if (jasperDesign.getName() == null
0237: || jasperDesign.getName().trim().length() == 0) {
0238: addBrokenRule("Report name is missing.", jasperDesign);
0239: }
0240:
0241: if (jasperDesign.getColumnCount() <= 0) {
0242: addBrokenRule("Column count must be greater than zero.",
0243: jasperDesign);
0244: }
0245:
0246: if (jasperDesign.getPageWidth() < 0) {
0247: addBrokenRule("Page width must be positive.", jasperDesign);
0248: }
0249:
0250: if (jasperDesign.getPageHeight() < 0) {
0251: addBrokenRule("Page height must be positive.", jasperDesign);
0252: }
0253:
0254: if (jasperDesign.getColumnWidth() < 0) {
0255: addBrokenRule("Column width must be positive.",
0256: jasperDesign);
0257: }
0258:
0259: if (jasperDesign.getColumnSpacing() < 0) {
0260: addBrokenRule("Column spacing must be positive.",
0261: jasperDesign);
0262: }
0263:
0264: if (jasperDesign.getLeftMargin() < 0) {
0265: addBrokenRule("Left margin must be positive.", jasperDesign);
0266: }
0267:
0268: if (jasperDesign.getRightMargin() < 0) {
0269: addBrokenRule("Right margin must be positive.",
0270: jasperDesign);
0271: }
0272:
0273: if (jasperDesign.getTopMargin() < 0) {
0274: addBrokenRule("Top margin must be positive.", jasperDesign);
0275: }
0276:
0277: if (jasperDesign.getBottomMargin() < 0) {
0278: addBrokenRule("Bottom margin must be positive.",
0279: jasperDesign);
0280: }
0281:
0282: if (jasperDesign.getLeftMargin()
0283: + jasperDesign.getColumnCount()
0284: * jasperDesign.getColumnWidth()
0285: + (jasperDesign.getColumnCount() - 1)
0286: * jasperDesign.getColumnSpacing()
0287: + jasperDesign.getRightMargin() > jasperDesign
0288: .getPageWidth()) {
0289: addBrokenRule(
0290: "The columns and the margins do not fit the page width.",
0291: jasperDesign);
0292: }
0293:
0294: if (jasperDesign.getTopMargin()
0295: + (jasperDesign.getBackground() != null ? jasperDesign
0296: .getBackground().getHeight() : 0)
0297: + jasperDesign.getBottomMargin() > jasperDesign
0298: .getPageHeight()) {
0299: addBrokenRule(
0300: "The background section and the margins do not fit the page height.",
0301: jasperDesign);
0302: }
0303:
0304: if (jasperDesign.isTitleNewPage()) {
0305: if (jasperDesign.getTopMargin()
0306: + (jasperDesign.getTitle() != null ? jasperDesign
0307: .getTitle().getHeight() : 0)
0308: + jasperDesign.getBottomMargin() > jasperDesign
0309: .getPageHeight()) {
0310: addBrokenRule(
0311: "The title section and the margins do not fit the page height.",
0312: jasperDesign);
0313: }
0314: } else {
0315: if (jasperDesign.getTopMargin()
0316: + (jasperDesign.getTitle() != null ? jasperDesign
0317: .getTitle().getHeight() : 0)
0318: + (jasperDesign.getPageHeader() != null ? jasperDesign
0319: .getPageHeader().getHeight()
0320: : 0)
0321: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0322: .getColumnHeader().getHeight()
0323: : 0)
0324: + (jasperDesign.getColumnFooter() != null ? jasperDesign
0325: .getColumnFooter().getHeight()
0326: : 0)
0327: + (jasperDesign.getPageFooter() != null ? jasperDesign
0328: .getPageFooter().getHeight()
0329: : 0) + jasperDesign.getBottomMargin() > jasperDesign
0330: .getPageHeight()) {
0331: addBrokenRule(
0332: "The title section, the page and column headers and footers and the margins do not fit the page height.",
0333: jasperDesign);
0334: }
0335: }
0336:
0337: if (jasperDesign.getTopMargin()
0338: + (jasperDesign.getPageHeader() != null ? jasperDesign
0339: .getPageHeader().getHeight() : 0)
0340: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0341: .getColumnHeader().getHeight()
0342: : 0)
0343: + (jasperDesign.getColumnFooter() != null ? jasperDesign
0344: .getColumnFooter().getHeight()
0345: : 0)
0346: + (jasperDesign.getPageFooter() != null ? jasperDesign
0347: .getPageFooter().getHeight() : 0)
0348: + jasperDesign.getBottomMargin() > jasperDesign
0349: .getPageHeight()) {
0350: addBrokenRule(
0351: "The page and column headers and footers and the margins do not fit the page height.",
0352: jasperDesign);
0353: }
0354:
0355: if (jasperDesign.getTopMargin()
0356: + (jasperDesign.getPageHeader() != null ? jasperDesign
0357: .getPageHeader().getHeight() : 0)
0358: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0359: .getColumnHeader().getHeight()
0360: : 0)
0361: + (jasperDesign.getColumnFooter() != null ? jasperDesign
0362: .getColumnFooter().getHeight()
0363: : 0)
0364: + (jasperDesign.getLastPageFooter() != null ? jasperDesign
0365: .getLastPageFooter().getHeight()
0366: : 0) + jasperDesign.getBottomMargin() > jasperDesign
0367: .getPageHeight()) {
0368: addBrokenRule(
0369: "The page and column headers and footers and the margins do not fit the last page height.",
0370: jasperDesign);
0371: }
0372:
0373: if (jasperDesign.getTopMargin()
0374: + (jasperDesign.getSummary() != null ? jasperDesign
0375: .getSummary().getHeight() : 0)
0376: + jasperDesign.getBottomMargin() > jasperDesign
0377: .getPageHeight()) {
0378: addBrokenRule(
0379: "The summary section and the margins do not fit the page height.",
0380: jasperDesign);
0381: }
0382:
0383: if (jasperDesign.getTopMargin()
0384: + (jasperDesign.getPageHeader() != null ? jasperDesign
0385: .getPageHeader().getHeight() : 0)
0386: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0387: .getColumnHeader().getHeight()
0388: : 0)
0389: + (jasperDesign.getDetail() != null ? jasperDesign
0390: .getDetail().getHeight() : 0)
0391: + (jasperDesign.getColumnFooter() != null ? jasperDesign
0392: .getColumnFooter().getHeight()
0393: : 0)
0394: + (jasperDesign.getPageFooter() != null ? jasperDesign
0395: .getPageFooter().getHeight() : 0)
0396: + jasperDesign.getBottomMargin() > jasperDesign
0397: .getPageHeight()) {
0398: addBrokenRule(
0399: "The detail section, the page and column headers and footers and the margins do not fit the page height.",
0400: jasperDesign);
0401: }
0402:
0403: if (jasperDesign.getTopMargin()
0404: + (jasperDesign.getNoData() != null ? jasperDesign
0405: .getNoData().getHeight() : 0)
0406: + jasperDesign.getBottomMargin() > jasperDesign
0407: .getPageHeight()) {
0408: addBrokenRule(
0409: "The noData section and the margins do not fit the page height.",
0410: jasperDesign);
0411: }
0412:
0413: verifyFormatFactoryClass();
0414: }
0415:
0416: protected void verifyFormatFactoryClass() {
0417: String formatFactoryClassName = jasperDesign
0418: .getFormatFactoryClass();
0419: if (formatFactoryClassName != null) {
0420: try {
0421: Class formatFactoryClass = JRClassLoader
0422: .loadClassForName(formatFactoryClassName);
0423: if (!FormatFactory.class
0424: .isAssignableFrom(formatFactoryClass)) {
0425: addBrokenRule(
0426: "The report format factory class is not compatible with "
0427: + FormatFactory.class.getName(),
0428: jasperDesign);
0429: }
0430: } catch (ClassNotFoundException e) {
0431: addBrokenRule(e.toString(), jasperDesign);
0432: }
0433: }
0434: }
0435:
0436: /**
0437: *
0438: */
0439: private void verifyQuery(JRDesignDataset dataset) {
0440: JRQuery query = dataset.getQuery();
0441: if (query != null) {
0442: String language = query.getLanguage();
0443: JRQueryExecuterFactory queryExecuterFactory = null;
0444: if (language == null || language.length() == 0) {
0445: addBrokenRule("Query language not set.", query);
0446: } else {
0447: try {
0448: queryExecuterFactory = JRQueryExecuterUtils
0449: .getQueryExecuterFactory(query
0450: .getLanguage());
0451: } catch (JRException e1) {
0452: addBrokenRule("Query executer factory for "
0453: + language + " cannot be created.", query);
0454: }
0455: }
0456:
0457: JRQueryChunk[] chunks = query.getChunks();
0458: if (chunks != null && chunks.length > 0) {
0459: Map parametersMap = dataset.getParametersMap();
0460:
0461: for (int j = 0; j < chunks.length; j++) {
0462: JRQueryChunk queryChunk = chunks[j];
0463: switch (queryChunk.getType()) {
0464: case JRQueryChunk.TYPE_PARAMETER: {
0465: JRParameter parameter = (JRParameter) parametersMap
0466: .get(queryChunk.getText());
0467: if (parameter == null) {
0468: addBrokenRule(
0469: "Query parameter not found : "
0470: + queryChunk.getText(),
0471: query);
0472: } else if (queryExecuterFactory != null) {
0473: String parameterType = null;
0474: try {
0475: parameterType = parameter
0476: .getValueClassName();
0477: } catch (JRRuntimeException e) {
0478: // ignore, already added when the parameter got verified
0479: }
0480: if (parameterType != null
0481: && !queryExecuterFactory
0482: .supportsQueryParameterType(parameterType)) {
0483: addBrokenRule(
0484: "Parameter type not supported in query : "
0485: + queryChunk.getText()
0486: + " class "
0487: + parameterType, query);
0488: }
0489: }
0490:
0491: break;
0492: }
0493: case JRQueryChunk.TYPE_PARAMETER_CLAUSE: {
0494: if (!parametersMap.containsKey(queryChunk
0495: .getText())) {
0496: addBrokenRule(
0497: "Query parameter not found : "
0498: + queryChunk.getText(),
0499: query);
0500: }
0501: break;
0502: }
0503: case JRQueryChunk.TYPE_TEXT:
0504: default: {
0505: }
0506: }
0507: }
0508: }
0509: }
0510: }
0511:
0512: /**
0513: *
0514: */
0515: private void verifyExpressions(List expressions, Map parametersMap,
0516: Map fieldsMap, Map variablesMap) {
0517: if (expressions != null && expressions.size() > 0) {
0518: for (Iterator it = expressions.iterator(); it.hasNext();) {
0519: JRExpression expression = (JRExpression) it.next();
0520: JRExpressionChunk[] chunks = expression.getChunks();
0521: if (chunks != null && chunks.length > 0) {
0522: for (int j = 0; j < chunks.length; j++) {
0523: JRExpressionChunk expressionChunk = chunks[j];
0524: switch (expressionChunk.getType()) {
0525: case JRExpressionChunk.TYPE_VARIABLE: {
0526: if (!variablesMap
0527: .containsKey(expressionChunk
0528: .getText())) {
0529: addBrokenRule("Variable not found : "
0530: + expressionChunk.getText(),
0531: expression);
0532: }
0533: break;
0534: }
0535: case JRExpressionChunk.TYPE_FIELD: {
0536: if (!fieldsMap.containsKey(expressionChunk
0537: .getText())) {
0538: addBrokenRule("Field not found : "
0539: + expressionChunk.getText(),
0540: expression);
0541: }
0542: break;
0543: }
0544: case JRExpressionChunk.TYPE_PARAMETER: {
0545: if (!parametersMap
0546: .containsKey(expressionChunk
0547: .getText())) {
0548: addBrokenRule("Parameter not found : "
0549: + expressionChunk.getText(),
0550: expression);
0551: }
0552: break;
0553: }
0554: case JRExpressionChunk.TYPE_RESOURCE:
0555: case JRExpressionChunk.TYPE_TEXT:
0556: default: {
0557: }
0558: }
0559: }
0560: }
0561: }
0562: }
0563: }
0564:
0565: private void verifyExpressions(JRDesignDataset dataset) {
0566: verifyExpressions(expressionCollector.getExpressions(dataset),
0567: dataset.getParametersMap(), dataset.getFieldsMap(),
0568: dataset.getVariablesMap());
0569: }
0570:
0571: /**
0572: *
0573: */
0574: private void verifyReportFonts() {
0575: JRReportFont[] fonts = jasperDesign.getFonts();
0576: if (fonts != null && fonts.length > 0) {
0577: for (int index = 0; index < fonts.length; index++) {
0578: JRReportFont font = fonts[index];
0579:
0580: if (font.getName() == null
0581: || font.getName().trim().length() == 0) {
0582: addBrokenRule("Report font name missing.", font);
0583: }
0584: }
0585: }
0586: }
0587:
0588: protected void verifyReportTemplates() {
0589: JRReportTemplate[] templates = jasperDesign.getTemplates();
0590: if (templates != null) {
0591: for (int i = 0; i < templates.length; i++) {
0592: JRReportTemplate template = templates[i];
0593: verifyTemplate(template);
0594: }
0595: }
0596: }
0597:
0598: protected void verifyTemplate(JRReportTemplate template) {
0599: JRExpression sourceExpression = template.getSourceExpression();
0600: if (sourceExpression == null) {
0601: addBrokenRule("Template source expression missing.",
0602: template);
0603: } else {
0604: try {
0605: Class valueClass = sourceExpression.getValueClass();
0606: if (valueClass == null) {
0607: addBrokenRule(
0608: "Template source expression value class not set.",
0609: sourceExpression);
0610: } else if (!verifyTemplateSourceType(valueClass)) {
0611: addBrokenRule(
0612: "Template source expression value class "
0613: + valueClass.getName()
0614: + "not supported.",
0615: sourceExpression);
0616: }
0617: } catch (JRRuntimeException e) {
0618: addBrokenRule(e, sourceExpression);
0619: }
0620: }
0621: }
0622:
0623: protected boolean verifyTemplateSourceType(Class valueClass) {
0624: boolean valid = false;
0625: for (int i = 0; i < templateTypes.length; i++) {
0626: Class type = templateTypes[i];
0627: if (type.isAssignableFrom(valueClass)) {
0628: valid = true;
0629: break;
0630: }
0631: }
0632: return valid;
0633: }
0634:
0635: /**
0636: *
0637: */
0638: private void verifyStyles() {
0639: JRStyle[] styles = jasperDesign.getStyles();
0640: if (styles != null && styles.length > 0) {
0641: for (int index = 0; index < styles.length; index++) {
0642: JRStyle style = styles[index];
0643:
0644: if (style.getName() == null
0645: || style.getName().trim().length() == 0) {
0646: addBrokenRule("Report style name missing.", style);
0647: }
0648: }
0649: }
0650: }
0651:
0652: /**
0653: *
0654: */
0655: private void verifyParameters(JRDesignDataset dataset) {
0656: JRParameter[] parameters = dataset.getParameters();
0657: if (parameters != null && parameters.length > 0) {
0658: for (int index = 0; index < parameters.length; index++) {
0659: JRParameter parameter = parameters[index];
0660:
0661: Object errorSource = parameter;
0662: if (parameter.isSystemDefined()) {
0663: errorSource = jasperDesign;
0664: }
0665:
0666: if (parameter.getName() == null
0667: || parameter.getName().trim().length() == 0) {
0668: addBrokenRule("Parameter name missing.",
0669: errorSource);
0670: }
0671:
0672: if (parameter.getValueClassName() == null) {
0673: addBrokenRule("Class not set for parameter : "
0674: + parameter.getName(), errorSource);
0675: } else {
0676: try {
0677: Class parameterType = parameter.getValueClass();
0678: JRExpression expression = parameter
0679: .getDefaultValueExpression();
0680: if (expression != null) {
0681: try {
0682: if (expression.getValueClass() == null) {
0683: addBrokenRule(
0684: "No value class defined for the expression in parameter: "
0685: + parameter
0686: .getName(),
0687: expression);
0688: } else {
0689: if (!parameterType
0690: .isAssignableFrom(expression
0691: .getValueClass())) {
0692: addBrokenRule(
0693: "The parameter default value expression class is not compatible with the parameter's class : "
0694: + parameter
0695: .getName(),
0696: expression);
0697: }
0698: }
0699: } catch (JRRuntimeException e) {
0700: addBrokenRule(e, expression);
0701: }
0702: }
0703: } catch (JRRuntimeException e) {
0704: addBrokenRule(e, errorSource);
0705: }
0706: }
0707: }
0708: }
0709: }
0710:
0711: /**
0712: *
0713: */
0714: private void verifyFields(JRDesignDataset dataset) {
0715: JRField[] fields = dataset.getFields();
0716: if (fields != null && fields.length > 0) {
0717: for (int index = 0; index < fields.length; index++) {
0718: JRField field = fields[index];
0719:
0720: if (field.getName() == null
0721: || field.getName().trim().length() == 0) {
0722: addBrokenRule("Field name missing.", field);
0723: }
0724:
0725: try {
0726: Class fieldType = field.getValueClass();
0727: if (fieldType == null) {
0728: addBrokenRule("Class not set for field : "
0729: + field.getName(), field);
0730: }
0731: } catch (JRRuntimeException e) {
0732: addBrokenRule(e, field);
0733: }
0734: }
0735: }
0736: }
0737:
0738: /**
0739: *
0740: */
0741: private void verifySortFields(JRDesignDataset dataset) {
0742: JRField[] fields = dataset.getFields();
0743: JRSortField[] sortFields = dataset.getSortFields();
0744: if (sortFields != null && sortFields.length > 0) {
0745: for (int index = 0; index < sortFields.length; index++) {
0746: JRSortField sortField = sortFields[index];
0747: String sortFieldName = sortField.getName();
0748:
0749: if (sortFieldName == null
0750: || sortFieldName.trim().length() == 0) {
0751: addBrokenRule("Sort field name missing.", sortField);
0752: } else {
0753: boolean isFound = false;
0754:
0755: int j = 0;
0756: while (!isFound && j < fields.length) {
0757: isFound = sortFieldName.equals(fields[j]
0758: .getName());
0759: j++;
0760: }
0761:
0762: if (!isFound) {
0763: addBrokenRule("Sort field \"" + sortFieldName
0764: + "\" not declared.", sortField);
0765: }
0766: }
0767: }
0768: }
0769: }
0770:
0771: /**
0772: *
0773: */
0774: private void verifyVariables(JRDesignDataset dataset)
0775: throws JRRuntimeException {
0776: JRVariable[] variables = dataset.getVariables();
0777: if (variables != null && variables.length > 0) {
0778: boolean isMainDataset = dataset.isMainDataset();
0779: for (int index = 0; index < variables.length; index++) {
0780: JRVariable variable = variables[index];
0781:
0782: if (variable.getName() == null
0783: || variable.getName().trim().length() == 0) {
0784: addBrokenRule("Variable name missing.", variable);
0785: }
0786:
0787: try {
0788: Class valueClass = variable.getValueClass();
0789: if (valueClass == null) {
0790: addBrokenRule("Class not set for variable : "
0791: + variable.getName(), variable);
0792: } else {
0793: JRExpression expression = variable
0794: .getExpression();
0795: if (expression != null) {
0796: try {
0797: if (expression.getValueClass() == null) {
0798: addBrokenRule(
0799: "No value class for the expression has been set in variable: "
0800: + variable
0801: .getName(),
0802: expression);
0803: } else {
0804: if (variable.getCalculation() != JRVariable.CALCULATION_COUNT
0805: && variable
0806: .getCalculation() != JRVariable.CALCULATION_DISTINCT_COUNT
0807: && variable
0808: .getCalculation() != JRVariable.CALCULATION_SYSTEM
0809: && !valueClass
0810: .isAssignableFrom(expression
0811: .getValueClass())) {
0812: addBrokenRule(
0813: "The variable expression class is not compatible with the variable's class : "
0814: + variable
0815: .getName(),
0816: expression);
0817: }
0818: }
0819: } catch (JRRuntimeException e) {
0820: addBrokenRule(e, expression);
0821: }
0822: }
0823:
0824: if (variable.getInitialValueExpression() != null) {
0825: try {
0826: if (!valueClass
0827: .isAssignableFrom(variable
0828: .getInitialValueExpression()
0829: .getValueClass())) {
0830: addBrokenRule(
0831: "The initial value class is not compatible with the variable's class : "
0832: + variable
0833: .getName(),
0834: variable
0835: .getInitialValueExpression());
0836: }
0837: } catch (JRRuntimeException e) {
0838: addBrokenRule(e, variable
0839: .getInitialValueExpression());
0840: }
0841: }
0842: }
0843: } catch (JRRuntimeException e) {
0844: addBrokenRule(e, variable);
0845: }
0846:
0847: byte resetType = variable.getResetType();
0848: if (resetType == JRVariable.RESET_TYPE_GROUP) {
0849: if (variable.getResetGroup() == null) {
0850: addBrokenRule(
0851: "Reset group missing for variable : "
0852: + variable.getName(), variable);
0853: } else {
0854: Map groupsMap = dataset.getGroupsMap();
0855:
0856: if (!groupsMap.containsKey(variable
0857: .getResetGroup().getName())) {
0858: addBrokenRule("Reset group \""
0859: + variable.getResetGroup()
0860: .getName()
0861: + "\" not found for variable : "
0862: + variable.getName(), variable);
0863: }
0864: }
0865: }
0866:
0867: byte incrementType = variable.getIncrementType();
0868: if (incrementType == JRVariable.RESET_TYPE_GROUP) {
0869: if (variable.getIncrementGroup() == null) {
0870: addBrokenRule(
0871: "Increment group missing for variable : "
0872: + variable.getName(), variable);
0873: } else {
0874: Map groupsMap = dataset.getGroupsMap();
0875:
0876: if (!groupsMap.containsKey(variable
0877: .getIncrementGroup().getName())) {
0878: addBrokenRule("Increment group \""
0879: + variable.getIncrementGroup()
0880: .getName()
0881: + "\" not found for variable : "
0882: + variable.getName(), variable);
0883: }
0884: }
0885: }
0886:
0887: if (!isMainDataset) {
0888: if (resetType == JRVariable.RESET_TYPE_COLUMN
0889: || resetType == JRVariable.RESET_TYPE_PAGE) {
0890: addBrokenRule(
0891: "Variable "
0892: + variable.getName()
0893: + " of dataset "
0894: + dataset.getName()
0895: + " cannot have Column or Page reset type.",
0896: variable);
0897: }
0898:
0899: if (incrementType == JRVariable.RESET_TYPE_COLUMN
0900: || incrementType == JRVariable.RESET_TYPE_PAGE) {
0901: addBrokenRule(
0902: "Variable "
0903: + variable.getName()
0904: + " of dataset "
0905: + dataset.getName()
0906: + " cannot have Column or Page increment type.",
0907: variable);
0908: }
0909: }
0910: }
0911: }
0912: }
0913:
0914: /**
0915: *
0916: */
0917: private void verifyGroups(JRDesignDataset dataset) {
0918: JRGroup[] groups = dataset.getGroups();
0919: if (groups != null && groups.length > 0) {
0920: boolean isMainDataset = dataset.isMainDataset();
0921: for (int index = 0; index < groups.length; index++) {
0922: JRGroup group = groups[index];
0923:
0924: if (group.getName() == null
0925: || group.getName().trim().length() == 0) {
0926: addBrokenRule("Group name missing.", group);
0927: }
0928:
0929: if (isMainDataset) {
0930: verifyGroupHeaderAndFooter(group);
0931: } else {
0932: if (group.getGroupHeader() != null
0933: || group.getGroupFooter() != null) {
0934: addBrokenRule(
0935: "Group "
0936: + group.getName()
0937: + " cannot have header or footer sections.",
0938: group);
0939: }
0940: }
0941:
0942: JRExpression expression = group.getExpression();
0943:
0944: if (expression != null) {
0945: try {
0946: Class clazz = expression.getValueClass();
0947: if (clazz == null) {
0948: addBrokenRule(
0949: "Class not set for group expression : "
0950: + group.getName(),
0951: expression);
0952: }
0953: } catch (JRRuntimeException e) {
0954: addBrokenRule(e, expression);
0955: }
0956: }
0957:
0958: if (isMainDataset) {
0959: verifyBand(group.getGroupHeader());
0960: verifyBand(group.getGroupFooter());
0961: }
0962: }
0963: }
0964: }
0965:
0966: private void verifyGroupHeaderAndFooter(JRGroup group) {
0967: if (jasperDesign.isTitleNewPage()) {
0968: if (jasperDesign.getTopMargin()
0969: + (jasperDesign.getPageHeader() != null ? jasperDesign
0970: .getPageHeader().getHeight()
0971: : 0)
0972: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0973: .getColumnHeader().getHeight()
0974: : 0)
0975: + (group.getGroupHeader() != null ? group
0976: .getGroupHeader().getHeight() : 0)
0977: + (jasperDesign.getColumnFooter() != null ? jasperDesign
0978: .getColumnFooter().getHeight()
0979: : 0)
0980: + (jasperDesign.getPageFooter() != null ? jasperDesign
0981: .getPageFooter().getHeight()
0982: : 0) + jasperDesign.getBottomMargin() > jasperDesign
0983: .getPageHeight()) {
0984: addBrokenRule(
0985: "The '"
0986: + group.getName()
0987: + "' group header section, the page and column headers and footers and the margins do not fit the page height.",
0988: group.getGroupHeader());
0989: }
0990:
0991: if (jasperDesign.getTopMargin()
0992: + (jasperDesign.getPageHeader() != null ? jasperDesign
0993: .getPageHeader().getHeight()
0994: : 0)
0995: + (jasperDesign.getColumnHeader() != null ? jasperDesign
0996: .getColumnHeader().getHeight()
0997: : 0)
0998: + (group.getGroupFooter() != null ? group
0999: .getGroupFooter().getHeight() : 0)
1000: + (jasperDesign.getColumnFooter() != null ? jasperDesign
1001: .getColumnFooter().getHeight()
1002: : 0)
1003: + (jasperDesign.getPageFooter() != null ? jasperDesign
1004: .getPageFooter().getHeight()
1005: : 0) + jasperDesign.getBottomMargin() > jasperDesign
1006: .getPageHeight()) {
1007: addBrokenRule(
1008: "The '"
1009: + group.getName()
1010: + "' group footer section, the page and column headers and footers and the margins do not fit the page height.",
1011: group.getGroupFooter());
1012: }
1013: } else {
1014: if (jasperDesign.getTopMargin()
1015: + (jasperDesign.getTitle() != null ? jasperDesign
1016: .getTitle().getHeight() : 0)
1017: + (jasperDesign.getPageHeader() != null ? jasperDesign
1018: .getPageHeader().getHeight()
1019: : 0)
1020: + (jasperDesign.getColumnHeader() != null ? jasperDesign
1021: .getColumnHeader().getHeight()
1022: : 0)
1023: + (group.getGroupHeader() != null ? group
1024: .getGroupHeader().getHeight() : 0)
1025: + (jasperDesign.getColumnFooter() != null ? jasperDesign
1026: .getColumnFooter().getHeight()
1027: : 0)
1028: + (jasperDesign.getPageFooter() != null ? jasperDesign
1029: .getPageFooter().getHeight()
1030: : 0) + jasperDesign.getBottomMargin() > jasperDesign
1031: .getPageHeight()) {
1032: addBrokenRule(
1033: "The '"
1034: + group.getName()
1035: + "' group header section, the title, the page and column headers and footers and the margins do not fit the first page height.",
1036: group.getGroupHeader());
1037: }
1038:
1039: if (jasperDesign.getTopMargin()
1040: + (jasperDesign.getTitle() != null ? jasperDesign
1041: .getTitle().getHeight() : 0)
1042: + (jasperDesign.getPageHeader() != null ? jasperDesign
1043: .getPageHeader().getHeight()
1044: : 0)
1045: + (jasperDesign.getColumnHeader() != null ? jasperDesign
1046: .getColumnHeader().getHeight()
1047: : 0)
1048: + (group.getGroupFooter() != null ? group
1049: .getGroupFooter().getHeight() : 0)
1050: + (jasperDesign.getColumnFooter() != null ? jasperDesign
1051: .getColumnFooter().getHeight()
1052: : 0)
1053: + (jasperDesign.getPageFooter() != null ? jasperDesign
1054: .getPageFooter().getHeight()
1055: : 0) + jasperDesign.getBottomMargin() > jasperDesign
1056: .getPageHeight()) {
1057: addBrokenRule(
1058: "The '"
1059: + group.getName()
1060: + "' group footer section, the title, the page and column headers and footers and the margins do not fit the first page height.",
1061: group.getGroupFooter());
1062: }
1063: }
1064: }
1065:
1066: /**
1067: *
1068: */
1069: private void verifyBand(JRBand band) {
1070: if (band != null) {
1071: JRElement[] elements = band.getElements();
1072: if (elements != null && elements.length > 0) {
1073: JRExpression expression = band.getPrintWhenExpression();
1074:
1075: if (expression != null) {
1076: try {
1077: Class clazz = expression.getValueClass();
1078: if (clazz == null) {
1079: addBrokenRule(
1080: "Class not set for band \"print when\" expression.",
1081: expression);
1082: } else if (!java.lang.Boolean.class
1083: .isAssignableFrom(clazz)) {
1084: addBrokenRule(
1085: "Class "
1086: + clazz
1087: + " not supported for band \"print when\" expression. Use java.lang.Boolean instead.",
1088: expression);
1089: }
1090: } catch (JRRuntimeException e) {
1091: addBrokenRule(e, expression);
1092: }
1093: }
1094:
1095: for (int index = 0; index < elements.length; index++) {
1096: JRElement element = elements[index];
1097:
1098: verifyPrintWhenExpr(element);
1099:
1100: /*
1101: if (element.getY() < 0)
1102: {
1103: System.out.println(
1104: "Warning : Element placed outside band area : y=" + element.getY()
1105: );
1106: //addBrokenRule("Element placed outside band area.");
1107: }
1108: else if (element.getY() + element.getHeight() > band.getHeight())
1109: */
1110: if (element.getY() + element.getHeight() > band
1111: .getHeight()) {
1112: // if (log.isWarnEnabled())
1113: // log.warn(
1114: // "Warning : Element bottom reaches outside band area : y=" + element.getY() +
1115: // " height=" + element.getHeight() +
1116: // " band-height=" + band.getHeight()
1117: // );
1118: addBrokenRule(
1119: "Warning : Element bottom reaches outside band area : y="
1120: + element.getY() + " height="
1121: + element.getHeight()
1122: + " band-height="
1123: + band.getHeight(), element);
1124: }
1125:
1126: verifyElement(element);
1127: }
1128: }
1129: }
1130: }
1131:
1132: protected void verifyElement(JRElement element) {
1133: if (element instanceof JRStaticText) {
1134: verifyStaticText((JRStaticText) element);
1135: } else if (element instanceof JRTextField) {
1136: verifyTextField((JRTextField) element);
1137: } else if (element instanceof JRImage) {
1138: verifyImage((JRImage) element);
1139: } else if (element instanceof JRSubreport) {
1140: verifySubreport((JRSubreport) element);
1141: } else if (element instanceof JRCrosstab) {
1142: verifyCrosstab((JRDesignCrosstab) element);
1143: } else if (element instanceof JRChart) {
1144: verifyChart((JRChart) element);
1145: } else if (element instanceof JRFrame) {
1146: verifyFrame((JRFrame) element);
1147: }
1148: }
1149:
1150: private void verifyPrintWhenExpr(JRElement element) {
1151: JRExpression expression;
1152: expression = element.getPrintWhenExpression();
1153:
1154: if (expression != null) {
1155: try {
1156: Class clazz = expression.getValueClass();
1157: if (clazz == null) {
1158: addBrokenRule(
1159: "Class not set for element \"print when\" expression.",
1160: expression);
1161: } else if (!java.lang.Boolean.class
1162: .isAssignableFrom(clazz)) {
1163: addBrokenRule(
1164: "Class "
1165: + clazz
1166: + " not supported for element \"print when\" expression. Use java.lang.Boolean instead.",
1167: expression);
1168: }
1169: } catch (JRRuntimeException e) {
1170: addBrokenRule(e, expression);
1171: }
1172: }
1173: }
1174:
1175: /**
1176: *
1177: */
1178: private void verifyStaticText(JRStaticText staticText) {
1179: verifyFont(staticText);
1180: }
1181:
1182: /**
1183: *
1184: */
1185: private void verifyTextField(JRTextField textField) {
1186: verifyFont(textField);
1187: verifyAnchor(textField);
1188: verifyHyperlink(textField);
1189:
1190: if (textField != null) {
1191: JRExpression expression = textField.getExpression();
1192:
1193: if (expression != null) {
1194: try {
1195: String className = expression.getValueClassName();
1196: if (className == null) {
1197: addBrokenRule(
1198: "Class not set for text field expression.",
1199: expression);
1200: } else if (Arrays.binarySearch(
1201: getTextFieldClassNames(), className) < 0) {
1202: addBrokenRule(
1203: "Class \""
1204: + className
1205: + "\" not supported for text field expression.",
1206: expression);
1207: }
1208: } catch (JRRuntimeException e) {
1209: addBrokenRule(e, expression);
1210: }
1211: }
1212: }
1213: }
1214:
1215: /**
1216: *
1217: */
1218: private void verifyFont(JRFont font) {
1219: JRReportFont reportFont = font.getReportFont();
1220:
1221: if (reportFont != null && reportFont.getName() != null) {
1222: Map fontsMap = jasperDesign.getFontsMap();
1223:
1224: if (!fontsMap.containsKey(reportFont.getName())) {
1225: addBrokenRule("Report font not found : "
1226: + reportFont.getName(), font);
1227: }
1228: }
1229: }
1230:
1231: /**
1232: *
1233: */
1234: private void verifyAnchor(JRAnchor anchor) {
1235: if (anchor != null) {
1236: JRExpression expression = anchor.getAnchorNameExpression();
1237:
1238: if (expression != null) {
1239: try {
1240: Class clazz = expression.getValueClass();
1241: if (clazz == null) {
1242: addBrokenRule(
1243: "Class not set for anchor name expression.",
1244: expression);
1245: } else if (!java.lang.String.class
1246: .isAssignableFrom(clazz)) {
1247: addBrokenRule(
1248: "Class "
1249: + clazz
1250: + " not supported for anchor name expression. Use java.lang.String instead.",
1251: expression);
1252: }
1253: } catch (JRRuntimeException e) {
1254: addBrokenRule(e, expression);
1255: }
1256: }
1257:
1258: if (anchor.getBookmarkLevel() != JRAnchor.NO_BOOKMARK
1259: && anchor.getBookmarkLevel() < 1) {
1260: addBrokenRule("Bookmark level should be "
1261: + JRAnchor.NO_BOOKMARK + " or greater than 0",
1262: anchor);
1263: }
1264: }
1265: }
1266:
1267: /**
1268: *
1269: */
1270: private void verifyHyperlink(JRHyperlink hyperlink) {
1271: if (hyperlink != null) {
1272: JRExpression expression = hyperlink
1273: .getHyperlinkReferenceExpression();
1274:
1275: if (expression != null) {
1276: try {
1277: Class clazz = expression.getValueClass();
1278: if (clazz == null) {
1279: addBrokenRule(
1280: "Class not set for hyperlink reference expression.",
1281: expression);
1282: } else if (!java.lang.String.class
1283: .isAssignableFrom(clazz)) {
1284: addBrokenRule(
1285: "Class "
1286: + clazz
1287: + " not supported for hyperlink reference expression. Use java.lang.String instead.",
1288: expression);
1289: }
1290: } catch (JRRuntimeException e) {
1291: addBrokenRule(e, expression);
1292: }
1293: }
1294:
1295: expression = hyperlink.getHyperlinkAnchorExpression();
1296:
1297: if (expression != null) {
1298: try {
1299: Class clazz = expression.getValueClass();
1300: if (clazz == null) {
1301: addBrokenRule(
1302: "Class not set for hyperlink anchor expression.",
1303: expression);
1304: } else if (!java.lang.String.class
1305: .isAssignableFrom(clazz)) {
1306: addBrokenRule(
1307: "Class "
1308: + clazz
1309: + " not supported for hyperlink anchor expression. Use java.lang.String instead.",
1310: expression);
1311: }
1312: } catch (JRRuntimeException e) {
1313: addBrokenRule(e, expression);
1314: }
1315: }
1316:
1317: expression = hyperlink.getHyperlinkPageExpression();
1318:
1319: if (expression != null) {
1320: try {
1321: Class clazz = expression.getValueClass();
1322: if (clazz == null) {
1323: addBrokenRule(
1324: "Class not set for hyperlink page expression.",
1325: expression);
1326: } else if (!java.lang.Integer.class
1327: .isAssignableFrom(clazz)) {
1328: addBrokenRule(
1329: "Class "
1330: + clazz
1331: + " not supported for hyperlink page expression. Use java.lang.Integer instead.",
1332: expression);
1333: }
1334: } catch (JRRuntimeException e) {
1335: addBrokenRule(e, expression);
1336: }
1337: }
1338:
1339: expression = hyperlink.getHyperlinkTooltipExpression();
1340:
1341: if (expression != null) {
1342: try {
1343: Class clazz = expression.getValueClass();
1344: if (clazz == null) {
1345: addBrokenRule(
1346: "Class not set for hyperlink tooltip expression.",
1347: expression);
1348: } else if (!java.lang.String.class
1349: .isAssignableFrom(clazz)) {
1350: addBrokenRule(
1351: "Class "
1352: + clazz
1353: + " not supported for hyperlink tooltip expression. Use java.lang.String instead.",
1354: expression);
1355: }
1356: } catch (JRRuntimeException e) {
1357: addBrokenRule(e, expression);
1358: }
1359: }
1360:
1361: JRHyperlinkParameter[] parameters = hyperlink
1362: .getHyperlinkParameters();
1363: if (parameters != null) {
1364: for (int i = 0; i < parameters.length; i++) {
1365: JRHyperlinkParameter parameter = parameters[i];
1366: verifyHyperlinkParameter(parameter);
1367: }
1368: }
1369: }
1370: }
1371:
1372: protected void verifyHyperlinkParameter(
1373: JRHyperlinkParameter parameter) {
1374: if (parameter != null) {
1375: String name = parameter.getName();
1376: if (name == null || name.length() == 0) {
1377: addBrokenRule("Hyperlink parameter name missing.",
1378: parameter);
1379: }
1380: }
1381: }
1382:
1383: /**
1384: *
1385: */
1386: private void verifyImage(JRImage image) {
1387: verifyAnchor(image);
1388: verifyHyperlink(image);
1389:
1390: if (image != null) {
1391: JRExpression expression = image.getExpression();
1392:
1393: if (expression != null) {
1394: try {
1395: String className = expression.getValueClassName();
1396: if (className == null) {
1397: addBrokenRule(
1398: "Class not set for image expression.",
1399: expression);
1400: } else if (Arrays.binarySearch(
1401: getImageClassNames(), className) < 0) {
1402: addBrokenRule(
1403: "Class \""
1404: + className
1405: + "\" not supported for image expression.",
1406: expression);
1407: }
1408: } catch (JRRuntimeException e) {
1409: addBrokenRule(e, expression);
1410: }
1411: }
1412: }
1413: }
1414:
1415: /**
1416: *
1417: */
1418: private void verifySubreport(JRSubreport subreport) {
1419: if (subreport != null) {
1420: JRExpression expression = subreport.getExpression();
1421:
1422: if (expression != null) {
1423: try {
1424: String className = expression.getValueClassName();
1425: if (className == null) {
1426: addBrokenRule(
1427: "Class not set for subreport expression.",
1428: expression);
1429: } else if (Arrays.binarySearch(
1430: getSubreportClassNames(), className) < 0) {
1431: addBrokenRule(
1432: "Class \""
1433: + className
1434: + "\" not supported for subreport expression.",
1435: expression);
1436: }
1437: } catch (JRRuntimeException e) {
1438: addBrokenRule(e, expression);
1439: }
1440: }
1441:
1442: expression = subreport.getParametersMapExpression();
1443:
1444: if (expression != null) {
1445: try {
1446: Class clazz = expression.getValueClass();
1447: if (clazz == null) {
1448: addBrokenRule(
1449: "Class not set for subreport parameters map expression.",
1450: expression);
1451: } else if (!java.util.Map.class
1452: .isAssignableFrom(clazz)) {
1453: addBrokenRule(
1454: "Class "
1455: + clazz
1456: + " not supported for subreport parameters map expression. Use java.util.Map instead.",
1457: expression);
1458: }
1459: } catch (JRRuntimeException e) {
1460: addBrokenRule(e, expression);
1461: }
1462: }
1463:
1464: JRSubreportParameter[] parameters = subreport
1465: .getParameters();
1466: if (parameters != null && parameters.length > 0) {
1467: for (int index = 0; index < parameters.length; index++) {
1468: JRSubreportParameter parameter = parameters[index];
1469:
1470: if (parameter.getName() == null
1471: || parameter.getName().trim().length() == 0) {
1472: addBrokenRule(
1473: "Subreport parameter name missing.",
1474: expression);
1475: }
1476:
1477: expression = parameter.getExpression();
1478:
1479: if (expression != null) {
1480: try {
1481: Class clazz = expression.getValueClass();
1482: if (clazz == null) {
1483: addBrokenRule(
1484: "Class not set for subreport parameter expression : "
1485: + parameter.getName()
1486: + ". Use java.lang.Object class.",
1487: expression);
1488: }
1489: } catch (JRRuntimeException e) {
1490: addBrokenRule(e, expression);
1491: }
1492: }
1493: }
1494: }
1495:
1496: if (subreport.getConnectionExpression() != null
1497: && subreport.getDataSourceExpression() != null) {
1498: addBrokenRule(
1499: "Subreport cannot have both connection expresion and data source expression.",
1500: subreport);
1501: }
1502:
1503: expression = subreport.getConnectionExpression();
1504:
1505: if (expression != null) {
1506: try {
1507: Class clazz = expression.getValueClass();
1508: if (clazz == null) {
1509: addBrokenRule(
1510: "Class not set for subreport connection expression.",
1511: expression);
1512: } else if (!java.sql.Connection.class
1513: .isAssignableFrom(clazz)) {
1514: addBrokenRule(
1515: "Class "
1516: + clazz
1517: + " not supported for subreport connection expression. Use java.sql.Connection instead.",
1518: expression);
1519: }
1520: } catch (JRRuntimeException e) {
1521: addBrokenRule(e, expression);
1522: }
1523: }
1524:
1525: expression = subreport.getDataSourceExpression();
1526:
1527: if (expression != null) {
1528: try {
1529: Class clazz = expression.getValueClass();
1530: if (clazz == null) {
1531: addBrokenRule(
1532: "Class not set for subreport data source expression.",
1533: expression);
1534: } else if (!net.sf.jasperreports.engine.JRDataSource.class
1535: .isAssignableFrom(clazz)) {
1536: addBrokenRule(
1537: "Class "
1538: + clazz
1539: + " not supported for subreport data source expression. Use net.sf.jasperreports.engine.JRDataSource instead.",
1540: expression);
1541: }
1542: } catch (JRRuntimeException e) {
1543: addBrokenRule(e, expression);
1544: }
1545: }
1546:
1547: JRSubreportReturnValue[] returnValues = subreport
1548: .getReturnValues();
1549: if (returnValues != null && returnValues.length > 0) {
1550: for (int i = 0; i < returnValues.length; i++) {
1551: JRSubreportReturnValue returnValue = returnValues[i];
1552:
1553: if (returnValue.getSubreportVariable() == null
1554: || returnValue.getSubreportVariable()
1555: .trim().length() == 0) {
1556: addBrokenRule(
1557: "Subreport return value variable name missing.",
1558: returnValue);
1559: }
1560:
1561: if (returnValue.getToVariable() == null
1562: || returnValue.getToVariable().trim()
1563: .length() == 0) {
1564: addBrokenRule(
1565: "Subreport return value to variable name missing.",
1566: returnValue);
1567: }
1568:
1569: if (!jasperDesign.getVariablesMap().containsKey(
1570: returnValue.getToVariable())) {
1571: addBrokenRule(
1572: "Subreport return value to variable not found.",
1573: returnValue);
1574: }
1575: }
1576: }
1577: }
1578: }
1579:
1580: /**
1581: *
1582: */
1583: private static synchronized String[] getTextFieldClassNames() {
1584: if (textFieldClassNames == null) {
1585: textFieldClassNames = new String[] {
1586: java.lang.Boolean.class.getName(),
1587: java.lang.Byte.class.getName(),
1588: java.util.Date.class.getName(),
1589: java.sql.Timestamp.class.getName(),
1590: java.sql.Time.class.getName(),
1591: java.lang.Double.class.getName(),
1592: java.lang.Float.class.getName(),
1593: java.lang.Integer.class.getName(),
1594: java.lang.Long.class.getName(),
1595: java.lang.Short.class.getName(),
1596: java.math.BigDecimal.class.getName(),
1597: java.lang.Number.class.getName(),
1598: java.lang.String.class.getName() };
1599:
1600: Arrays.sort(textFieldClassNames);
1601: }
1602:
1603: return textFieldClassNames;
1604: }
1605:
1606: /**
1607: *
1608: */
1609: private static synchronized String[] getImageClassNames() {
1610: if (imageClassNames == null) {
1611: imageClassNames = new String[] {
1612: java.lang.String.class.getName(),
1613: java.io.File.class.getName(),
1614: java.net.URL.class.getName(),
1615: java.io.InputStream.class.getName(),
1616: java.awt.Image.class.getName(),
1617: net.sf.jasperreports.engine.JRRenderable.class
1618: .getName() };
1619:
1620: Arrays.sort(imageClassNames);
1621: }
1622:
1623: return imageClassNames;
1624: }
1625:
1626: /**
1627: *
1628: */
1629: private static synchronized String[] getSubreportClassNames() {
1630: if (subreportClassNames == null) {
1631: subreportClassNames = new String[] {
1632: java.lang.String.class.getName(),
1633: java.io.File.class.getName(),
1634: java.net.URL.class.getName(),
1635: java.io.InputStream.class.getName(),
1636: net.sf.jasperreports.engine.JasperReport.class
1637: .getName() };
1638:
1639: Arrays.sort(subreportClassNames);
1640: }
1641:
1642: return subreportClassNames;
1643: }
1644:
1645: private void verifyCrosstab(JRDesignCrosstab crosstab) {
1646: verifyParameters(crosstab);
1647:
1648: JRCrosstabDataset dataset = crosstab.getDataset();
1649: if (dataset == null) {
1650: addBrokenRule("Crosstab dataset missing.", crosstab);
1651: } else {
1652: verifyElementDataset(dataset);
1653: }
1654:
1655: verifyCellContents(crosstab.getHeaderCell(), "crosstab cell");
1656:
1657: JRCrosstabRowGroup[] rowGroups = crosstab.getRowGroups();
1658: if (rowGroups == null || rowGroups.length == 0) {
1659: addBrokenRule(
1660: "Crosstab should have at least one row group.",
1661: crosstab);
1662: } else {
1663: for (int i = 0; i < rowGroups.length; i++) {
1664: verifyCrosstabRowGroup(rowGroups[i]);
1665: }
1666: }
1667:
1668: JRCrosstabColumnGroup[] colGroups = crosstab.getColumnGroups();
1669: if (colGroups == null || colGroups.length == 0) {
1670: addBrokenRule(
1671: "Crosstab should have at least one column group.",
1672: crosstab);
1673: } else {
1674: for (int i = 0; i < colGroups.length; i++) {
1675: verifyCrosstabColumnGroup(colGroups[i]);
1676: }
1677: }
1678:
1679: JRCrosstabMeasure[] measures = crosstab.getMeasures();
1680: if (measures == null || measures.length == 0) {
1681: addBrokenRule("Crosstab should have at least one measure.",
1682: crosstab);
1683: } else {
1684: for (int i = 0; i < measures.length; i++) {
1685: verifyCrosstabMeasure(measures[i]);
1686: }
1687: }
1688:
1689: verifyCrosstabCells(crosstab);
1690:
1691: verifyCellContents(crosstab.getWhenNoDataCell(),
1692: "when no data cell");
1693:
1694: verifyExpressions(crosstab);
1695: }
1696:
1697: private void verifyParameters(JRDesignCrosstab crosstab) {
1698: JRExpression paramMapExpression = crosstab
1699: .getParametersMapExpression();
1700:
1701: if (paramMapExpression != null) {
1702: try {
1703: Class clazz = paramMapExpression.getValueClass();
1704: if (clazz == null) {
1705: addBrokenRule(
1706: "Class not set for crosstab parameters map expression.",
1707: paramMapExpression);
1708: } else if (!java.util.Map.class.isAssignableFrom(clazz)) {
1709: addBrokenRule(
1710: "Class "
1711: + clazz
1712: + " not supported for crosstab parameters map expression. Use java.util.Map instead.",
1713: paramMapExpression);
1714: }
1715: } catch (JRRuntimeException e) {
1716: addBrokenRule(e, paramMapExpression);
1717: }
1718: }
1719:
1720: JRCrosstabParameter[] parameters = crosstab.getParameters();
1721: if (parameters != null) {
1722: for (int i = 0; i < parameters.length; i++) {
1723: JRCrosstabParameter parameter = parameters[i];
1724:
1725: String paramName = parameter.getName();
1726: if (paramName == null || paramName.length() == 0) {
1727: addBrokenRule(
1728: "Missing parameter name for crosstab.",
1729: parameter);
1730: }
1731:
1732: JRExpression expression = parameter.getExpression();
1733: Class expressionClass = null;
1734: if (expression != null) {
1735: try {
1736: expressionClass = expression.getValueClass();
1737: if (expressionClass == null) {
1738: addBrokenRule(
1739: "Expression class not set for crosstab parameter "
1740: + paramName + ".",
1741: expression);
1742: }
1743: } catch (JRRuntimeException e) {
1744: addBrokenRule(e, expression);
1745: }
1746: }
1747:
1748: try {
1749: Class valueClass = parameter.getValueClass();
1750: if (valueClass == null) {
1751: addBrokenRule(
1752: "Class not set for crosstab parameter "
1753: + paramName + ".", parameter);
1754: } else if (expressionClass != null
1755: && !valueClass
1756: .isAssignableFrom(expressionClass)) {
1757: addBrokenRule(
1758: "Incompatible expression class for crosstab parameter "
1759: + paramName + ".", parameter);
1760: }
1761: } catch (Exception e) {
1762: addBrokenRule(e, parameter);
1763: }
1764: }
1765: }
1766: }
1767:
1768: private void verifyCrosstabRowGroup(JRCrosstabRowGroup group) {
1769: verifyCrosstabGroup(group);
1770: }
1771:
1772: private void verifyCrosstabColumnGroup(JRCrosstabColumnGroup group) {
1773: verifyCrosstabGroup(group);
1774: }
1775:
1776: private void verifyCrosstabGroup(JRCrosstabGroup group) {
1777: String groupName = group.getName();
1778: if (groupName == null || groupName.length() == 0) {
1779: addBrokenRule("Crosstab group name missing.", group);
1780: }
1781:
1782: verifyCrosstabBucket(group);
1783: verifyCellContents(group.getHeader(), groupName + " header");
1784: if (group.hasTotal()) {
1785: verifyCellContents(group.getTotalHeader(), groupName
1786: + " total header");
1787: }
1788: }
1789:
1790: private void verifyCrosstabBucket(JRCrosstabGroup group) {
1791: JRCrosstabBucket bucket = group.getBucket();
1792:
1793: JRExpression expression = bucket.getExpression();
1794: Class expressionClass = null;
1795: if (expression == null) {
1796: addBrokenRule(
1797: "Crosstab bucket expression missing for group "
1798: + group.getName() + ".", bucket);
1799: } else {
1800: try {
1801: expressionClass = expression.getValueClass();
1802: if (expressionClass == null) {
1803: addBrokenRule(
1804: "Crosstab bucket expression class missing for group "
1805: + group.getName() + ".", expression);
1806: }
1807: } catch (JRRuntimeException e) {
1808: addBrokenRule(e, expression);
1809: }
1810: }
1811:
1812: try {
1813: Class valueClass = expression == null ? null : expression
1814: .getValueClass();
1815: if (valueClass == null) {
1816: addBrokenRule(
1817: "Crosstab bucket value class missing for group "
1818: + group.getName() + ".", bucket);
1819: } else if (expressionClass != null
1820: && !valueClass.isAssignableFrom(expressionClass)) {
1821: addBrokenRule(
1822: "The class of the expression is not compatible with the class of the crosstab bucket for group "
1823: + group.getName() + ".", expression);
1824: }
1825: JRExpression comparatorExpression = bucket
1826: .getComparatorExpression();
1827: if (comparatorExpression == null) {
1828: if (valueClass != null
1829: && !Comparable.class
1830: .isAssignableFrom(valueClass)) {
1831: addBrokenRule(
1832: "No comparator expression specified and the value class is not comparable for crosstab group "
1833: + group.getName() + ".", bucket);
1834: }
1835: } else {
1836: try {
1837: Class comparatorClass = comparatorExpression
1838: .getValueClass();
1839: if (comparatorClass == null) {
1840: addBrokenRule(
1841: "Crosstab bucket comparator expression class missing for group "
1842: + group.getName() + ".",
1843: comparatorExpression);
1844: } else if (!Comparator.class
1845: .isAssignableFrom(comparatorClass)) {
1846: addBrokenRule(
1847: "The comparator expression should be compatible with java.util.Comparator for crosstab group "
1848: + group.getName() + ".",
1849: comparatorExpression);
1850: }
1851: } catch (JRRuntimeException e) {
1852: addBrokenRule(e, comparatorExpression);
1853: }
1854: }
1855: } catch (JRRuntimeException e) {
1856: addBrokenRule(e, expression);
1857: }
1858: }
1859:
1860: private void verifyCrosstabCells(JRDesignCrosstab crosstab) {
1861: JRCrosstabCell[][] cells = crosstab.getCells();
1862: JRCrosstabRowGroup[] rowGroups = crosstab.getRowGroups();
1863: JRCrosstabColumnGroup[] columnGroups = crosstab
1864: .getColumnGroups();
1865:
1866: JRCrosstabCell baseCell = cells[rowGroups.length][columnGroups.length];
1867: if (baseCell == null || baseCell.getWidth() == null) {
1868: addBrokenRule("Crosstab base cell width not specified.",
1869: crosstab);
1870: }
1871:
1872: if (baseCell == null || baseCell.getHeight() == null) {
1873: addBrokenRule("Crosstab base cell height not specified.",
1874: crosstab);
1875: }
1876:
1877: for (int i = rowGroups.length; i >= 0; --i) {
1878: for (int j = columnGroups.length; j >= 0; --j) {
1879: JRCrosstabCell cell = cells[i][j];
1880:
1881: String cellText = getCrosstabCellText(rowGroups,
1882: columnGroups, i, j);
1883:
1884: if (cell != null) {
1885: JRCellContents contents = cell.getContents();
1886:
1887: if (i < rowGroups.length) {
1888: JRCrosstabCell colCell = cells[rowGroups.length][j];
1889: if (colCell != null
1890: && colCell.getContents().getWidth() != contents
1891: .getWidth()) {
1892: addBrokenRule("Crosstab " + cellText
1893: + " width should be "
1894: + colCell.getContents().getWidth()
1895: + ".", cell);
1896: }
1897: }
1898:
1899: if (j < columnGroups.length) {
1900: JRCrosstabCell rowCell = cells[i][columnGroups.length];
1901: if (rowCell != null
1902: && rowCell.getContents().getHeight() != contents
1903: .getHeight()) {
1904: addBrokenRule("Crosstab " + cellText
1905: + " height should be "
1906: + rowCell.getContents().getHeight()
1907: + ".", cell);
1908: }
1909: }
1910:
1911: verifyCellContents(contents, cellText);
1912: }
1913: }
1914: }
1915: }
1916:
1917: private String getCrosstabCellText(JRCrosstabRowGroup[] rowGroups,
1918: JRCrosstabColumnGroup[] columnGroups, int rowIndex,
1919: int columnIndex) {
1920: String text;
1921:
1922: if (rowIndex == rowGroups.length) {
1923: if (columnIndex == columnGroups.length) {
1924: text = "cell";
1925: } else {
1926: text = columnGroups[columnIndex].getName()
1927: + " total cell";
1928: }
1929: } else {
1930: if (columnIndex == columnGroups.length) {
1931: text = rowGroups[rowIndex].getName() + " total cell";
1932: } else {
1933: text = rowGroups[rowIndex].getName() + ","
1934: + columnGroups[columnIndex].getName()
1935: + " total cell";
1936: }
1937: }
1938:
1939: return text;
1940: }
1941:
1942: private void verifyCrosstabMeasure(JRCrosstabMeasure measure) {
1943: String measureName = measure.getName();
1944: if (measureName == null || measureName.trim().length() == 0) {
1945: addBrokenRule("Measure name missing.", measure);
1946: }
1947:
1948: byte calculation = measure.getCalculation();
1949: if (calculation == JRVariable.CALCULATION_SYSTEM) {
1950: addBrokenRule(
1951: "Crosstab mesures cannot have system calculation",
1952: measure);
1953: }
1954:
1955: JRExpression valueExpression = measure.getValueExpression();
1956: Class expressionClass = null;
1957: if (valueExpression == null) {
1958: addBrokenRule("Missing expression for measure "
1959: + measureName, measure);
1960: } else {
1961: try {
1962: expressionClass = valueExpression.getValueClass();
1963: if (expressionClass == null) {
1964: addBrokenRule(
1965: "Crosstab measure expression class missing for "
1966: + measureName + ".",
1967: valueExpression);
1968: }
1969: } catch (JRRuntimeException e) {
1970: addBrokenRule(e, valueExpression);
1971: }
1972: }
1973:
1974: try {
1975: Class valueClass = measure.getValueClass();
1976: if (valueClass == null) {
1977: addBrokenRule("Measure value class missing.", measure);
1978: } else if (expressionClass != null
1979: && calculation != JRVariable.CALCULATION_COUNT
1980: && calculation != JRVariable.CALCULATION_DISTINCT_COUNT
1981: && !valueClass.isAssignableFrom(expressionClass)) {
1982: addBrokenRule(
1983: "The class of the expression is not compatible with the class of the measure "
1984: + measureName + ".", valueExpression);
1985: }
1986: if (measure.getPercentageOfType() != JRCrosstabMeasure.PERCENTAGE_TYPE_NONE) {
1987: Class percentageCalculatorClass = measure
1988: .getPercentageCalculatorClass();
1989: if (percentageCalculatorClass == null) {
1990: if (valueClass != null
1991: && !JRPercentageCalculatorFactory
1992: .hasBuiltInCalculator(valueClass)) {
1993: addBrokenRule(
1994: "Percentage calculator class needs to be specified for measure "
1995: + measureName + ".", measure);
1996: }
1997: } else {
1998: if (!JRPercentageCalculator.class
1999: .isAssignableFrom(percentageCalculatorClass)) {
2000: addBrokenRule(
2001: "Incompatible percentage calculator class for measure "
2002: + measureName + ".", measure);
2003: }
2004: }
2005: }
2006: } catch (JRRuntimeException e) {
2007: addBrokenRule(e, measure);
2008: }
2009:
2010: try {
2011: Class incrementerFactoryClass = measure
2012: .getIncrementerFactoryClass();
2013: if (incrementerFactoryClass != null
2014: && !JRExtendedIncrementerFactory.class
2015: .isAssignableFrom(incrementerFactoryClass)) {
2016: addBrokenRule(
2017: "Crosstab measures need extended incrementers (net.sf.jasperreports.engine.fill.JRExtendedIncrementerFactory).",
2018: measure);
2019: }
2020: } catch (JRRuntimeException e) {
2021: addBrokenRule(e, measure);
2022: }
2023: }
2024:
2025: private void verifyExpressions(JRDesignCrosstab crosstab) {
2026: verifyExpressions(expressionCollector.getExpressions(crosstab),
2027: crosstab.getParametersMap(), new HashMap(), crosstab
2028: .getVariablesMap());
2029: }
2030:
2031: private void verifyChart(JRChart chart) {
2032: if (chart.getEvaluationTime() == JRExpression.EVALUATION_TIME_AUTO) {
2033: addBrokenRule(
2034: "Charts do not support Auto evaluation time.",
2035: chart);
2036: }
2037:
2038: JRChartDataset dataset = chart.getDataset();
2039: if (dataset == null) {
2040: addBrokenRule("Chart dataset missing.", chart);
2041: } else {
2042: dataset.validate(this );
2043: }
2044: }
2045:
2046: private void verifyCellContents(JRCellContents contents,
2047: String cellText) {
2048: if (contents != null) {
2049: JRElement[] elements = contents.getElements();
2050: if (elements != null && elements.length > 0) {
2051: int topPadding = 0;
2052: int leftPadding = 0;
2053: int bottomPadding = 0;
2054: int rightPadding = 0;
2055:
2056: JRBox box = contents.getBox();
2057: if (box != null) {
2058: topPadding = box.getTopPadding();
2059: leftPadding = box.getLeftPadding();
2060: bottomPadding = box.getBottomPadding();
2061: rightPadding = box.getRightPadding();
2062: }
2063:
2064: int cellWidth = contents.getWidth();
2065: boolean widthCalculated = cellWidth != JRCellContents.NOT_CALCULATED;
2066: int avlblWidth = cellWidth - leftPadding - rightPadding;
2067: int cellHeight = contents.getHeight();
2068: boolean heightCalculated = cellHeight != JRCellContents.NOT_CALCULATED;
2069: int avlblHeight = cellHeight - topPadding
2070: - bottomPadding;
2071:
2072: for (int i = 0; i < elements.length; i++) {
2073: JRElement element = elements[i];
2074:
2075: verifyPrintWhenExpr(element);
2076:
2077: if (widthCalculated
2078: && element.getX() + element.getWidth() > avlblWidth) {
2079: addBrokenRule("Element reaches outside "
2080: + cellText + " width: x="
2081: + element.getX() + ", width="
2082: + element.getWidth()
2083: + ", available width=" + avlblWidth
2084: + ".", element);
2085: }
2086:
2087: if (heightCalculated
2088: && element.getY() + element.getHeight() > avlblHeight) {
2089: addBrokenRule("Element reaches outside "
2090: + cellText + " height: y="
2091: + element.getY() + ", height="
2092: + element.getHeight()
2093: + ", available height=" + avlblHeight
2094: + ".", element);
2095: }
2096:
2097: if (element instanceof JRStaticText) {
2098: verifyStaticText((JRStaticText) element);
2099: } else if (element instanceof JRTextField) {
2100: JRTextField textField = (JRTextField) element;
2101:
2102: if (textField.getEvaluationTime() != JRExpression.EVALUATION_TIME_NOW) {
2103: addBrokenRule(
2104: "Elements with delayed evaluation time are not supported inside crosstab cells.",
2105: textField);
2106: }
2107:
2108: verifyTextField(textField);
2109: } else if (element instanceof JRImage) {
2110: JRImage image = (JRImage) element;
2111:
2112: if (image.getEvaluationTime() != JRExpression.EVALUATION_TIME_NOW) {
2113: addBrokenRule(
2114: "Elements with delayed evaluation time are not supported inside crosstab cells.",
2115: image);
2116: }
2117:
2118: verifyImage(image);
2119: } else if (element instanceof JRFrame) {
2120: verifyFrame((JRFrame) element);
2121: } else if (element instanceof JRSubreport) {
2122: addBrokenRule(
2123: "Subreports are not allowed inside crosstab cells.",
2124: element);
2125: } else if (element instanceof JRCrosstab) {
2126: addBrokenRule(
2127: "Crosstabs are not allowed inside crosstab cells.",
2128: element);
2129: } else if (element instanceof JRChart) {
2130: addBrokenRule(
2131: "Charts are not allowed inside crosstab cells.",
2132: element);
2133: }
2134: }
2135: }
2136: }
2137: }
2138:
2139: private void verifyElementDataset(JRElementDataset dataset) {
2140: JRDatasetRun datasetRun = dataset.getDatasetRun();
2141:
2142: if (datasetRun != null) {
2143: byte incrementType = dataset.getIncrementType();
2144: if (incrementType == JRVariable.RESET_TYPE_PAGE
2145: || incrementType == JRVariable.RESET_TYPE_COLUMN) {
2146: addBrokenRule(
2147: "Chart datasets with dataset run cannont have Column or Page increment type.",
2148: dataset);
2149: }
2150:
2151: byte resetType = dataset.getResetType();
2152: if (resetType == JRVariable.RESET_TYPE_PAGE
2153: || resetType == JRVariable.RESET_TYPE_COLUMN) {
2154: addBrokenRule(
2155: "Chart datasets with dataset run cannont have Column or Page reset type.",
2156: dataset);
2157: } else if (resetType != JRVariable.RESET_TYPE_REPORT) {
2158: //doesn't make sense, but let it go
2159: }
2160:
2161: verifyDatasetRun(datasetRun);
2162: }
2163:
2164: JRExpression incrementWhenExpression = dataset
2165: .getIncrementWhenExpression();
2166: if (incrementWhenExpression != null) {
2167: try {
2168: Class valueClass = incrementWhenExpression
2169: .getValueClass();
2170: if (valueClass == null) {
2171: addBrokenRule(
2172: "Class not set for data set \"increment when\" expression.",
2173: incrementWhenExpression);
2174: } else if (!Boolean.class.isAssignableFrom(valueClass)) {
2175: addBrokenRule(
2176: "Class "
2177: + valueClass
2178: + " not supported for dataset \"increment when\" expression. Use java.lang.Boolean instead.",
2179: incrementWhenExpression);
2180: }
2181: } catch (JRRuntimeException e) {
2182: addBrokenRule(e, incrementWhenExpression);
2183: }
2184: }
2185: }
2186:
2187: private void verifyDatasetRun(JRDatasetRun datasetRun) {
2188: JRDesignDataset dataset = null;
2189:
2190: String datasetName = datasetRun.getDatasetName();
2191: if (datasetName == null || datasetName.length() == 0) {
2192: addBrokenRule("Dataset name is missing for dataset run.",
2193: datasetRun);
2194: } else {
2195: dataset = (JRDesignDataset) jasperDesign.getDatasetMap()
2196: .get(datasetName);
2197:
2198: if (dataset == null) {
2199: addBrokenRule("Unknown dataset name " + datasetName
2200: + ".", datasetRun);
2201: }
2202: }
2203:
2204: JRExpression parametersMapExpression = datasetRun
2205: .getParametersMapExpression();
2206:
2207: if (parametersMapExpression != null) {
2208: try {
2209: Class clazz = parametersMapExpression.getValueClass();
2210: if (clazz == null) {
2211: addBrokenRule("Class not set for dataset "
2212: + datasetName
2213: + " parameters map expression.",
2214: parametersMapExpression);
2215: } else if (!java.util.Map.class.isAssignableFrom(clazz)) {
2216: addBrokenRule(
2217: "Class "
2218: + clazz
2219: + " not supported for dataset "
2220: + datasetName
2221: + " parameters map expression. Use java.util.Map instead.",
2222: parametersMapExpression);
2223: }
2224: } catch (JRRuntimeException e) {
2225: addBrokenRule(e, parametersMapExpression);
2226: }
2227: }
2228:
2229: JRDatasetParameter[] parameters = datasetRun.getParameters();
2230: if (parameters != null && parameters.length > 0) {
2231: for (int index = 0; index < parameters.length; index++) {
2232: JRDatasetParameter parameter = parameters[index];
2233:
2234: String paramName = parameter.getName();
2235: if (paramName == null || paramName.trim().length() == 0) {
2236: addBrokenRule("Dataset " + datasetName
2237: + " parameter name missing.", parameter);
2238: }
2239:
2240: JRParameter datasetParam = null;
2241: if (dataset != null) {
2242: datasetParam = (JRParameter) dataset
2243: .getParametersMap().get(paramName);
2244:
2245: if (datasetParam == null) {
2246: addBrokenRule("Unknown parameter " + paramName
2247: + " in dataset " + datasetName + ".",
2248: parameter);
2249: }
2250: }
2251:
2252: JRExpression expression = parameter.getExpression();
2253:
2254: if (expression != null) {
2255: try {
2256: Class clazz = expression.getValueClass();
2257: if (clazz == null) {
2258: addBrokenRule("Class not set for dataset "
2259: + datasetName
2260: + " parameter expression : "
2261: + paramName + ".", expression);
2262: } else if (datasetParam != null
2263: && !datasetParam.getValueClass()
2264: .isAssignableFrom(clazz)) {
2265: addBrokenRule("Class " + clazz
2266: + " not supported for parameter "
2267: + paramName + " of dataset "
2268: + datasetName + ". Use "
2269: + datasetParam.getValueClass()
2270: + " instead.", expression);
2271: }
2272: } catch (JRRuntimeException e) {
2273: addBrokenRule(e, expression);
2274: }
2275: }
2276: }
2277: }
2278:
2279: JRExpression connectionExpression = datasetRun
2280: .getConnectionExpression();
2281: JRExpression dataSourceExpression = datasetRun
2282: .getDataSourceExpression();
2283:
2284: if (connectionExpression != null
2285: && dataSourceExpression != null) {
2286: addBrokenRule(
2287: "Dataset "
2288: + datasetName
2289: + " cannot have both connection expresion and data source expression.",
2290: datasetRun);
2291: }
2292:
2293: if (connectionExpression != null) {
2294: try {
2295: Class clazz = connectionExpression.getValueClass();
2296: if (clazz == null) {
2297: addBrokenRule("Class not set for dataset "
2298: + datasetName + " connection expression.",
2299: connectionExpression);
2300: } else if (!java.sql.Connection.class
2301: .isAssignableFrom(clazz)) {
2302: addBrokenRule(
2303: "Class "
2304: + clazz
2305: + " not supported for dataset "
2306: + datasetName
2307: + " connection expression. Use java.sql.Connection instead.",
2308: connectionExpression);
2309: }
2310: } catch (JRRuntimeException e) {
2311: addBrokenRule(e, connectionExpression);
2312: }
2313: }
2314:
2315: if (dataSourceExpression != null) {
2316: try {
2317: Class clazz = dataSourceExpression.getValueClass();
2318: if (clazz == null) {
2319: addBrokenRule("Class not set for dataset "
2320: + datasetName + " data source expression.",
2321: dataSourceExpression);
2322: } else if (!net.sf.jasperreports.engine.JRDataSource.class
2323: .isAssignableFrom(clazz)) {
2324: addBrokenRule(
2325: "Class "
2326: + clazz
2327: + " not supported for dataset "
2328: + datasetName
2329: + " data source expression. Use net.sf.jasperreports.engine.JRDataSource instead.",
2330: dataSourceExpression);
2331: }
2332: } catch (JRRuntimeException e) {
2333: addBrokenRule(e, dataSourceExpression);
2334: }
2335: }
2336: }
2337:
2338: private void verifyDatasets() {
2339: JRDataset[] datasets = jasperDesign.getDatasets();
2340: if (datasets != null && datasets.length > 0) {
2341: for (int i = 0; i < datasets.length; ++i) {
2342: JRDesignDataset dataset = (JRDesignDataset) datasets[i];
2343:
2344: if (dataset.getName() == null
2345: || dataset.getName().trim().length() == 0) {
2346: addBrokenRule("Dataset name is missing.", dataset);
2347: }
2348:
2349: verifyDataset(dataset);
2350: }
2351: }
2352: }
2353:
2354: private void verifyDataset(JRDesignDataset dataset) {
2355: verifyExpressions(dataset);
2356:
2357: verifyParameters(dataset);
2358:
2359: verifyQuery(dataset);
2360:
2361: verifyFields(dataset);
2362:
2363: verifySortFields(dataset);
2364:
2365: verifyVariables(dataset);
2366:
2367: verifyGroups(dataset);
2368:
2369: JRExpression filterExpression = dataset.getFilterExpression();
2370: if (filterExpression != null) {
2371: try {
2372: Class valueClass = filterExpression.getValueClass();
2373: if (valueClass == null) {
2374: addBrokenRule(
2375: "Class not set for filter expression.",
2376: filterExpression);
2377: } else if (!Boolean.class.isAssignableFrom(valueClass)) {
2378: addBrokenRule(
2379: "Class "
2380: + valueClass
2381: + " not supported for filter expression. Use java.lang.Boolean instead.",
2382: filterExpression);
2383: }
2384: } catch (JRRuntimeException e) {
2385: addBrokenRule(e, filterExpression);
2386: }
2387: }
2388: }
2389:
2390: private void verifyFrame(JRFrame frame) {
2391: JRElement[] elements = frame.getElements();
2392: if (elements != null && elements.length > 0) {
2393: int topPadding = frame.getTopPadding();
2394: int leftPadding = frame.getLeftPadding();
2395: int bottomPadding = frame.getBottomPadding();
2396: int rightPadding = frame.getRightPadding();
2397:
2398: int avlblWidth = frame.getWidth() - leftPadding
2399: - rightPadding;
2400: int avlblHeight = frame.getHeight() - topPadding
2401: - bottomPadding;
2402:
2403: for (int i = 0; i < elements.length; i++) {
2404: JRElement element = elements[i];
2405:
2406: if (element.getX() + element.getWidth() > avlblWidth) {
2407: addBrokenRule(
2408: "Element reaches outside frame width: x="
2409: + element.getX() + ", width="
2410: + element.getWidth()
2411: + ", available width=" + avlblWidth
2412: + ".", element);
2413: }
2414:
2415: if (element.getY() + element.getHeight() > avlblHeight) {
2416: addBrokenRule(
2417: "Element reaches outside frame height: y="
2418: + element.getY() + ", height="
2419: + element.getHeight()
2420: + ", available height="
2421: + avlblHeight + ".", element);
2422: }
2423:
2424: verifyElement(element);
2425: }
2426: }
2427: }
2428:
2429: public void verify(JRCategoryDataset dataset) {
2430: verifyElementDataset(dataset);
2431:
2432: JRCategorySeries[] series = dataset.getSeries();
2433: if (series != null) {
2434: for (int i = 0; i < series.length; i++) {
2435: verify(series[i]);
2436: }
2437: }
2438: }
2439:
2440: protected void verify(JRCategorySeries series) {
2441: verifyHyperlink(series.getItemHyperlink());
2442: }
2443:
2444: public void verify(JRPieDataset dataset) {
2445: verifyElementDataset(dataset);
2446: verifyHyperlink(dataset.getSectionHyperlink());
2447: }
2448:
2449: public void verify(JRHighLowDataset dataset) {
2450: verifyElementDataset(dataset);
2451: verifyHyperlink(dataset.getItemHyperlink());
2452: }
2453:
2454: public void verify(JRTimePeriodDataset dataset) {
2455: verifyElementDataset(dataset);
2456:
2457: JRTimePeriodSeries[] series = dataset.getSeries();
2458: if (series != null) {
2459: for (int i = 0; i < series.length; i++) {
2460: verify(series[i]);
2461: }
2462: }
2463: }
2464:
2465: protected void verify(JRTimePeriodSeries series) {
2466: verifyHyperlink(series.getItemHyperlink());
2467: }
2468:
2469: public void verify(JRTimeSeriesDataset dataset) {
2470: verifyElementDataset(dataset);
2471:
2472: JRTimeSeries[] series = dataset.getSeries();
2473: if (series != null) {
2474: for (int i = 0; i < series.length; i++) {
2475: verify(series[i]);
2476: }
2477: }
2478: }
2479:
2480: protected void verify(JRTimeSeries series) {
2481: verifyHyperlink(series.getItemHyperlink());
2482: }
2483:
2484: /**
2485: * Verify the design of a value dataset. Since value dataset's only
2486: * contain a single value and do not support hyperlinks there is nothing
2487: * to verify.
2488: */
2489: public void verify(JRValueDataset dataset) {
2490: }
2491:
2492: public void verify(JRXyDataset dataset) {
2493: verifyElementDataset(dataset);
2494:
2495: JRXySeries[] series = dataset.getSeries();
2496: if (series != null) {
2497: for (int i = 0; i < series.length; i++) {
2498: verify(series[i]);
2499: }
2500: }
2501: }
2502:
2503: protected void verify(JRXySeries series) {
2504: verifyHyperlink(series.getItemHyperlink());
2505: }
2506:
2507: public void verify(JRXyzDataset dataset) {
2508: verifyElementDataset(dataset);
2509:
2510: JRXyzSeries[] series = dataset.getSeries();
2511: if (series != null) {
2512: for (int i = 0; i < series.length; i++) {
2513: verify(series[i]);
2514: }
2515: }
2516: }
2517:
2518: protected void verify(JRXyzSeries series) {
2519: verifyHyperlink(series.getItemHyperlink());
2520: }
2521: }
|