/* $Log$ Revision 1.4 2003/05/02 07:58:45 heto Changed the package structure from se.prevas.arexis.XYZ to se.arexis.agdb.XYZ Modified configuration and source files according to package change. Revision 1.3 2003/04/25 12:14:46 heto Changed all references to axDefault.css Source layout fixes. Revision 1.2 2003/04/25 09:11:14 heto Error page function added Revision 1.1.1.1 2002/10/16 18:14:07 heto Import of aGDB 1.5 L3 from Prevas CVS-tree. This version of aGDB is migrated to Tomcat from JServ by Tobias Hermansson Revision 1.13 2001/06/18 09:06:30 frob Some new methods, also adopted to changes in Defaults.java. Revision 1.12 2001/06/13 09:30:23 frob Modified interfact of comment method in HTMLWriter, caused updates in several files. Revision 1.11 2001/06/13 06:06:26 frob Changed the structure of the header table produced in HTMLWriter. From now, the table has only two rows. Any other stuff has to be placed within a content table (also produced byt the HTMLWriter). This modification caused updates in several servlets. Revision 1.10 2001/05/31 07:07:16 frob Implemented the writeBottomDefault method in HTMLWriter and removed it from all servlets. The servlets now uses the method in HTMLWriter. Revision 1.9 2001/05/30 09:19:22 frob Rewrote the statistics part of viewProj. Fixed some CSS stuff in HTMLWriter. Some keys added to Defaults.properties and Errors.properties Revision 1.8 2001/05/28 14:37:23 frob New methods, restructured. Revision 1.7 2001/05/28 06:32:28 frob Restructuring, some new elements. Revision 1.6 2001/05/22 06:17:08 roca Backfuncktionality fixed for all (?) servlets/subpages Revision 1.5 2001/05/21 07:03:41 frob Changed debug text in Header table to be consistent. Renamed mainTable to contentTable. Revision 1.4 2001/05/18 06:18:07 frob New method for writing frameset doctype. Revision 1.3 2001/05/17 08:09:40 frob Added comment method + methods for navigator page. Revision 1.2 2001/05/15 12:15:55 frob Moved the default CSS part to a serparate method. Revision 1.1 2001/04/27 12:44:49 frob Initial checkin. */ package se.arexis.agdb.util; import java.io.*; import java.util.*; /** * HTMLWriter is a class that helps to write HTML code. It contains several * methods which will make it easier to generate HTML code from the * application. * * <P>All tables starts with a header table which includes the title of the * page. The table may also includ additional information such as buttons, * text etc. The header table should be created by calling the headerTable * method. * * <P>Most pages then continue with a content table which holds the rest of * the elements of the page. This means that all elements on a page should * be positioned within the content table. There are two ways to create the * content table. Either use the contentTable method, and pass the contents * of the page as a parameter. Or use the methods contentTableStart and * contentTableEnd to start/finish the table. The first alternative is * suitable when few elements are used on the page. If there are many items * on the page, the second alternative is better. * * @author frob * @see Object */ public class HTMLWriter extends Object { ////////////////////////////////////////////////////////////////////// // // Public section // ////////////////////////////////////////////////////////////////////// /** * Write a message to the webpage */ static public void writeErrorPage(PrintWriter out, String head, String message) { out.println("<p><b>" + head + "</b><br>\n"+message+"\n</p>\n"); } /** * Writes a DOCTYPE tag. * * @param out The PrintWriter to write to */ static public void doctype(PrintWriter out) { out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " + "Transitional//EN\""); out.println(" \"http://www.w3.org/TR/html4/loose.dtd\">"); } /** * Writes a frameset DOCTYPE tag. * * @param out The PrintWriter to write to. */ static public void framesetDoctype(PrintWriter out) { out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Frameset//EN\"\n" + " \"http://www.w3.org/TR/REC-html40/frameset.dtd\">"); } /** * Writes a comment tag to the PrintWriter. * * @param out The PrintWriter to write to. * @param comment The comment to write. * @param NLbefore If set to true, a new line is written before the text. * @param NLafter If set to true, a new line is written after the text. */ static public void comment(PrintWriter out, String comment, boolean NLbefore, boolean NLafter) { if (NLbefore) { out.print("\n"); } out.println("<!-- " + comment + " -->"); if (NLafter) { out.print("\n"); } } /** * Opens the HTML tag. * * @param out The PrintWriter to write to. */ static public void openHTML(PrintWriter out) { out.println("<HTML>"); } /** * Closes the HTML tag. * * @param out The PrintWriter to write to. */ static public void closeHTML(PrintWriter out) { out.println("</HTML>"); } /** * Opens the HEAD tag and writes a title tag. * * @param out The PrintWriter to write to. * @param pageTitle The title of the page. */ static public void openHEAD(PrintWriter out, String pageTitle) { out.println("<HEAD>"); out.println(" <TITLE>" + pageTitle + "</TITLE>"); } /** * Closes the HEAD tag. * * @param out The PrintWriter to write to. */ static public void closeHEAD(PrintWriter out) { out.println("</HEAD>"); } /** * Opens the BODY tag. * * @param out The PrintWriter to write to. * @param bodyParams Additional parameters to the body tag. */ static public void openBODY(PrintWriter out, String bodyParams) { out.println("<BODY " + bodyParams + " >"); } /** * Closes the BODY tag. * * @param out The PrintWriter to write to. */ static public void closeBODY(PrintWriter out) { out.println("</BODY>"); } /** * Prints the default CSS settings to the given print writer. * * @param out The PrintWrite to write to. */ static public void defaultCSS(PrintWriter out) { out.println(" <STYLE TYPE=\"text/css\">\n" + " BODY\n" + " {\n"+ " BACKGROUND-COLOR: " + Defaults.BACKGROUND_COLOR + ";\n" + " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 10pt;\n" + " }\n" + "\n" + " H1\n" + " {\n"+ " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 18pt;\n" + " FONT-WEIGHT: bolder;\n" + " }\n" + "\n" + " H2\n" + " {\n"+ " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 14pt;\n" + " FONT-WEIGHT: bolder;\n" + " }\n" + "\n" + " H3\n" + " {\n"+ " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 12pt;\n" + " }\n" + "\n" + " H4\n" + " {\n"+ " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 10pt;\n" + " FONT-WEIGHT: bolder;\n" + " }\n" + "\n" + " TD\n" + " {\n" + " COLOR: black;\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 10pt;\n" + " FONT-WEIGHT: bold;\n" + " }\n" + "\n" + " INPUT\n" + " {\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 9pt;\n" + " FONT-WEIGHT: normal;\n" + " }\n" + "\n" + " SELECT\n" + " {\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 9pt;\n" + " FONT-WEIGHT: normal;\n" + " HEIGHT: 22px;\n" + " }\n" + "\n" + " OPTION\n" + " {\n" + " FONT-FAMILY: Arial, Helvetica, Verdana;\n" + " FONT-SIZE: 9pt;\n" + " FONT-WEIGHT: normal;\n" + " }\n" + " </STYLE>"); } /** * Writes the CSS section used on the navigator page. * * @param out The PrintWriter object to write to. */ static public void navigatorCSS(PrintWriter out) { out.println(" <STYLE TYPE=\"text/css\">\n" + " A\n" + " {\n" + " TEXT-DECORATION: none;\n" + " COLOR: white;\n" + " }\n" + "\n" + " TD\n" + " {\n" + " FONT-FAMILY: Verdana, Helvetica;\n" + " FONT-SIZE: 10pt;\n" + " COLOR: white;\n" + " }\n" + "\n" + " BODY\n" + " {\n" + " BACKGROUND-COLOR: white;\n" + " FONT-WEIGHT: bolder;\n" + " }\n" + " </STYLE>"); } /** * Writes the CSS for middle frames to the given PrintWriter. * * @param out The PrintWriter to write to. */ static public void middleFrameCSS(PrintWriter out) { out.println(" <STYLE TYPE=\"text/css\">\n" + " BODY\n" + " {\n" + " BACKGROUND-COLOR: " + Defaults.BACKGROUND_COLOR + ";\n" + " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 10pt;\n" + " }\n" + "\n" + " TABLE\n" + " {\n"+ " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 8pt;\n" + " MARGIN-RIGHT: 0px;\n" + " MARGIN-LEFT: 2px;\n" + " PADDING-RIGHT: 0px;\n" + " }\n" + "\n" + " TD\n" + " {\n" + " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 8pt;\n" + " }\n" + "\n" + " A\n" + " {\n" + " COLOR: " + Defaults.BACKGROUND_COLOR + ";\n" + " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 8pt;\n" + " TEXT-DECORATION: none;\n" + " }\n" + "\n" + " </STYLE>"); } static public void bottomFrameCSS(PrintWriter out) { out.println(" <STYLE TYPE=\"text/css\">\n" + " BODY\n" + " {\n" + " BACKGROUND-COLOR: " + Defaults.BACKGROUND_COLOR + ";\n" + " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 10pt;\n" + " }\n" + "\n" + " TABLE\n" + " {\n"+ " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 8pt;\n" + " MARGIN-RIGHT: 0px;\n" + " MARGIN-LEFT: 2px;\n" + " PADDING-RIGHT: 0px;\n" + " }\n" + "\n" + " TD\n" + " {\n" + " FONT-FAMILY: Verdana;\n" + " FONT-SIZE: 8pt;\n" + " }\n" + "\n" + " </STYLE>"); } /** * Writes a link to a CSS. * * @param out The PrintWriter to write to. * @param cssURL The URL to the CSS to use. */ static public void css(PrintWriter out, String cssURL) { out.println(" <LINK rel=\"stylesheet\" type=\"text/css\" href=\"" + cssURL + "\">"); } /** * Generates HTML to create a button with a onClick event. * * @param buttonName The name (value) of the button. * @param eventString The event to be linked with the button. * @param buttonWidth The width of the button. * @return The generated HTML. */ static public String button(String buttonName, String eventString, int buttonWidth) { return "<INPUT type=button value=" + buttonName + " style=\"WIDTH: " + Integer.toString(buttonWidth) + "px\" " + "onClick='" + eventString + "'>"; } /** * Generates HTML to create a Back button linked to a onClick event. * * @param eventString The event to be linked to the button. * @return The generated HTML. */ static public String backButton(String eventString) { return button("Back", eventString, Integer.parseInt(Defaults.DEFAULT_BUTTONWIDTH)); } /** * Writes the topmost table on a page. The table has the following * layout: * * +---+-----------------------------------+ * | | pageTitle | * | +-----------------------------------+ * | | | * +---+-----------------------------------+ * * @param out The PrintWriter to write to. * @param borderWidth The width of the table border. * @param pageTitle The text to be used as pageTitle. */ static public void headerTable(PrintWriter out, int borderWidth, String pageTitle) { comment(out, "++++++++++ Header table method, start ++++++++++", true, false); out.println("<TABLE width=846 border=" + Integer.toString(borderWidth) + " cellspacing=0 cellpadding=0>"); comment(out, "Header table, r1", true, false); out.println(" <TR>"); out.println(" <TD width=14 rowspan=2></TD>"); out.println(" <TD width=736 height=15>\n" + " <CENTER>\n" + " <B style=\"font-size: 15pt\">" + pageTitle + "</B>\n" + " </CENTER>\n" + " </TD>"); out.println(" </TR>"); comment(out, "Header table, r2", true, false); out.println(" <TR>"); out.println(" <TD height=2 bgcolor=\"#008B8B\"> </TD>"); out.println(" </TR>"); out.println("</TABLE>"); comment(out, "++++++++++ Header table method, end ++++++++++", false, false); } /** * Writes the content table on a page. This table should be placed after * the header table. The table has the following structure: * <P> * +---+-----------------------------------+ * | | pageContent | * +---+-----------------------------------+ * <P> * * @param out The PrintWriter to write to. * @param borderWidth The border width of the table. * @param pageContent The text to be used as pageContent. */ static public void contentTable(PrintWriter out, int borderWidth, String pageContent) { contentTableStart(out, borderWidth); out.println(pageContent); contentTableEnd(out); } /** * Opens the TABLE tag used for the content table. Opens the table, * opens the first (and only) row. Writes the first column which is * empty and opens the second column which is where the content elements * should be printed. * * @param out The PrintWriter to write to. * @param borderWidth The border of the table. */ static public void contentTableStart(PrintWriter out, int borderWidth) { comment(out, "++++++++++ contentTableStart, start ++++++++++", true, false); out.println("<TABLE border= " + Integer.toString(borderWidth) + " cellspacing=0 cellpadding=0>"); out.println(" <TR>\n" + " <TD width=20></TD>\n" + " <TD>\n" + " <!-- ====== pageContent start ====== -->\n"); } /** * Closes the TABLE tag used for the content table. Closes the second * column on the row an closes the row. Finally, the table is closed. * * @param out The PrintWriter to write to. */ static public void contentTableEnd(PrintWriter out) { out.println(""); out.println(" <!-- ====== pageContent end ====== -->\n" + " </TD>\n" + " </TR>\n" + "</TABLE>"); out.println("<!-- ++++++++++ contentTableEnd, end ++++++++++ -->\n"); } /** * Writes the start of the top table, ie the table used in the top * frame. Opens the TABLE and TR tags * * @param out The PrintWriter to write to. * @param borderWidth The width of the table border. */ static public void topTableStart(PrintWriter out, int borderWidth) { comment(out, "++++++++++ Top table, start ++++++++++", true, false); out.println("<TABLE width=800 border=" + borderWidth + " cellpadding=0 cellspacing=0>\n" + "<TR>\n"); } /** * Writes the end of the top table. Closes the TR and TABLE tags. * * @param out The PrintWriter to write to. */ static public void topTableEnd(PrintWriter out) { out.println("</TR>\n" + "</TABLE>"); comment(out, "++++++++++ Top table, end ++++++++++", false, true); } /** * Writes a selected navigator text. * * @param out The PrintWriter to write to. * @param requestedPage The page to display when the link is clicked. * @param linkText The text to display as the link. */ static public void navigatorSelected(PrintWriter out, String requestedPage, String linkText) { out.println(" <TD width=\"11%\">\n" + " <A HREF=\"mainPage?PAGE=" + requestedPage + "\" target=_top>\n" + " <FONT color=\"#00CED1\">\n" + " <B>" + linkText + "</B>\n" + " </FONT>\n" + " </A>\n" + " </TD>"); } /** * Writes a non selected navigator text. * * @param out The PrintWriter to write to. * @param requestedPage The page to display when the link is clicked. * @param linkText The text to display as the link. */ static public void navigatorNotSelected(PrintWriter out, String requestedPage, String linkText) { out.println(" <TD width=\"11%\" >\n" + " <A HREF=\"mainPage?PAGE=" + requestedPage + "\" target=_top>\n" + " <B>" + linkText + "</B>\n" + " </A>\n" + " </TD>"); } /** * Writes the opening TABLE tag for the details table. * * @param out The PrintWriter to write to. * @param borderSize The size of the table border. */ static public void openDetailsTable(PrintWriter out, int borderSize) { comment(out, "++++++++++ Detatils table, start ++++++++++", true, false); out.println("<TABLE width=\"100%\" border=" + borderSize + ">"); } /** * Writes the static table on a separate row in the details table. * * @param out The PrintWriter to write to. * @param data[][] The data to print. * @param borderSize The size of the table border. */ static public void detailsStaticDataTable(PrintWriter out, String data[][], int borderSize) { out.println("<TR>\n" + " <TD>"); comment(out, "++++++++++ Details static data table, start ++++++++++", true, false); out.println(" <TABLE border= " + borderSize + " cellSpacing=3>\n" + " <TR>\n" + " <TD nowrap colspan=2 bgcolor=lightgrey>\n" + " <FONT size=\"+1\">Static data</FONT>\n" + " </TD>\n" + " </TR>"); for (int i = 0; i < data.length; i ++) { out.println(" <TR>\n" + " <TD nowrap>" + data[i][0] + ": </TD>\n" + " <TD nowrap>" + data[i][1] + "</TD>\n" + " </TR>"); } out.println(" </TABLE>"); out.println("<!-- ++++++++++ Details, static data table, end ++++++++++ -->\n"); out.println(" </TD>\n" + "</TR>\n"); } /** * Writes the data table on a separate row in the detail table. * * @param out The PrintWriter to write to. * @param columnTitles The column titles to use. * @param dataVector The data to print. * @param borderSize The size of the table border. */ static public void detailsDataTable(PrintWriter out, String[] columnTitles, Vector dataVector, int borderSize) { out.println("\n<TR>\n" + " <TD>"); comment(out, "++++++++++ Details data table, start ++++++++++", true, false); out.println(" <TABLE align=center border=" + borderSize + " cellSpacing=0 width=800px>"); comment(out, "Data table, r1: table header", true, false); out.println(" <TR bgcolor=Black>\n" + " <TD align=center colspan=10 nowrap>\n" + " <FONT color=\"#ffffff\">Current Data</FONT>\n" + " </TD>\n" + " </TR>"); comment(out, "Data table, r2: column headers", true, false); out.println(" <TR bgcolor= \"#008B8B\">"); for (int i = 0; i < columnTitles.length; i++) { out.println(" <TD nowrap>" + columnTitles[i] + "</TD>"); } out.println(" </TR>"); // Loop all data in the dataVector and print it String[] currentData, previousData; comment(out, "Data table, r3: current data", true, false); for (int dataRow = 0; dataRow < dataVector.size(); dataRow++) { // Get the data at the current row and remove any null values. currentData = (String[]) dataVector.elementAt(dataRow); currentData = clearNullDetailData(currentData); // If there is previous data, get it. Also clear any null values. if (dataRow + 1 < dataVector.size()) { previousData = (String[]) dataVector.elementAt(dataRow + 1); previousData = clearNullDetailData(previousData); } else { previousData = null; } // Write the detail row writeDetailRow(out, currentData, previousData, dataRow); // If this is the first row, write the history header if (dataRow == 0) { comment(out, "Data table, r4: history header", true, false); out.println(" <TR bgcolor=Black>\n" + " <TD align=center colspan=10>\n" + " <FONT color=\"#ffffff\">History</FONT>\n" + " </TD>\n" + " </TR>"); comment(out, "Data table, r5 - rx: history data", true, false); } } out.println(" </TABLE>"); out.println("<!-- ++++++++++ Details data table, end ++++++++++ -->\n"); out.println(" </TD>\n" + "</TR>\n"); } /** * Writes a buttons table on a separate row in the detatails table. * * @param out The PrintWriter to write to. * @param backButtonOnClick The event string to be used with the back * button. * @param additionalHTML Any additional HTML to be written in the * table. * @param borderSize The size of the table border. */ public static void detailsButtonTable(PrintWriter out, String backButtonOnClick, String additionalHTML, int borderSize) { out.println("\n<TR>\n" + " <TD>"); comment(out, "++++++++++ Details button table, start ++++++++++", true, false); out.println(" <TABLE cellspacing=0 cellpadding=0 border=" + borderSize + ">\n" + " <TR>\n" + " <TD>\n" + " <FORM action=\"\">\n" + backButton(backButtonOnClick) + "\n" + additionalHTML + "\n" + " </FORM>\n" + " </TD>\n" + " </TR>\n" + " </TABLE>"); comment(out, "++++++++++ Details button table, end ++++++++++", false, true); out.println(" </TD>\n" + "</TR>"); } /** * Writes an emtpy table row. * * @param out The PrintWriter to write to. */ static public void emptyTableRow(PrintWriter out) { out.println("<TR>\n" + " <TD> </TD>\n" + "</TR>"); } static public void writeBottomDefault(PrintWriter out) { doctype(out); openHEAD(out, ""); defaultCSS(out); closeHEAD(out); openBODY(out, ""); out.println("<TABLE width=700>\n" + "<TR>\n" + " <TD>\n" + " <CENTER><H4>Nothing selected</H4></CENTER>\n" + " </TD>\n" + "</TR>\n" + "</TABLE>"); closeBODY(out); closeHTML(out); } /** * Writes the start of a top page. This includes the doctype, the * header, the CCS. Furhtermore, the body tag is opened as well as the * form tag. * * @param out The PrintWriter to write to. * @param servletPath The path to use with the action parameter in the * form tag. */ static public void startTopPage(PrintWriter out, String servletPath) { // Write the start of the page. doctype(out); openHTML(out); openHEAD(out, ""); defaultCSS(out); // Any new pages should be placed in a frame named "content", // defined by the frameset in mainPage out.println("<BASE target=\"content\">"); closeHEAD(out); comment(out, "", true, false); // Start writing the body. openBODY(out, ""); out.println("<FORM method=get action=\"" + servletPath + "\">"); } /** * Writes the start of the middle page. Writes the doctype, header, CSS, * opens the body and writes the info line. * * @param out The PrintWriter to write to. * @param action The current action. * @param startIndex The index of the first item to display. * @param itemsToDisplay Total number of items to display. * @param maxRows Max number of rows on each page. */ static public void startMiddlePage(PrintWriter out, String action, int startIndex, int itemsToDisplay, int maxRows) { doctype(out); openHEAD(out, ""); middleFrameCSS(out); out.println(" <BASE target=\"content\">"); closeHEAD(out); openBODY(out, ""); out.println(" " + buildInfoLine(action, startIndex, itemsToDisplay, maxRows)); } /** * Opens the table used in the middle page. Opens the table, the first * row and writes an emtpy first column. * * @param out The PrintWriter to write to. * @param borderWidth The size of the border of the table. * @param tableWidth The width of the table. */ static public void startMiddlePageTable(PrintWriter out, int borderWidth, int tableWidth) { out.println("<TABLE bgcolor=\"" + Defaults.TABLEHEADER_COLOR + "\" border=" + borderWidth + " cellpadding=0" + " cellspacing=0 width=" + tableWidth + ">\n" + "<TR>"); out.println(" <TD width=5 height=20></TD>"); } /** * Writes a column header in the middle table. * * @param out The PrinWriter to write to. * @param columnWidth The width of the current colum. * @param servletPath The path to the servlet to be realted with the * link on the column header. * @param queryString The query string to add to the servlet path. * @param currentOrderBy The current value of the orderBy parameter. * @param columnText The text to be displayed in the header. * @param newOrderBy The orderBy value to use in the query string. */ public static void writeMiddleDetailsHeader(PrintWriter out, int columnWidth, String servletPath, String queryString, String currentOrderBy, String columnText, String newOrderBy) { // Start writing the column. The column will contain a HREF element // with ACTION and ORDERBY parameter. out.println(" <TD width=" + columnWidth + ">\n" + " <A HREF=\"" + servletPath + "?ACTION=" + Defaults.ACTION_DISPLAY + "&" + queryString + "&ORDERBY=" + newOrderBy + "\">"); if (newOrderBy.equals(currentOrderBy)) { out.println(" <FONT color=\"" + Defaults.MIDDLE_SELECTED_COLOR + "\">\n" + " <B>" + columnText + "</B>\n" + " </FONT>\n" + " </A>\n" + " </TD>"); } else { out.println(" " + columnText + "\n" + " </A>\n" + " </TD>"); } } static public void startBottomPage(PrintWriter out, int borderWidth) { doctype(out); openHTML(out); openHEAD(out, ""); bottomFrameCSS(out); closeHEAD(out); openBODY(out, ""); out.println("<TABLE border=0 cellpadding=0 cellspacing=0 width=" + borderWidth + ">"); } ////////////////////////////////////////////////////////////////////// // // Protected section // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // // Private section // ////////////////////////////////////////////////////////////////////// /** * Replaces any null elements in the array with blanks (""). * * @param detailRow The array to modify. * @return The modified array. */ static private String[] clearNullDetailData(String[] detailRow) { for (int col = 0; col < detailRow.length; col++) { if (detailRow[col] == null) { detailRow[col] = ""; } } return detailRow; } /** * Writes a row in the detail table. Current data is compared to the * previous data and any modified value will be displayed in red to * highlihgt the modification. * * @param out The PrintWriter to write to. * @param currentData An array with current data. * @param previousData An array with previous data. * @param rowNumber The current row of data. */ static private void writeDetailRow(PrintWriter out, String[] currentData, String[] previousData, int rowNumber) { // Set background depending on row number if (rowNumber == 0 || rowNumber == 1 || rowNumber % 2 != 0) { out.println(" <TR bgcolor=white>"); } else { out.println(" <TR bgcolor=lightgrey>"); } // No current data given, this is a serious error! if (currentData == null) { Errors.logError("HTMLWriter.writeDetailRow: currentData is null!"); } // No previous data given, means this is the last row to write else if (previousData == null) { for(int cols = 0; cols < currentData.length; cols++) { writeDetailCell(out, true, currentData[cols]); } } // Both current and previous data given else { String currentDataCol; // Holds data from the current column. boolean unmodifiedValue; // Is value unmodified since previous version? // Loop columns in current data for (int col = 0; col < currentData.length; col++) { currentDataCol = currentData[col]; // If this is the last column of data (which is the time // stamp), indicate that the value should be printed as // unmodified as this value will always change. if ((col + 1) == currentData.length) { unmodifiedValue = true; } // This is not the timestampt. Compare current value with // previous value and set unmodifiedValue. else { // There are some history date unmodifiedValue = currentDataCol.equalsIgnoreCase(previousData[col]); } // Write the data cell writeDetailCell(out, unmodifiedValue, currentDataCol); } } out.println(" </TR>"); } /** * Writes one cell of data in the detail table. * * @param out The PrintWriter to write to. * @param unmodifiedValue Is value unmodified or not? * @param cellValue The value of the cell. */ static private void writeDetailCell(PrintWriter out, boolean unmodifiedValue, String cellValue) { if (cellValue == null || cellValue == "") { cellValue = " "; } // If value is modified, add FONT-tag to the value. if (!unmodifiedValue) { cellValue = "\n <FONT color=red>" + cellValue + "</FONT>\n "; } out.println(" <TD nowrap>" + cellValue + "</TD>"); } /** * Builds the infoline to be displayed in the middle frame. The line * contains information about the object to be displayed in the bottom frame. * * @param requestedAction The current action. * @param startIndex The index to start with. * @param rows Total number of rows to display. * @param maxRows Maximum number of rows to display on one page. * @return The info line. */ private static String buildInfoLine(String requestedAction, int startIndex, int rows, int maxRows) { String resultString = null; // Calculate the upper limit, ie the index of the last item to // display int upperLimit = startIndex + maxRows - 1; // If upperlimit to high, adjust it if (upperLimit > rows) { upperLimit = rows; } // If no rows to display, adjust startIndex if (rows == 0) { startIndex = 0; } if (!Utils.assigned(requestedAction) || Utils.blank(requestedAction)) { resultString = " "; } // Build the result string by calculating the row numbers to // display. Is done differently depending on the requested action else if (requestedAction.equals(Defaults.ACTION_FIRST) || requestedAction.equals(Defaults.ACTION_PREV) || requestedAction.equals(Defaults.ACTION_NEXT) || requestedAction.equals(Defaults.ACTION_LAST) || requestedAction.equals(Defaults.ACTION_DISPLAY)) { resultString = "Displaying " + startIndex + "-" + upperLimit + " of " + rows + " rows."; } else if (requestedAction.equals(Defaults.ACTION_COUNT)) { // Count the number of rows this filter will return resultString = "Query will return " + rows + " row(s)."; } // Unknown action else { resultString = new String("?" + requestedAction + "?"); } return resultString; } }