001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.services.html;
066:
067: import com.jcorporate.expresso.core.db.DBException;
068: import com.jcorporate.expresso.core.misc.StringUtil;
069: import com.jcorporate.expresso.ext.report.ExpressoReport;
070: import com.jcorporate.expresso.ext.report.ReportException;
071:
072: import javax.servlet.http.HttpServletRequest;
073: import javax.servlet.http.HttpServletResponse;
074: import java.io.BufferedOutputStream;
075: import java.io.FileOutputStream;
076: import java.io.IOException;
077: import java.io.OutputStream;
078: import java.io.PrintWriter;
079: import java.util.ArrayList;
080: import java.util.Date;
081: import java.util.HashMap;
082: import java.util.Hashtable;
083: import java.util.Iterator;
084: import java.util.Map;
085: import java.util.StringTokenizer;
086: import java.util.Vector;
087:
088: /**
089: * A specialized HTML Element that implements a report. Reports have headers,
090: * possibly embedded reports, possibly page breaks, and various other
091: * embedded elements.
092: * <p/>
093: * <p>Reports also differ from other HTML components in that they can be written
094: * directly to files if required.</p>
095: *
096: * @author Michael Nash
097: * @version $Revision: 1.14 $ $Date: 2004/11/17 20:48:18 $
098: */
099: public class ReportPage extends HtmlElement implements ExpressoReport {
100:
101: private String this Class = this .getClass().getName() + ".";
102: private String reportTitle = null;
103: private Page myPage = null;
104: private Table currentTable = null;
105: private String fileName = null;
106: private HashMap myParams = null;
107: private Vector defaultParams = new Vector(1);
108: private String dbName = "";
109: private String reportCode = "";
110:
111: /**
112: * Constructor
113: *
114: * @throws HtmlException If superclass constructor fails
115: */
116: public ReportPage() throws HtmlException {
117: myPage = new Page("Report Page");
118: } /* ReportPage() */
119:
120: /**
121: * The report code
122: *
123: * @param newCode java.lang.String
124: */
125: public void setReportCode(String newCode) {
126: reportCode = newCode;
127: }
128:
129: /**
130: * Dummy implementation. Override if your report has default values
131: * to implement.
132: *
133: * @throws DBException upon error
134: */
135: public void populateDefaultValues() throws DBException {
136: }
137:
138: /**
139: * Retrieve the report code
140: *
141: * @return java.lang.String
142: */
143: public String getReportCode() {
144: return reportCode;
145: }
146:
147: /**
148: * Constructor
149: * Create a report page for output to a file
150: *
151: * @param newFileName Filename for output
152: * @param newTitle Title of the report
153: * @throws HtmlException If the report page cannot be created
154: */
155: public ReportPage(String newFileName, String newTitle)
156: throws HtmlException {
157: this ();
158: setFileName(newFileName);
159: setTitle(newTitle);
160: } /* ReportPage(String, String) */
161:
162: /**
163: * Add a new line to the report
164: *
165: * @param newLine Line to add to the report output
166: * @throws HtmlException If the line cannot be added
167: */
168: public synchronized void addLine(String newLine)
169: throws HtmlException {
170: sendLine(newLine);
171: } /* addLine(String) */
172:
173: /**
174: * @param newCode the new parameter code
175: * @param newDescrip the new description
176: * @param newType the java type
177: * @param newDefaultValue the default value
178: * @throws HtmlException upon error
179: */
180: protected void addParam(String newCode, String newDescrip,
181: String newType, String newDefaultValue)
182: throws HtmlException {
183: ReportPageParam newParam = new ReportPageParam(newCode,
184: newDescrip, newType, newDefaultValue);
185: defaultParams.addElement(newParam);
186: } /* addParam(String, String, STring, String) */
187:
188: /**
189: * Add a new row to the report's current table
190: *
191: * @param rowString Pipe-seperated values, one for each column for the new row
192: * in the table
193: * @throws HtmlException A new row could not be added
194: */
195: public synchronized void addRow(String rowString)
196: throws HtmlException {
197: Row myRow = new Row();
198: currentTable.add(myRow);
199:
200: StringTokenizer stk = new StringTokenizer(rowString, "|");
201:
202: while (stk.hasMoreTokens()) {
203: myRow.add(new Cell(new Text(stk.nextToken())));
204: }
205: } /* addRow(String) */
206:
207: /**
208: * Add a date/time stamp to the report output
209: *
210: * @throws HtmlException If the date/time stampt cannot be added
211: */
212: public synchronized void addTimeStamp() throws HtmlException {
213: Date Now = new Date(System.currentTimeMillis());
214: myPage.add(new Paragraph(new Text(Now.toString())));
215: } /* addTimeStamp() */
216:
217: /**
218: * Close the report, writing the final HTML.
219: * Also closes the output if we're in cgi mode
220: *
221: * @throws HtmlException If a problem occurrs saving the report
222: */
223: public synchronized void close() throws HtmlException {
224: save();
225: } /* close() */
226:
227: public synchronized void display(HttpServletRequest req,
228: HttpServletResponse res, String charset)
229: throws HtmlException {
230: if (StringUtil.notNull(charset).equals("")) {
231: charset = "ISO-8859-1";
232: }
233:
234: res.setContentType("text/html; charset=" + charset);
235:
236: try {
237: PrintWriter out = res.getWriter();
238: display(out);
239: } catch (IOException ie) {
240: throw new HtmlException(ie);
241: }
242: } /* display(HttpServletRequest, HttpServletResponse, String) */
243:
244: /**
245: * Display to the screen (browser) in the normal way
246: *
247: * @param out PrintWriter to send to client
248: * @throws HtmlException If the report could not be written
249: */
250: public void display(PrintWriter out) throws HtmlException {
251: myPage.display(out);
252: } /* display(PrintWriter) */
253:
254: /**
255: * depth is ignored
256: *
257: * @param depth the number of tabs to indent
258: * @param out the output stream
259: * @throws HtmlException upon error
260: */
261: protected void display(PrintWriter out, int depth)
262: throws HtmlException {
263: display(out);
264: }
265:
266: /**
267: * End the current table in the output stream of this report
268: *
269: * @throws HtmlException If the table could not be ended correctly
270: */
271: public synchronized void endTable() throws HtmlException {
272: myPage.add(currentTable);
273: currentTable = null;
274: } /* endTable() */
275:
276: /**
277: * Get the current table being used by the report
278: *
279: * @return Table HTML Table object being currently used
280: * @throws HtmlException If the current table cannot be accessed
281: */
282: public Table getCurrentTable() throws HtmlException {
283: return currentTable;
284: } /* getCurrentTable() */
285:
286: /**
287: * Retrieve the db name
288: *
289: * @return java.lang.String
290: */
291: public String getDBName() {
292: return dbName;
293: } /* getDBName() */
294:
295: /**
296: * Return a Vector of default parameter objects
297: *
298: * @return Vector of default parameters
299: */
300: public Vector getDefaultParams() {
301: return (Vector) defaultParams.clone();
302: } /* getDefaultParams() */
303:
304: /**
305: * Retrieve the default parameter value for the given parameter name
306: *
307: * @param parameterName the name of the parameter. Must be listed
308: * in the list of parameter names
309: * @return java.lang.String. The default parameter value. May be null.
310: * @throws IllegalArgumentException if the parameter name does not exist
311: * in the report's parameter list.
312: */
313: public synchronized String getDefaultValue(String parameterName) {
314: StringUtil
315: .assertNotBlank(parameterName,
316: "getDefaultValue(String) parameter: parameterName cannot be blank");
317: for (Iterator i = defaultParams.iterator(); i.hasNext();) {
318: ReportPageParam oneParam = (ReportPageParam) i.next();
319: if (parameterName.equals(oneParam.getCode())) {
320: return oneParam.getDefaultValue();
321: }
322: }
323:
324: throw new IllegalArgumentException(parameterName
325: + " is not a parameter in the report");
326: }
327:
328: /**
329: * Return a reference to the current page
330: *
331: * @return the page
332: */
333: protected Page getPage() {
334: return myPage;
335: } /* getPage() */
336:
337: /**
338: * Return the value of the named parameter
339: *
340: * @param paramCode of the parameter
341: * @return Value of the given parameter
342: * @throws HtmlException if there is no such parameter
343: */
344: public String getParam(String paramCode) throws HtmlException {
345: String myName = (this Class + "getParam(String)");
346:
347: if (myParams == null) {
348: throw new HtmlException(myName
349: + ":No parameters defined for "
350: + " this report. Can't get parameter '" + paramCode
351: + "'");
352: }
353:
354: String retVal = (String) myParams.get(paramCode);
355:
356: if (retVal == null) {
357: throw new HtmlException(myName + ":No such parameter as '"
358: + paramCode + "'");
359: }
360:
361: return retVal;
362: } /* getParam(String) */
363:
364: /**
365: * Return the parameters for this report
366: *
367: * @return Hashtable of Parameters of this report
368: * @throws HtmlException If an error occurs retrieving the parameters
369: */
370: public synchronized Hashtable getParams() throws HtmlException {
371: if (myParams == null) {
372: return new Hashtable(1);
373: } else {
374: return new Hashtable(myParams);
375: }
376: } /* getParams() */
377:
378: /**
379: * Return the title of this report
380: *
381: * @return Report title of this report
382: */
383: public String getTitle() {
384: return reportTitle;
385: } /* getTitle() */
386:
387: /**
388: * Save output to a file
389: *
390: * @throws HtmlException If the output could not be written
391: */
392: public void save() throws HtmlException {
393: String myName = (this Class + "save()");
394:
395: try {
396: FileOutputStream fout = new FileOutputStream(fileName);
397: BufferedOutputStream bout = new BufferedOutputStream(fout);
398: PrintWriter out = new PrintWriter(bout);
399: myPage.display(out);
400: } catch (IOException ie) {
401: throw new HtmlException(myName + ":I/O Error writing "
402: + fileName + ":" + ie.getMessage());
403: }
404: } /* save() */
405:
406: /**
407: * Send the given line to either the server (if we are running in CORBA-based mode)
408: * or straight to output (cgi mode)
409: *
410: * @param theLine The line to output
411: * @throws HtmlException If the line could not be output
412: */
413: private void sendLine(String theLine) throws HtmlException {
414: myPage.add(new Text(theLine));
415: } /* sendLine(String) */
416:
417: /**
418: * @param newDBName new data context
419: */
420: public synchronized void setDBName(String newDBName) {
421: dbName = StringUtil.notNull(newDBName);
422: } /* setDBName(String) */
423:
424: /**
425: * Set the file name for output
426: *
427: * @param newFileName New output file name
428: * @throws HtmlException If the parameter is invalid
429: */
430: public synchronized void setFileName(String newFileName)
431: throws HtmlException {
432: fileName = newFileName;
433: } /* setFileName(String) */
434:
435: /**
436: * Set the filename and the title of this report
437: *
438: * @param newFileName Name of the output file to write
439: * @param newTitle Title of the report
440: * @throws HtmlException If the parameters are not valid
441: */
442: public synchronized void setFileName(String newFileName,
443: String newTitle) throws HtmlException {
444: setTitle(newTitle);
445: setFileName(newFileName);
446: } /* setFileName(String, String) */
447:
448: /**
449: * Set the parameters for this report to the given hashtable
450: *
451: * @param newParams New parameters hashtable
452: * @throws HtmlException If these parameters cannot be set
453: */
454: public synchronized void setParams(Hashtable newParams)
455: throws HtmlException {
456: if (newParams != null) {
457: myParams = new HashMap(newParams);
458: }
459: } /* setParams(Hashtable) */
460:
461: /**
462: * Set the title of this report
463: *
464: * @param newTitle New title of report
465: */
466: public synchronized void setTitle(String newTitle) {
467: reportTitle = newTitle;
468: } /* setTitle(String) */
469:
470: /**
471: * Begin a new table in the report output stream
472: *
473: * @param caption Caption for the table
474: * @param colHeaders A pipe-seperated list of column headers
475: * @throws HtmlException A new table could not be started
476: */
477: public synchronized void startTable(String caption,
478: String colHeaders) throws HtmlException {
479: currentTable = new Table();
480: currentTable.setCaption(caption);
481: currentTable.setBorder(1);
482: currentTable.addHeading(colHeaders);
483: } /* startTable(String, String) */
484:
485: /**
486: * Print the Report Page. Override this in your own derived class to provide
487: * custom printing. Otherwise, this just calls the display() function to
488: * maintain backwards compatibility
489: *
490: * @param os The OutputStream to send to.
491: * @throws ReportException upon error.
492: * @throws IOException upon IO error
493: */
494: public void printReport(OutputStream os) throws ReportException,
495: java.io.IOException {
496: try {
497: java.io.PrintWriter printWriter = new java.io.PrintWriter(
498: os);
499: this .display(printWriter);
500: printWriter.flush();
501: } catch (HtmlException ex) {
502: throw new ReportException("Error producing report", ex);
503: }
504: }
505:
506: /**
507: * Sets the report parameters
508: *
509: * @param parameters Map of parameters
510: */
511: public void setReportParameters(Map parameters) {
512: if (myParams == null) {
513: myParams = new HashMap(parameters.size());
514: }
515: //Put in default parameters, and set in the new ones.
516: if (defaultParams != null) {
517: for (Iterator i = this .defaultParams.iterator(); i
518: .hasNext();) {
519: ReportPageParam param = (ReportPageParam) i.next();
520: myParams.put(param.getCode(), param.getDefaultValue());
521: }
522: }
523:
524: for (Iterator i = parameters.keySet().iterator(); i.hasNext();) {
525: String key = (String) i.next();
526: String value = (String) parameters.get(key);
527: if (value != null && value.length() > 0) {
528: myParams.put(key, value);
529: }
530: }
531: }
532:
533: /**
534: * Protected "getter" function so derived classes can get the
535: * report parameters
536: *
537: * @return java.util.Map
538: */
539: protected Map getReportParameters() {
540: return myParams;
541: }
542:
543: /**
544: * Sets the data context for this report.
545: *
546: * @param newDataContext the new data context
547: */
548: public void setDataContext(String newDataContext) {
549: dbName = newDataContext;
550: }
551:
552: /**
553: * Retrieve the data context for this report.
554: *
555: * @return java.lang.String
556: */
557: protected String getDataContext() {
558: return dbName;
559: }
560:
561: /**
562: * Retrieve the report mime type. In this case, HTML text.
563: *
564: * @return java.lang.String: "text/html"
565: */
566: public String getReportMimeType() {
567: return "text/html";
568: }
569:
570: /**
571: * Retrieve the recommended file extension for the report. Return the
572: * value without the '.'. So an example file extension for an Excel
573: * report would be "xls", and XML formatted report would be
574: * "xml" [although if you're using special XML languages, of course
575: * you have the freedom to specify the extension]
576: *
577: * @return java.lang.String in the format specified above.
578: */
579: public String getReportFileExtension() {
580: return "html";
581: }
582:
583: /**
584: * Retrieve a list of parameters that this report supports. This function
585: * may be blank, in which case, there still could be parameters for the report
586: * but the automatic ui functions such as <code>ReportServer</code> won't
587: * present them as options.
588: *
589: * @return java.util.List of Strings. or null if there are no parameters
590: */
591: public java.util.List getParameterNames() {
592: if (defaultParams != null && defaultParams.size() > 0) {
593: ArrayList al = new ArrayList(defaultParams.size());
594: for (Iterator i = defaultParams.iterator(); i.hasNext();) {
595: ReportPageParam oneparams = (ReportPageParam) i.next();
596: al.add(oneparams.getCode());
597: }
598: return al;
599: } else {
600: return null;
601: }
602: }
603:
604: }
605:
606: /* ReportPage */
|