0001: /*
0002: * (C) Copyright 2000 - 2003 Nabh Information Systems, Inc.
0003: *
0004: * This program is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU General Public License
0006: * as published by the Free Software Foundation; either version 2
0007: * of the License, or (at your option) any later version.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0017: *
0018: */
0019:
0020: package com.nabhinc.portlet.report;
0021:
0022: import java.io.*;
0023: import java.sql.ResultSetMetaData;
0024: import java.util.*;
0025:
0026: import javax.portlet.ActionRequest;
0027: import javax.portlet.ActionResponse;
0028: import javax.portlet.PortletConfig;
0029: import javax.portlet.PortletException;
0030: import javax.portlet.PortletSession;
0031: import javax.portlet.PortletURL;
0032: import javax.portlet.RenderRequest;
0033: import javax.portlet.RenderResponse;
0034:
0035: import com.nabhinc.coil.parser.COILParser;
0036: import com.nabhinc.coil.parser.JavaContext;
0037: import com.nabhinc.core.Defaults;
0038:
0039: import com.nabhinc.portlet.base.BasePortlet;
0040: import com.nabhinc.util.StringUtil;
0041: import com.nabhinc.util.db.DBUtil;
0042:
0043: /**
0044: *
0045: *
0046: * @author Padmanabh Dabke
0047: * (c) 2003 Nabh Information Systems, Inc. All Rights Reserved.
0048: */
0049: public class ReportPortlet extends BasePortlet {
0050:
0051: // Codes that identify column type
0052: public static final int TYPE_BOOLEAN = 0;
0053: public static final int TYPE_DATE = 1;
0054: public static final int TYPE_FLOAT = 2;
0055: public static final int TYPE_INT = 3;
0056: public static final int TYPE_LONG = 4;
0057: public static final int TYPE_SHORT = 5;
0058: public static final int TYPE_STRING = 6;
0059: public static final int TYPE_TIME = 7;
0060: public static final int TYPE_TIMESTAMP = 8;
0061:
0062: // Special variable names
0063: public static final String VAR_RECORD_COUNT = "recordCount";
0064: public static final String VAR_GROUP_COUNT = "groupCount";
0065: public static final String VAR_PAGE_COUNT = "pageCount";
0066:
0067: public static final String VAR_RECORD_NUMBER = "recordNumber";
0068: public static final String VAR_GROUP_MEMBER_NUMBER = "groupMemberNumber";
0069: public static final String VAR_GROUP_NUMBER = "groupNumber";
0070: public static final String VAR_PAGE_NUMBER = "pageNumber";
0071:
0072: //public static final String VAR_GROUP_VALUE = "currentGroupValue";
0073: public static final String VAR_GROUP_SIZE = "currentGroupSize";
0074:
0075: public static final String REFRESH_ATTRIB = "refresh";
0076:
0077: public static final String CONTENT_ATTRIB = "content";
0078: public static final String PAGE_NUMBER_ATTRIB = "page_number";
0079: public static final String PROJECT_ID_ATTRIB = "project_id";
0080:
0081: public static final String LIST_SQL_INIT_PARAM = "listSQL";
0082: public static final String DATA_SOURCE_INIT_PARAM = "dataSource";
0083: public static final String COUNT_SQL_INIT_PARAM = "countSQL";
0084: public static final String HEADERS_INIT_PARAM = "headers";
0085: public static final String REPORT_HEADER_INIT_PARAM = "reportHeader";
0086: public static final String REPORT_FOOTER_INIT_PARAM = "reportFooter";
0087: public static final String PAGE_HEADER_INIT_PARAM = "pageHeader";
0088: public static final String PAGE_FOOTER_INIT_PARAM = "pageFooter";
0089: public static final String COLUMNS_INIT_PARAM = "columns";
0090: public static final String COLUMN_NAME_INIT_PARAM = "columnName";
0091: public static final String COLUMN_EXPR_INIT_PARAM = "columnExpr";
0092: public static final String SECTION_NAME_INIT_PARAM = "sectionName";
0093: public static final String SECTION_HEADER_INIT_PARAM = "sectionHeader";
0094: public static final String SECTION_FOOTER_INIT_PARAM = "sectionFooter";
0095: public static final String SECTION_EXPR_INIT_PARAM = "sectionExpr";
0096: public static final String START_GROUP_ON_NEW_PAGE_INIT_PARAM = "startGroupOnNewPage";
0097: public static final String EMPTY_REPORT_MSG_INIT_PARAM = "emptyReportMessage";
0098: public static final String NEXT_LABEL_INIT_PARAM = "next";
0099: public static final String PREV_LABEL_INIT_PARAM = "prev";
0100: public static final String REFRESH_LABEL_INIT_PARAM = "refresh";
0101:
0102: public static final String ROWS_PER_PAGE_PREF = "rowsPerPage";
0103:
0104: /**
0105: * Parser for evaluating report expressions.
0106: */
0107: private COILParser rpParser = new COILParser(new StringReader(""));
0108:
0109: /**
0110: * Evaluation context for report expressions.
0111: */
0112: private JavaContext rpContext = new JavaContext();
0113:
0114: /**
0115: * JNDI name of the data source that supplies data.
0116: */
0117: private String rpDataSource = "jdbc/stringbeansdb";
0118:
0119: /**
0120: * SQL for getting report data.
0121: */
0122: private String rpSQL = null;
0123:
0124: /**
0125: * Report header expression.
0126: */
0127: private String rpReportHeader = null;
0128:
0129: /**
0130: * Report footer expression.
0131: */
0132: private String rpReportFooter = null;
0133:
0134: /**
0135: * Page header expression.
0136: */
0137: private String rpPageHeader = null;
0138:
0139: /**
0140: * Page footer expression.
0141: */
0142: private String rpPageFooter = "\"<table width=\\\"100%\\\" cellpadding=10><tr><td align=\\\"right\\\"><b>Page \" + pageNumber + \" of \" + pageCount + \"</b></td></tr></table>\"";
0143:
0144: /**
0145: * Group names used as variable names
0146: */
0147: private String[] rpGroupNames = null;
0148:
0149: /**
0150: * Group header expression.
0151: */
0152: private String[] rpGroupHeader = null;
0153:
0154: /**
0155: * Group footer expression.
0156: */
0157: private String[] rpGroupFooter = null;
0158:
0159: /**
0160: * Group expression
0161: */
0162: private String[] rpGroupExpression = null;
0163:
0164: /**
0165: * Column headers for generated table.
0166: */
0167: private String[] rpHeaders = null;
0168:
0169: /**
0170: * All column names
0171: */
0172: private String[] rpAllColumns = null;
0173:
0174: /**
0175: * All column data types
0176: */
0177: //private int[] rpColumnTypes =
0178: // { TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_INT };
0179: /**
0180: * COIL expressions for report column displays
0181: */
0182: private String[] rpReportField = null;
0183:
0184: /**
0185: * Message to be displayed if the table is empty
0186: */
0187: private String rpEmptyMessage = "This report is empty.";
0188:
0189: /**
0190: * Should a group be started on a new page ?
0191: */
0192: private boolean rpStartGroupOnNewPage = false;
0193:
0194: /**
0195: * Text or HTML for the "next" link.
0196: */
0197: private String rpNext = "Next";
0198:
0199: /**
0200: * Text or HTML for the "prev" link.
0201: */
0202: private String rpPrev = "Prev";
0203:
0204: /**
0205: * Text or HTML for the report refresh link.
0206: */
0207: private String rpRefresh = "Refresh";
0208:
0209: // Inner classes
0210: class ReportGroup {
0211: public int[] groupNumber = null;
0212: public int groupLevel = 0;
0213: public Object[] groupValues = null;
0214: public Vector groupMembers = new Vector();
0215:
0216: public ReportGroup(int[] num, Object[] val, int level) {
0217: groupNumber = new int[num.length];
0218: for (int i = 0; i < num.length; i++) {
0219: groupNumber[i] = num[i];
0220: }
0221: groupValues = val;
0222: groupLevel = level;
0223: }
0224: }
0225:
0226: class ReportPage {
0227: public int pageNumber = 0;
0228: public int startIndex = 0;
0229: public int endIndex = 0;
0230: public Vector pageGroups = new Vector();
0231:
0232: public ReportPage(int num) {
0233: pageNumber = num;
0234: }
0235: }
0236:
0237: /**
0238: * ReportBuilder constructor comment.
0239: */
0240: public ReportPortlet() {
0241: super ();
0242: }
0243:
0244: /**
0245: * Insert the method's description here.
0246: * Creation date: (12/9/2002 10:17:20 AM)
0247: */
0248: public void cacheRecord(java.sql.ResultSet results, Object[] cache,
0249: int numFields) throws Exception {
0250: //Object fValue = null;
0251: for (int i = 0; i < numFields; i++) {
0252: // cache[i] = fValue;
0253: cache[i] = results.getObject(i + 1);
0254: }
0255:
0256: }
0257:
0258: /**
0259: * Insert the method's description here.
0260: * Creation date: (12/9/2002 10:17:20 AM)
0261: */
0262: public Vector cacheResults(java.sql.ResultSet results)
0263: throws Exception {
0264:
0265: Vector resultsVec = new Vector();
0266: Object[] cache = null;
0267: int numFields = rpAllColumns.length;
0268: //Object fValue = null;
0269:
0270: while (results.next()) {
0271: cache = new Object[numFields];
0272: for (int i = 0; i < numFields; i++) {
0273: cache[i] = results.getObject(i + 1);
0274: }
0275: resultsVec.addElement(cache);
0276: }
0277: return resultsVec;
0278:
0279: }
0280:
0281: /**
0282: * Insert the method's description here.
0283: * Creation date: (12/9/2002 1:40:23 PM)
0284: * @return java.lang.Object
0285: * @param record java.lang.Object[]
0286: * @exception java.lang.Exception The exception description.
0287: */
0288: private Object[] computeGroupValues(Object[] record)
0289: throws java.lang.Exception {
0290:
0291: if (rpGroupExpression == null)
0292: return null;
0293:
0294: int numFields = rpAllColumns.length;
0295: for (int i = 0; i < numFields; i++) {
0296: rpContext.bind(rpAllColumns[i], record[i]);
0297: }
0298: Object[] values = new Object[rpGroupExpression.length];
0299: for (int i = 0; i < rpGroupExpression.length; i++) {
0300: rpParser.ReInit(new StringReader(rpGroupExpression[i]));
0301: values[i] = rpParser.COILExpression().evaluate(rpContext);
0302: if (values[i] == null)
0303: System.out.println(rpGroupExpression[i]
0304: + " evaluated to null.");
0305: }
0306: return values;
0307: }
0308:
0309: private int checkGroupLevel(Object[] currentGroupValues,
0310: Object[] newGroupValues) {
0311: if (currentGroupValues == null || newGroupValues == null)
0312: return -1;
0313: try {
0314: for (int i = 0; i < currentGroupValues.length; i++) {
0315: if (currentGroupValues[i] == null) {
0316: if (newGroupValues[i] != null)
0317: return i;
0318: } else {
0319: if (!currentGroupValues[i]
0320: .equals(newGroupValues[i]))
0321: return i;
0322: }
0323: }
0324: } catch (Exception e) {
0325: e.printStackTrace();
0326: }
0327: return -1;
0328: }
0329:
0330: /**
0331: * Insert the method's description here.
0332: * Creation date: (12/9/2002 1:35:01 PM)
0333: * @return java.util.Vector
0334: * @param resultsCache java.util.Vector
0335: * @exception java.lang.Exception The exception description.
0336: */
0337: private Vector createReport(Vector resultsCache, int rowsPerPage)
0338: throws java.lang.Exception {
0339:
0340: Vector pages = new Vector();
0341: if (resultsCache.size() == 0) {
0342: return pages;
0343: }
0344:
0345: int numResults = resultsCache.size();
0346: rpContext.bind(VAR_RECORD_COUNT, new Integer(numResults));
0347: ReportPage currentPage = new ReportPage(1);
0348: pages.addElement(currentPage);
0349: rpContext.bind(VAR_RECORD_NUMBER, new Integer(1));
0350: rpContext.bind(VAR_GROUP_MEMBER_NUMBER, new Integer(1));
0351: int groupCount[] = { 1 };
0352: if (rpGroupNames != null) {
0353: groupCount = new int[rpGroupNames.length];
0354: for (int i = 0; i < groupCount.length; i++) {
0355: groupCount[i] = 1;
0356: }
0357: }
0358:
0359: Object[] currentRecord = (Object[]) resultsCache.elementAt(0);
0360: Object[] currentGroupValues = computeGroupValues(currentRecord);
0361: if (currentGroupValues != null)
0362: for (int i = 0; i < currentGroupValues.length; i++) {
0363: rpContext.bind(rpGroupNames[i], currentGroupValues[i]);
0364: }
0365: ReportGroup currentGroup = new ReportGroup(groupCount,
0366: currentGroupValues, 0);
0367: currentGroup.groupMembers.addElement(currentRecord);
0368: currentPage.pageGroups.addElement(currentGroup);
0369:
0370: int groupIndex = 2;
0371: int lineNumber = 1;
0372: int pageNumber = 1;
0373: for (int i = 1; i < numResults; i++) {
0374: lineNumber++;
0375: currentRecord = (Object[]) resultsCache.elementAt(i);
0376: rpContext.bind(VAR_RECORD_NUMBER, new Integer(i + 1));
0377: rpContext.bind(VAR_GROUP_MEMBER_NUMBER, new Integer(
0378: groupIndex));
0379: Object[] newGroupValues = computeGroupValues(currentRecord);
0380:
0381: int groupLevel = checkGroupLevel(currentGroupValues,
0382: newGroupValues);
0383: boolean startNewGroup = groupLevel > -1 ? true : false;
0384:
0385: if ((startNewGroup && rpStartGroupOnNewPage)
0386: || lineNumber > rowsPerPage) {
0387:
0388: // Start a new page
0389: lineNumber = 1;
0390: pageNumber++;
0391: currentPage.endIndex = currentGroup.groupMembers.size();
0392:
0393: currentPage = new ReportPage(pageNumber);
0394: pages.addElement(currentPage);
0395: if (!startNewGroup) {
0396: currentPage.pageGroups.addElement(currentGroup);
0397: currentPage.startIndex = currentGroup.groupMembers
0398: .size();
0399: }
0400: }
0401:
0402: if (startNewGroup) {
0403: groupCount[groupLevel]++;
0404: for (int j = groupLevel + 1; j < groupCount.length; j++) {
0405: groupCount[j] = 1;
0406: }
0407: currentGroup = new ReportGroup(groupCount,
0408: newGroupValues, groupLevel);
0409: currentGroupValues = newGroupValues;
0410: currentPage.pageGroups.addElement(currentGroup);
0411: groupIndex = 1;
0412: } else {
0413: groupIndex++;
0414: }
0415: currentGroup.groupMembers.addElement(currentRecord);
0416:
0417: }
0418: currentPage.endIndex = currentGroup.groupMembers.size();
0419:
0420: rpContext.bind(VAR_PAGE_COUNT, new Integer(pages.size()));
0421: for (int i = 0; i < currentGroup.groupNumber.length; i++) {
0422: rpContext.bind(VAR_GROUP_COUNT + (i + 1), new Integer(
0423: currentGroup.groupNumber[i]));
0424: }
0425: return pages;
0426: }
0427:
0428: /**
0429: * Insert the method's description here.
0430: * Creation date: (12/5/2002 12:31:22 PM)
0431: * @exception java.lang.Exception The exception description.
0432: */
0433: public String[] generateContent(String projectID, int rowsPerPage)
0434: throws IOException, PortletException {
0435: java.sql.Connection conn = null;
0436: String[] content = null;
0437: try {
0438: conn = DBUtil.getConnection(rpDataSource);
0439: String sql = rpSQL.replaceAll("\\$project", projectID);
0440: java.sql.PreparedStatement st = conn.prepareStatement(sql);
0441: java.sql.ResultSet results = st.executeQuery();
0442: if (rpAllColumns == null) {
0443: // Extract the column data from the result metadata
0444: ResultSetMetaData metaData = results.getMetaData();
0445: int numCols = metaData.getColumnCount();
0446: rpAllColumns = new String[numCols];
0447: for (int i = 0; i < numCols; i++) {
0448: rpAllColumns[i] = metaData.getColumnName(i + 1)
0449: .toLowerCase();
0450: }
0451: if (rpHeaders == null) {
0452: if (rpReportField == null)
0453: rpReportField = rpAllColumns;
0454: rpHeaders = rpAllColumns;
0455: } else {
0456: rpReportField = new String[rpHeaders.length];
0457: for (int i = 0; i < rpReportField.length; i++) {
0458: rpReportField[i] = rpAllColumns[i];
0459: }
0460: }
0461: }
0462: Vector resultsCache = cacheResults(results);
0463: Vector pages = createReport(resultsCache, rowsPerPage);
0464: if (pages.size() == 0) {
0465: content = new String[1];
0466: content[0] = rpEmptyMessage;
0467: return content;
0468: }
0469:
0470: content = new String[pages.size()];
0471:
0472: int numPages = pages.size();
0473: int numFields = rpReportField.length;
0474: int numColumns = rpAllColumns.length;
0475: int recordNum = 1;
0476: for (int j = 0; j < numPages; j++) {
0477: StringBuffer sb = new StringBuffer();
0478: sb.append("<table class=\"Body\" width=\"100%\">");
0479:
0480: // Write report header.
0481: if (j == 0 && rpReportHeader != null) {
0482: sb
0483: .append("<tr><td class=\"ReportHeader\" colspan=\""
0484: + rpReportField.length + "\">");
0485: rpParser.ReInit(new StringReader(rpReportHeader));
0486: sb.append("<br/>");
0487: sb.append(rpParser.COILExpression().evaluate(
0488: rpContext));
0489: sb.append("<br/> ");
0490: sb.append("</td></tr>");
0491: }
0492: rpContext.bind(VAR_PAGE_NUMBER, new Integer(j + 1));
0493: ReportPage page = (ReportPage) pages.elementAt(j);
0494:
0495: // Write page header.
0496: if (rpPageHeader != null && j > 0) {
0497: sb.append("<br/>");
0498: sb.append("<tr><td class=\"PageHeader\" colspan=\""
0499: + rpReportField.length + "\">");
0500: rpParser.ReInit(new StringReader(rpPageHeader));
0501: sb.append(rpParser.COILExpression().evaluate(
0502: rpContext));
0503: //sb.append("<br> ");
0504: sb.append("</td></tr>");
0505: }
0506: sb.append("<tr class=\"portlet-section-header\">");
0507: for (int i = 0; i < numFields; i++) {
0508: sb.append("<td class=\"portlet-section-header\">");
0509: sb.append(rpHeaders[i]);
0510: sb.append("</td>");
0511: }
0512: sb.append("</tr>");
0513:
0514: // Write page groups
0515: int numGroups = page.pageGroups.size();
0516: for (int k = 0; k < numGroups; k++) {
0517:
0518: ReportGroup currentGroup = (ReportGroup) page.pageGroups
0519: .elementAt(k);
0520: int numRows = currentGroup.groupMembers.size();
0521: int startIndex = 0;
0522: int endIndex = numRows;
0523: Vector rows = currentGroup.groupMembers;
0524: rpContext
0525: .bind(VAR_GROUP_SIZE, new Integer(numRows));
0526: if (rpGroupNames != null) {
0527: for (int i = 0; i < rpGroupNames.length; i++) {
0528: rpContext.bind(rpGroupNames[i],
0529: currentGroup.groupValues[i]);
0530: }
0531: }
0532: for (int i = 0; i < currentGroup.groupNumber.length; i++) {
0533: rpContext
0534: .bind(
0535: VAR_GROUP_NUMBER + (i + 1),
0536: new Integer(
0537: currentGroup.groupNumber[i]));
0538: }
0539:
0540: // Adjust parameters if a group is split between pages.
0541: if (k == 0) {
0542: startIndex = page.startIndex;
0543: }
0544:
0545: if (k == numGroups - 1) {
0546: endIndex = page.endIndex;
0547: }
0548:
0549: // Write group header only if a new group is being started.
0550: if (rpGroupHeader != null
0551: && startIndex == 0
0552: && rpGroupHeader[currentGroup.groupLevel] != null) {
0553: sb.append("<tr><td class=\"GroupHeader");
0554: sb.append(currentGroup.groupLevel);
0555: sb.append("\" colspan=\"");
0556: sb.append(rpReportField.length);
0557: sb.append("\">");
0558: rpParser
0559: .ReInit(new StringReader(
0560: rpGroupHeader[currentGroup.groupLevel]));
0561: sb.append(rpParser.COILExpression().evaluate(
0562: rpContext));
0563: sb.append("</td></tr>");
0564: }
0565:
0566: // Write group contents
0567: for (int l = startIndex; l < endIndex; l++) {
0568: rpContext.bind(VAR_GROUP_MEMBER_NUMBER,
0569: new Integer(l));
0570: Object[] record = (Object[]) rows.elementAt(l);
0571:
0572: sb.append("<tr>");
0573: for (int i = 0; i < numColumns; i++) {
0574: rpContext.bind(rpAllColumns[i], record[i]);
0575: }
0576:
0577: rpContext.bind(VAR_RECORD_NUMBER, new Integer(
0578: recordNum));
0579: for (int i = 0; i < numFields; i++) {
0580: sb
0581: .append("<td class=\"portlet-section-body\">");
0582: rpParser.ReInit(new StringReader(
0583: rpReportField[i]));
0584: sb.append(rpParser.COILExpression()
0585: .evaluate(rpContext));
0586: sb.append("</td>");
0587: }
0588: recordNum++;
0589: sb.append("</tr>");
0590: }
0591:
0592: // Write group footer only if the complete group has been written
0593: if (endIndex == currentGroup.groupMembers.size()
0594: && rpGroupFooter != null
0595: && rpGroupFooter[currentGroup.groupLevel] != null) {
0596: sb.append("<tr><td class=\"GroupFooter");
0597: sb.append(currentGroup.groupLevel);
0598: sb.append("\" colspan=\"");
0599: sb.append(rpReportField.length);
0600: sb.append("\">");
0601: rpParser
0602: .ReInit(new StringReader(
0603: rpGroupFooter[currentGroup.groupLevel]));
0604: sb.append(rpParser.COILExpression().evaluate(
0605: rpContext));
0606: sb.append("</td></tr>");
0607: }
0608: }
0609:
0610: // Write page footer
0611: if (rpPageFooter != null) {
0612: sb.append("<tr><td class=\"PageFooter\" colspan=\""
0613: + rpReportField.length + "\">");
0614: sb.append("<br/>");
0615: rpParser.ReInit(new StringReader(rpPageFooter));
0616: sb.append(rpParser.COILExpression().evaluate(
0617: rpContext));
0618:
0619: sb.append("</td></tr>");
0620: }
0621:
0622: // Write report footer.
0623: if (j == numPages - 1 && rpReportFooter != null) {
0624: sb
0625: .append("<tr><td class=\"portlet-section-body\" colspan=\""
0626: + rpReportField.length + "\">");
0627: rpParser.ReInit(new StringReader(rpReportFooter));
0628: sb.append(rpParser.COILExpression().evaluate(
0629: rpContext));
0630: sb.append("</td></tr>");
0631: }
0632: sb.append("</table>");
0633: content[j] = sb.toString();
0634: }
0635:
0636: } catch (IOException ioex) {
0637: ioex.printStackTrace();
0638: throw ioex;
0639:
0640: } catch (Exception ex) {
0641: ex.printStackTrace();
0642: throw new PortletException(ex);
0643: } finally {
0644: try {
0645: if (conn != null)
0646: conn.close();
0647: } catch (Exception ex1) {
0648: // ignore
0649: }
0650: }
0651: return content;
0652: }
0653:
0654: /**
0655: * Insert the method's description here.
0656: * Creation date: (12/5/2002 12:31:22 PM)
0657: * @exception java.lang.Exception The exception description.
0658: */
0659: /*
0660: public Object handleGroupDisplay(Object currentGroup, StringBuffer sb) throws Exception {
0661:
0662: // Evaluate group expression
0663: rpParser.ReInit(new StringReader(rpGroupExpression));
0664: Object newGroup = rpParser.COILExpression().evaluate(rpContext);
0665: try {
0666: Object groupValue = rpContext.resolve(VAR_GROUP_VALUE);
0667: if (groupValue == null) rpContext.bind(VAR_GROUP_VALUE, newGroup);
0668: } catch (Exception ex) {
0669: rpContext.bind(VAR_GROUP_VALUE, newGroup);
0670: }
0671: if (newGroup.equals(currentGroup)) {
0672: // We are still in the same group, increment group count and return
0673: Integer groupCountObj = (Integer) rpContext.resolve(VAR_GROUP_MEMBER_NUMBER);
0674: if (groupCountObj == null) {
0675: rpContext.bind(VAR_GROUP_MEMBER_NUMBER, new Integer(1));
0676: } else {
0677: rpContext.bind(VAR_GROUP_MEMBER_NUMBER, new Integer(groupCountObj.intValue() + 1));
0678: }
0679: return newGroup;
0680: }
0681:
0682: if (currentGroup != null && rpGroupFooter != null) {
0683: // Write group footer.
0684: sb.append("<TR><TD class=\"GroupFooter\" colspan=" + rpReportField.length +
0685: ">");
0686: rpParser.ReInit(new StringReader(rpGroupFooter));
0687: sb.append(rpParser.COILExpression().evaluate(rpContext));
0688: sb.append("</TD></TR>");
0689: }
0690:
0691: // Reset group count & value
0692: rpContext.bind(VAR_GROUP_MEMBER_NUMBER, new Integer(1));
0693: rpContext.bind(VAR_GROUP_VALUE, newGroup);
0694:
0695: // Write group header.
0696: if (rpGroupHeader != null) {
0697: sb.append("<TR><TD class=\"GroupHeader\" colspan=" + rpReportField.length +
0698: ">");
0699: rpParser.ReInit(new StringReader(rpGroupHeader));
0700: sb.append(rpParser.COILExpression().evaluate(rpContext));
0701: sb.append("</TD></TR>");
0702: }
0703: return newGroup;
0704: }
0705:
0706: */
0707:
0708: /**
0709: * Expects one or more of:
0710: */
0711: public void init(PortletConfig config) throws PortletException {
0712: super .init(config);
0713:
0714: // Check for alternate way of specifying group information
0715:
0716: int groupCount = 0;
0717:
0718: try {
0719: while (true) {
0720: String grpStr = config
0721: .getInitParameter(SECTION_NAME_INIT_PARAM
0722: + groupCount);
0723: if (grpStr == null || grpStr.trim().equals(""))
0724: break;
0725: groupCount++;
0726: }
0727:
0728: } catch (Throwable ex) {
0729: ex.printStackTrace();
0730: }
0731:
0732: if (groupCount != 0) {
0733: rpGroupNames = new String[groupCount];
0734: rpGroupExpression = new String[groupCount];
0735: rpGroupHeader = new String[groupCount];
0736: rpGroupFooter = new String[groupCount];
0737:
0738: for (int i = 0; i < groupCount; i++) {
0739: rpGroupNames[i] = config
0740: .getInitParameter(SECTION_NAME_INIT_PARAM + i);
0741: rpGroupExpression[i] = config
0742: .getInitParameter(SECTION_EXPR_INIT_PARAM + i);
0743: rpGroupHeader[i] = config
0744: .getInitParameter(SECTION_HEADER_INIT_PARAM + i);
0745: rpGroupFooter[i] = config
0746: .getInitParameter(SECTION_FOOTER_INIT_PARAM + i);
0747: }
0748: }
0749:
0750: rpSQL = config.getInitParameter(LIST_SQL_INIT_PARAM);
0751: rpDataSource = config.getInitParameter(DATA_SOURCE_INIT_PARAM);
0752: if (rpDataSource == null || rpDataSource.trim().equals(""))
0753: rpDataSource = Defaults.getDataSourceName();
0754: rpReportHeader = config
0755: .getInitParameter(REPORT_HEADER_INIT_PARAM);
0756: rpReportFooter = config
0757: .getInitParameter(REPORT_FOOTER_INIT_PARAM);
0758: rpPageHeader = config.getInitParameter(PAGE_HEADER_INIT_PARAM);
0759: rpPageFooter = config.getInitParameter(PAGE_FOOTER_INIT_PARAM);
0760:
0761: try {
0762: rpAllColumns = StringUtil.split(config
0763: .getInitParameter(COLUMNS_INIT_PARAM), ",");
0764: } catch (Exception ex) {
0765:
0766: }
0767:
0768: if (rpAllColumns == null) {
0769: // Try alternate specification of column names
0770: int colCount = 0;
0771: while (true) {
0772: String grpStr = config
0773: .getInitParameter(COLUMN_NAME_INIT_PARAM
0774: + colCount);
0775: if (grpStr == null || grpStr.trim().equals(""))
0776: break;
0777: colCount++;
0778: }
0779:
0780: if (colCount == 0) {
0781: error("init", "Missing report column names");
0782: throw new PortletException(
0783: "Failed to get column names.");
0784: } else {
0785: rpAllColumns = new String[colCount];
0786: for (int i = 0; i < colCount; i++) {
0787: rpAllColumns[i] = config
0788: .getInitParameter(COLUMN_NAME_INIT_PARAM
0789: + i);
0790: }
0791: }
0792: }
0793:
0794: String temp = config.getInitParameter("headers");
0795: if (temp != null) {
0796: rpHeaders = StringUtil.split(temp, ",");
0797: }
0798: int fieldCount = 0;
0799: while (true) {
0800: String grpStr = config.getInitParameter("columnExpr"
0801: + fieldCount);
0802: if (grpStr == null || grpStr.trim().equals(""))
0803: break;
0804: fieldCount++;
0805: }
0806:
0807: if (fieldCount == 0) {
0808: rpReportField = rpAllColumns;
0809: //rpHeaders = rpAllColumns;
0810: } else {
0811: rpReportField = new String[fieldCount];
0812: // rpHeaders = new String[fieldCount];
0813: for (int i = 0; i < fieldCount; i++) {
0814: rpReportField[i] = config.getInitParameter("columnExpr"
0815: + i);
0816: // rpHeaders[i] = config.getInitParameter("columnExpr" + i);
0817: }
0818: }
0819:
0820: if (rpHeaders == null)
0821: rpHeaders = rpReportField;
0822:
0823: if (config.getInitParameter("startGroupOnNewPage") == null) {
0824: rpStartGroupOnNewPage = false;
0825: } else {
0826: rpStartGroupOnNewPage = true;
0827: }
0828:
0829: temp = config.getInitParameter("emptyReportMessage");
0830: if (temp != null)
0831: rpEmptyMessage = temp;
0832:
0833: if (rpHeaders == null) {
0834: try {
0835: rpHeaders = StringUtil.split(config
0836: .getInitParameter("headers"), ",");
0837: } catch (Exception ex) {
0838: error("init", "Invalid column header specification");
0839: throw new PortletException(
0840: "Failed to parse column headers: " + ex);
0841: }
0842: }
0843:
0844: temp = config.getInitParameter("next");
0845: if (temp != null)
0846: rpNext = temp;
0847:
0848: temp = config.getInitParameter("prev");
0849: if (temp != null)
0850: rpPrev = temp;
0851:
0852: temp = config.getInitParameter("refresh");
0853: if (temp != null)
0854: rpRefresh = temp;
0855:
0856: }
0857:
0858: /**
0859: * Insert the method's description here.
0860: * Creation date: (12/9/2002 10:17:20 AM)
0861: */
0862: public void setFieldValue(java.sql.ResultSet results, int i)
0863: throws Exception {
0864: /*
0865: Object fValue = null;
0866: int colType = rpColumnTypes[i];
0867: switch (colType) {
0868: case TYPE_BOOLEAN :
0869: fValue = new Boolean(results.getBoolean(rpAllColumns[i]));
0870: break;
0871: case TYPE_DATE :
0872: fValue = results.getDate(rpAllColumns[i]);
0873: break;
0874: case TYPE_FLOAT :
0875: fValue = new Float(results.getFloat(rpAllColumns[i]));
0876: break;
0877: case TYPE_INT :
0878: fValue = new Integer(results.getInt(rpAllColumns[i]));
0879: break;
0880: case TYPE_LONG :
0881: fValue = new Long(results.getLong(rpAllColumns[i]));
0882: break;
0883: case TYPE_SHORT :
0884: fValue = new Short(results.getShort(rpAllColumns[i]));
0885: break;
0886: case TYPE_STRING :
0887: fValue = results.getString(rpAllColumns[i]);
0888: break;
0889: case TYPE_TIME :
0890: fValue = results.getTime(rpAllColumns[i]);
0891: break;
0892: case TYPE_TIMESTAMP :
0893: fValue = results.getTimestamp(rpAllColumns[i]);
0894: break;
0895: default :
0896: throw new Exception("Unknown column type.");
0897:
0898:
0899:
0900: }
0901: rpContext.bind(rpAllColumns[i], fValue);
0902: */
0903: rpContext.bind(rpAllColumns[i], results.getObject(i + 1));
0904:
0905: }
0906:
0907: /**
0908: * Simply returns the content string that was configured via <content>
0909: * element.
0910: */
0911: public void doView(RenderRequest request, RenderResponse response)
0912: throws PortletException, IOException {
0913:
0914: String[] content = null;
0915: PrintWriter w = response.getWriter();
0916: PortletSession session = request.getPortletSession();
0917: String projectID = request.getParameter(PROJECT_ID_ATTRIB);
0918: int rowsPerPage = Integer.parseInt(request.getPreferences()
0919: .getValue(ROWS_PER_PAGE_PREF, "10"));
0920:
0921: if (projectID == null) {
0922: projectID = (String) session
0923: .getAttribute(PROJECT_ID_ATTRIB);
0924: } else {
0925: session.setAttribute(PROJECT_ID_ATTRIB, projectID);
0926: }
0927:
0928: if (session.getAttribute(REFRESH_ATTRIB,
0929: PortletSession.PORTLET_SCOPE) != null) {
0930: content = generateContent(projectID, rowsPerPage);
0931: session.setAttribute(CONTENT_ATTRIB, content,
0932: PortletSession.PORTLET_SCOPE);
0933: session.removeAttribute(REFRESH_ATTRIB,
0934: PortletSession.PORTLET_SCOPE);
0935: } else {
0936: content = (String[]) session.getAttribute(CONTENT_ATTRIB,
0937: PortletSession.PORTLET_SCOPE);
0938: if (content == null) {
0939: content = generateContent(projectID, rowsPerPage);
0940: session.setAttribute(CONTENT_ATTRIB, content,
0941: PortletSession.PORTLET_SCOPE);
0942: }
0943: }
0944:
0945: PortletURL refreshURL = response.createActionURL();
0946: refreshURL.setParameter(REFRESH_ATTRIB, "true");
0947: if (projectID != null)
0948: refreshURL.setParameter(PROJECT_ID_ATTRIB, projectID);
0949:
0950: String refreshURLStr = " <a title=\"" + rpRefresh
0951: + "\" href=\"" + refreshURL + "\">" + rpRefresh
0952: + "</a>";
0953:
0954: if (content.length > 1) {
0955: String pageIndexStr = request
0956: .getParameter(PAGE_NUMBER_ATTRIB);
0957: if (pageIndexStr == null) {
0958: pageIndexStr = (String) session.getAttribute(
0959: PAGE_NUMBER_ATTRIB,
0960: PortletSession.PORTLET_SCOPE);
0961: } else {
0962: session.setAttribute(PAGE_NUMBER_ATTRIB, pageIndexStr,
0963: PortletSession.PORTLET_SCOPE);
0964: }
0965: int pageIndex = 0;
0966: if (pageIndexStr != null) {
0967: pageIndex = Integer.parseInt(pageIndexStr);
0968: }
0969: if (pageIndex >= content.length)
0970: pageIndex = content.length - 1;
0971: PortletURL prevURL = response.createRenderURL();
0972: prevURL.setParameter(PAGE_NUMBER_ATTRIB, Integer
0973: .toString(pageIndex - 1));
0974: String prevURLStr = null;
0975: if (pageIndex != 0) {
0976: prevURLStr = " <a title=\"" + rpPrev
0977: + "\" href=\"" + prevURL + "\">" + rpPrev
0978: + "</a>";
0979: }
0980:
0981: PortletURL nextURL = response.createRenderURL();
0982: nextURL.setParameter(PAGE_NUMBER_ATTRIB, Integer
0983: .toString(pageIndex + 1));
0984: String nextURLStr = null;
0985: if (pageIndex != content.length - 1) {
0986: nextURLStr = " <a title=\"" + rpNext
0987: + "\" href=\"" + nextURL + "\">" + rpNext
0988: + "</a>";
0989: }
0990: w.write(content[pageIndex]);
0991: w
0992: .write("<table width=\"100%\"><tr><td class=\"portlet-section-body\" align=\"right\"><br/>");
0993:
0994: w.write(refreshURLStr);
0995: if (prevURLStr != null) {
0996: w.write(prevURLStr);
0997: }
0998: if (nextURLStr != null) {
0999: w.write(nextURLStr);
1000: }
1001: w.write("</td></tr></table>");
1002: } else {
1003: w.write(content[0]);
1004: w
1005: .write("<table width=\"100%\"><tr><td class=\"portlet-section-body\" align=\"right\"><br/>");
1006:
1007: w.write(refreshURLStr);
1008: w.write("</td></tr></table>");
1009: }
1010:
1011: }
1012:
1013: public void processAction(ActionRequest request,
1014: ActionResponse actionResponse) throws PortletException,
1015: java.io.IOException {
1016:
1017: //if (request.getParameter(REFRESH_ATTRIB) != null) {
1018: request.getPortletSession().setAttribute(REFRESH_ATTRIB,
1019: "true", PortletSession.PORTLET_SCOPE);
1020: //}
1021: }
1022:
1023: protected void setReportSQL(String sql) {
1024: rpSQL = sql;
1025: }
1026:
1027: protected void setColumnHeaders(String[] h) {
1028: rpHeaders = h;
1029: }
1030:
1031: protected void setReportHeaders(String[] headers) {
1032: rpHeaders = headers;
1033: }
1034:
1035: protected void setDataSourceName(String dsName) {
1036: rpDataSource = dsName;
1037: }
1038:
1039: protected void setReportHeader(String header) {
1040: rpReportHeader = header;
1041: }
1042:
1043: protected void setReportFooter(String footer) {
1044: rpReportFooter = footer;
1045: }
1046:
1047: protected void setPageHeader(String h) {
1048: rpPageHeader = h;
1049: }
1050:
1051: protected void setPageFooter(String f) {
1052: rpPageFooter = f;
1053: }
1054:
1055: protected void setGroupNames(String[] groupNames) {
1056: rpGroupNames = groupNames;
1057: }
1058:
1059: protected void setGroupExpressions(String[] groupExpressions) {
1060: rpGroupExpression = groupExpressions;
1061: }
1062:
1063: protected void setGroupHeaders(String[] h) {
1064: rpGroupHeader = h;
1065: }
1066:
1067: protected void setGroupFooters(String[] f) {
1068: rpGroupFooter = f;
1069: }
1070:
1071: }
|