001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.reports.adapter;
051:
052: import java.awt.Color;
053: import java.util.ArrayList;
054: import java.util.Iterator;
055:
056: import net.sf.jasperreports.engine.JRElement;
057: import net.sf.jasperreports.engine.JRException;
058: import net.sf.jasperreports.engine.JRGroup;
059: import net.sf.jasperreports.engine.JRTextElement;
060: import net.sf.jasperreports.engine.design.JRDesignBand;
061: import net.sf.jasperreports.engine.design.JRDesignExpression;
062: import net.sf.jasperreports.engine.design.JRDesignField;
063: import net.sf.jasperreports.engine.design.JRDesignGroup;
064: import net.sf.jasperreports.engine.design.JRDesignLine;
065: import net.sf.jasperreports.engine.design.JRDesignReportFont;
066: import net.sf.jasperreports.engine.design.JRDesignStaticText;
067: import net.sf.jasperreports.engine.design.JRDesignTextField;
068: import net.sf.jasperreports.engine.design.JRDesignVariable;
069: import net.sf.jasperreports.engine.design.JasperDesign;
070:
071: import com.projity.configuration.ReportColumns;
072: import com.projity.configuration.ReportDefinition;
073: import com.projity.field.Field;
074: import com.projity.graphic.configuration.SpreadSheetFieldArray;
075:
076: /**
077: *
078: */
079: public class ReportAdapter {
080: private static String GroupName = "group";
081:
082: private ReportDefinition reportDefinition;
083: private JRDesignReportFont boldFont;
084: private JRDesignReportFont italicFont;
085: private JRDesignReportFont normalFont;
086: private boolean hasAggregableField = false;
087:
088: private JasperDesign jasperDesign = new JasperDesign();
089:
090: public ReportAdapter(ReportDefinition reportDefinition) {
091: this .reportDefinition = reportDefinition;
092: }
093:
094: private boolean isAggregable(Field field) {
095: return (Field.SUM == field.getSummaryForGroup());
096: }
097:
098: private int neededWidth(SpreadSheetFieldArray fields) {
099: int width = 0;
100:
101: // LEGAL: 612x1008
102: // BORDERS: 20x30x20x30
103:
104: Iterator iterator = fields.iterator();
105: while (iterator.hasNext()) {
106: Field field = (Field) iterator.next();
107: width += field.getColumnWidth();
108:
109: }
110: return width;
111: }
112:
113: private void generateBaseDesign() throws JRException {
114:
115: if (reportDefinition.isTimeBased()) {
116: jasperDesign.setProperty(DataSourceProvider.TIME_BASED,
117: "true");
118: }
119:
120: jasperDesign.setProperty(
121: DataSourceProvider.COLLECTION_TYPE_PROPERTY,
122: new Integer(reportDefinition.getCollectionType())
123: .toString());
124:
125: jasperDesign.setName(reportDefinition.getName());
126: jasperDesign.setPageWidth(1008);
127: jasperDesign.setPageHeight(612);
128: jasperDesign.setColumnWidth(968);
129: jasperDesign.setColumnSpacing(0);
130: jasperDesign.setLeftMargin(20);
131: jasperDesign.setRightMargin(20);
132: jasperDesign.setTopMargin(30);
133: jasperDesign.setBottomMargin(30);
134:
135: //Fonts
136: normalFont = new JRDesignReportFont();
137: normalFont.setName("Arial_Normal");
138: normalFont.setDefault(true);
139: normalFont.setFontName("Arial");
140: normalFont.setSize(10);
141: normalFont.setPdfFontName("Helvetica");
142: normalFont.setPdfEncoding("Cp1252");
143: normalFont.setPdfEmbedded(false);
144: jasperDesign.addFont(normalFont);
145:
146: boldFont = new JRDesignReportFont();
147: boldFont.setName("Arial_Bold");
148: boldFont.setDefault(false);
149: boldFont.setFontName("Arial");
150: boldFont.setSize(12);
151: boldFont.setBold(true);
152: boldFont.setPdfFontName("Helvetica-Bold");
153: boldFont.setPdfEncoding("Cp1252");
154: boldFont.setPdfEmbedded(false);
155: jasperDesign.addFont(boldFont);
156:
157: italicFont = new JRDesignReportFont();
158: italicFont.setName("Arial_Italic");
159: italicFont.setDefault(false);
160: italicFont.setFontName("Arial");
161: italicFont.setSize(12);
162: italicFont.setItalic(true);
163: italicFont.setPdfFontName("Helvetica-Oblique");
164: italicFont.setPdfEncoding("Cp1252");
165: italicFont.setPdfEmbedded(false);
166: jasperDesign.addFont(italicFont);
167:
168: //Title
169: JRDesignBand band = new JRDesignBand();
170: band.setHeight(50);
171: JRDesignLine line = new JRDesignLine();
172: line.setX(0);
173: line.setY(0);
174: line.setWidth(968);
175: line.setHeight(0);
176: band.addElement(line);
177:
178: JRDesignStaticText text = new JRDesignStaticText();
179:
180: text.setX(0);
181: text.setY(10);
182: text.setWidth(968);
183: text.setHeight(30);
184: text.setTextAlignment(JRTextElement.TEXT_ALIGN_CENTER);
185: JRDesignReportFont bigFont = new JRDesignReportFont();
186: bigFont.setName("Arial_Normal");
187: bigFont.setDefault(true);
188: bigFont.setFontName("Arial");
189: bigFont.setSize(22);
190: bigFont.setPdfFontName("Helvetica");
191: bigFont.setPdfEncoding("Cp1252");
192: bigFont.setPdfEmbedded(false);
193: text.setFont(bigFont);
194: text.setText(reportDefinition.getName());
195: band.addElement(text);
196: jasperDesign.setTitle(band);
197:
198: }
199:
200: public JRDesignTextField getPageFooter() {
201: JRDesignTextField textField = new JRDesignTextField();
202: textField.setX(0);
203: textField.setY(10);
204: textField.setWidth(968);
205: textField.setHeight(15);
206: textField.setTextAlignment(JRTextElement.TEXT_ALIGN_CENTER);
207: textField.setFont(normalFont);
208: JRDesignExpression expression = new JRDesignExpression();
209: expression.setValueClass(java.lang.String.class);
210: expression
211: .setText("\"Page \" + String.valueOf($V{PAGE_NUMBER})"); // + \" of\"");
212: textField.setExpression(expression);
213: return textField;
214: }
215:
216: private String getFieldName(Field field, boolean asDuration) {
217: String fieldName = field.getId();
218: String returnFieldName = "";
219:
220: String mod = "";
221:
222: fieldName = fieldName.substring(new String("Field.").length());
223:
224: if ((!field.isMoney())) {
225: if (!asDuration) {
226: mod = "MODText" + mod;
227: mod = mod + "FIELD";
228: }
229: }
230:
231: returnFieldName = mod + fieldName;
232:
233: return returnFieldName;
234: }
235:
236: private Class getFieldClass(Field field, boolean asDuration) {
237: if (field.isMoney()) {
238: return Double.class;
239: } else if (field.isDurationOrWork() && asDuration) {
240: return Long.class;
241: } else {
242: return String.class;
243: }
244: }
245:
246: private String getFieldPattern(Field field) {
247: if (field.isMoney()) {
248: return "$ #,##0.00";
249: } else {
250: return null;
251: }
252: }
253:
254: private void addFields(ArrayList fields) throws JRException {
255: Iterator iterator = fields.iterator();
256: while (iterator.hasNext()) {
257: Field field = (Field) iterator.next();
258:
259: JRDesignField designField = new JRDesignField();
260: designField.setName(getFieldName(field, false));
261: designField.setValueClass(getFieldClass(field, false));
262:
263: // System.out.println("field is " + designField.getName());
264: try { //TOTO try catch is to avoid problems with duplicate field. Find the cause.
265: jasperDesign.addField(designField);
266:
267: if (isAggregable(field)) {
268: hasAggregableField = true;
269:
270: if (field.isDurationOrWork()) {
271: // add extra Long field (used for calculations)
272: designField = new JRDesignField();
273: designField.setName(getFieldName(field, true));
274: designField.setValueClass(getFieldClass(field,
275: true));
276: jasperDesign.addField(designField);
277: }
278: }
279: } catch (JRException e) {
280: System.out.println(e.getMessage());
281: }
282: }
283: }
284:
285: /**
286: * Add fields which have sums. If a group is passed in, assign the filds to the group so that the sums
287: * are reset after each group.
288: * @param fields
289: * @param group
290: * @throws JRException
291: */
292: private void addAggregableFields(ArrayList fields,
293: JRDesignGroup group) throws JRException {
294: Iterator iterator = fields.iterator();
295: while (iterator.hasNext()) {
296: Field field = (Field) iterator.next();
297:
298: if (isAggregable(field)) {
299: String fieldName = getFieldName(field, true);
300: JRDesignVariable variable = new JRDesignVariable();
301: variable.setName(fieldName + "Sum");
302: variable.setValueClass(getFieldClass(field, true));
303: variable
304: .setCalculation(JRDesignVariable.CALCULATION_SUM);
305: if (group == null) {
306: variable
307: .setResetType(JRDesignVariable.RESET_TYPE_REPORT);
308: } else {
309: variable
310: .setResetType(JRDesignVariable.RESET_TYPE_GROUP);
311: variable.setResetGroup(group);
312:
313: }
314:
315: JRDesignExpression expression = new JRDesignExpression();
316: expression.setValueClass(getFieldClass(field, true));
317: expression.setText("$F{" + fieldName + "}");
318: variable.setExpression(expression);
319: jasperDesign.addVariable(variable);
320:
321: }
322: }
323: }
324:
325: private JRDesignBand addFieldsHeader(JRDesignBand band,
326: SpreadSheetFieldArray fields, boolean isSub) {
327: // JRDesignRectangle rectangle = new JRDesignRectangle();
328: // rectangle.setX(0);
329: // rectangle.setY(5);
330: // rectangle.setWidth(515);
331: // rectangle.setHeight(15);
332: //// if(isSub) {
333: //// rectangle.setForecolor(new Color(0x99, 0x99, 0x99));
334: //// rectangle.setBackcolor(new Color(0x99, 0x99, 0x99));
335: //// } else {
336: //// rectangle.setForecolor(new Color(0x33, 0x33, 0x33));
337: //// rectangle.setBackcolor(new Color(0x33, 0x33, 0x33));
338: //// }
339: // band.addElement(rectangle);
340:
341: // columns in page header
342: Iterator iterator = fields.iterator();
343: int x = 0;
344: while (iterator.hasNext()) {
345: Field field = (Field) iterator.next();
346: JRDesignStaticText staticText = new JRDesignStaticText();
347: staticText.setX(x);
348: if (isSub) {
349: staticText.setY(20);
350: } else {
351: staticText.setY(5);
352: }
353: staticText.setWidth(field.getColumnWidth());
354: staticText.setHeight(15);
355: staticText.setForecolor(Color.white);
356: if (isSub) {
357: staticText.setBackcolor(new Color(0x99, 0x99, 0x99));
358: } else {
359: staticText.setBackcolor(new Color(0x33, 0x33, 0x33));
360: }
361: staticText.setMode(JRElement.MODE_OPAQUE);
362: staticText.setTextAlignment(JRTextElement.TEXT_ALIGN_RIGHT);
363: staticText.setFont(boldFont);
364: staticText.setText(field.getName());
365: band.addElement(staticText);
366:
367: x += field.getColumnWidth();
368: }
369:
370: return band;
371: }
372:
373: private JRDesignBand getFieldsHeader(SpreadSheetFieldArray fields,
374: boolean isSub) throws JRException {
375: //Page header
376: JRDesignBand band = new JRDesignBand();
377: band.setHeight(20);
378: return addFieldsHeader(band, fields, isSub);
379: }
380:
381: private JRDesignBand addDetail(JRDesignBand band,
382: SpreadSheetFieldArray fields, JRGroup group)
383: throws JRException {
384: Iterator iterator = fields.iterator();
385: int x = 0;
386: if (null != group) {
387: band.setHeight(40);
388: } else {
389: band.setHeight(15);
390: }
391: while (iterator.hasNext()) {
392: Field field = (Field) iterator.next();
393: JRDesignTextField textField = new JRDesignTextField();
394: if (null != group) {
395: textField
396: .setEvaluationTime(JRDesignExpression.EVALUATION_TIME_GROUP);
397: textField.setEvaluationGroup(group);
398: // textField.setBackcolor(Color.black);
399: // textField.setForecolor(Color.white);
400: textField.setY(5);
401: textField.setFont(boldFont);
402: textField.setHeight(15);
403: } else {
404: textField.setY(0);
405: textField.setFont(normalFont);
406: textField.setHeight(12);
407: }
408: textField.setX(x);
409: textField.setWidth(field.getColumnWidth());
410: textField.setTextAlignment(JRTextElement.TEXT_ALIGN_RIGHT);
411:
412: String fieldName = getFieldName(field, false);
413: if (field.isMoney()) {
414: // Double
415: textField.setPattern(getFieldPattern(field));
416: }
417:
418: JRDesignExpression expression = new JRDesignExpression();
419: expression.setValueClass(getFieldClass(field, false));
420: expression.setText("$F{" + fieldName + "}");
421:
422: textField.setExpression(expression);
423: band.addElement(textField);
424:
425: x += field.getColumnWidth();
426: }
427:
428: return band;
429: }
430:
431: private JRDesignBand getDetail(SpreadSheetFieldArray fields,
432: JRGroup group) throws JRException {
433: //Detail
434: JRDesignBand band = new JRDesignBand();
435: return addDetail(band, fields, group);
436: }
437:
438: private JRDesignBand getAggregatableFooter(
439: SpreadSheetFieldArray fields) throws JRException {
440:
441: JRDesignBand band = new JRDesignBand();
442: band.setHeight(40);
443: Iterator iterator = fields.iterator();
444: int x = 0;
445: while (iterator.hasNext()) {
446: Field field = (Field) iterator.next();
447: if (isAggregable(field)) {
448: JRDesignLine line = new JRDesignLine();
449: line.setX(x);
450: line.setY(0);
451: line.setWidth(field.getColumnWidth());
452: line.setHeight(0);
453: band.addElement(line);
454: line.setY(2);
455: band.addElement(line);
456:
457: JRDesignTextField textField = new JRDesignTextField();
458: textField.setX(x);
459: textField.setY(4);
460: textField.setWidth(field.getColumnWidth());
461: textField.setHeight(12);
462: textField
463: .setTextAlignment(JRTextElement.TEXT_ALIGN_RIGHT);
464: textField.setFont(normalFont);
465: JRDesignExpression expression = new JRDesignExpression();
466:
467: // Money (double) or Duration(long)
468: if (field.isMoney()) {
469: expression
470: .setValueClass(getFieldClass(field, true));
471: textField.setPattern(getFieldPattern(field));
472: expression.setText("$V{"
473: + getFieldName(field, true) + "Sum}");
474: } else if (field.isWork()) {
475: expression.setValueClass(String.class);
476: expression
477: .setText("com.projity.datatype.DurationFormat.formatWork($V{"
478: + getFieldName(field, true)
479: + "Sum})");
480: } else if (field.isDuration()) {
481: expression.setValueClass(String.class);
482: expression
483: .setText("com.projity.datatype.DurationFormat.format($V{"
484: + getFieldName(field, true)
485: + "Sum})");
486: }
487:
488: textField.setExpression(expression);
489: band.addElement(textField);
490: }
491:
492: x += field.getColumnWidth();
493: }
494:
495: return band;
496:
497: }
498:
499: private void addLastPageFooter(SpreadSheetFieldArray fields)
500: throws JRException {
501: JRDesignBand band = getAggregatableFooter(fields);
502: band.addElement(getPageFooter());
503:
504: jasperDesign.setLastPageFooter(band);
505: }
506:
507: private void addPageFooter() throws JRException {
508: //page footer
509: JRDesignBand band = new JRDesignBand();
510: band.setHeight(30);
511: JRDesignLine line = new JRDesignLine();
512: line.setX(0);
513: line.setY(0);
514: line.setWidth(968);
515: line.setHeight(0);
516: band.addElement(line);
517:
518: band.addElement(getPageFooter());
519: jasperDesign.setPageFooter(band);
520: }
521:
522: public void generateDesign(SpreadSheetFieldArray fieldArray)
523: throws JRException {
524: hasAggregableField = false;
525: generateBaseDesign();
526: ArrayList columnsList = (ArrayList) reportDefinition
527: .getColumnsList();
528:
529: ReportColumns columns;
530: if (columnsList.size() == 1) {
531: // simple flat report
532: SpreadSheetFieldArray fields;
533: if (fieldArray != null)
534: fields = fieldArray;
535: else {
536: columns = (ReportColumns) columnsList.get(0);
537: fields = columns.getFieldArray();
538: }
539: addFields(fields);
540:
541: if (hasAggregableField) {
542: addAggregableFields(fields, null);
543: }
544:
545: jasperDesign.setPageHeader(getFieldsHeader(fields, false));
546:
547: jasperDesign.setDetail(getDetail(fields, null));
548:
549: addPageFooter();
550:
551: // last page footer (if any)
552: if (hasAggregableField) {
553: addLastPageFooter(fields);
554: }
555:
556: // int neededW = neededWidth(fields);
557: // System.out.println("Needed width is " + neededW);
558: // System.out.println("columns number is " + fields.size());
559: } else if (columnsList.size() == 2) {
560: // reports & subreports
561: columns = (ReportColumns) columnsList.get(0);
562: String groupByField = columns.getGroupbyField();
563: SpreadSheetFieldArray mainFields = columns.getFieldArray();
564: columns = (ReportColumns) columnsList.get(1);
565: SpreadSheetFieldArray detailFields;
566: if (fieldArray != null)
567: detailFields = fieldArray;
568: else
569: detailFields = columns.getFieldArray();
570:
571: addFields(mainFields);
572: addFields(detailFields);
573:
574: JRDesignGroup group = new JRDesignGroup();
575: if (hasAggregableField) {
576: addAggregableFields(detailFields, group);
577: }
578:
579: group.setName(GroupName);
580: group.setStartNewColumn(false);
581: group.setStartNewPage(false);
582: JRDesignExpression expression = new JRDesignExpression();
583:
584: Iterator iterator = mainFields.iterator();
585: while (iterator.hasNext()) {
586: Field f = (Field) iterator.next();
587:
588: if (groupByField.equals(f.getId())) {
589: expression.setText("$F{" + getFieldName(f, false)
590: + "}");
591: expression.setValueClass(getFieldClass(f, false));
592: group.setExpression(expression);
593: break;
594: }
595: }
596:
597: JRDesignBand band = getDetail(mainFields, group);
598: band = addFieldsHeader(band, detailFields, true);
599: group.setGroupHeader(band);
600:
601: if (hasAggregableField) {
602: group
603: .setGroupFooter(getAggregatableFooter(detailFields));
604: }
605: jasperDesign.addGroup(group);
606:
607: jasperDesign.setPageHeader(getFieldsHeader(mainFields,
608: false));
609: jasperDesign.setDetail(getDetail(detailFields, null));
610: addPageFooter();
611:
612: } else {
613: throw new JRException(
614: "report definition must contain either one or two columns (see view.xml)");
615: }
616:
617: }
618:
619: /**
620: * @return Returns the jasperDesign.
621: */
622: public JasperDesign getJasperDesign() {
623: return jasperDesign;
624: }
625: }
|