001 package railo.runtime.tag; 002 003 import java.io.IOException; 004 005 import org.apache.commons.lang.StringUtils; 006 007 import railo.runtime.exp.ExpressionException; 008 import railo.runtime.exp.PageException; 009 import railo.runtime.ext.tag.BodyTagTryCatchFinallyImpl; 010 import railo.runtime.functions.string.CJustify; 011 import railo.runtime.functions.string.LJustify; 012 import railo.runtime.functions.string.RJustify; 013 import railo.runtime.op.Caster; 014 015 /** 016 * Builds a table in a CFML page. Use the cfcol tag to define table column and row 017 * characteristics. The cftable tag renders data either as preformatted text, or, with the HTMLTable 018 * attribute, as an HTML table. Use cftable to create tables if you don't want to write HTML table tag 019 * code, or if your data can be well presented as preformatted text. 020 * 021 * 022 * 023 **/ 024 public final class Table extends BodyTagTryCatchFinallyImpl { 025 026 /** 027 * Field <code>ALIGN_LEFT</code> 028 */ 029 public static final short ALIGN_LEFT=0; 030 /** 031 * Field <code>ALIGN_CENTER</code> 032 */ 033 public static final short ALIGN_CENTER=1; 034 /** 035 * Field <code>ALIGN_RIGHT</code> 036 */ 037 public static final short ALIGN_RIGHT=2; 038 039 /** Name of the cfquery from which to draw data. */ 040 private railo.runtime.type.Query query; 041 042 /** Maximum number of rows to display in the table. */ 043 private int maxrows=Integer.MAX_VALUE; 044 045 /** Specifies the query row from which to start processing. */ 046 private int startrow=1; 047 048 /** Adds a border to the table. Use only when you specify the HTMLTable attribute for the table. */ 049 private boolean border; 050 051 /** Displays headers for each column, as specified in the cfcol tag. */ 052 private boolean colheaders; 053 054 /** Number of spaces to insert between columns 'default is 2'. */ 055 private int colspacing=2; 056 057 /** Renders the table as an HTML 3.0 table. */ 058 private boolean htmltable; 059 060 /** Number of lines to use for the table header. The default is 2, which leaves one line between 061 ** the headers and the first row of the table. */ 062 private int headerlines=2; 063 064 StringBuffer header=new StringBuffer(); 065 StringBuffer body=new StringBuffer(); 066 067 private int initRow; 068 069 private int count=0; 070 private boolean startNewRow; 071 072 /** 073 * @see javax.servlet.jsp.tagext.Tag#release() 074 */ 075 public void release() { 076 super.release(); 077 query=null; 078 maxrows=Integer.MAX_VALUE; 079 startrow=1; 080 border=false; 081 colheaders=false; 082 colspacing=2; 083 htmltable=false; 084 headerlines=2; 085 if(header.length()>0)header=new StringBuffer(); 086 body=new StringBuffer(); 087 count=0; 088 } 089 090 /** set the value query 091 * Name of the cfquery from which to draw data. 092 * @param query value to set 093 * @throws PageException 094 **/ 095 public void setQuery(String query) throws PageException { 096 this.query = Caster.toQuery(pageContext.getVariable(query)); 097 } 098 099 /** set the value maxrows 100 * Maximum number of rows to display in the table. 101 * @param maxrows value to set 102 **/ 103 public void setMaxrows(double maxrows) { 104 this.maxrows=(int)maxrows; 105 } 106 107 /** set the value startrow 108 * Specifies the query row from which to start processing. 109 * @param startrow value to set 110 **/ 111 public void setStartrow(double startrow) { 112 this.startrow=(int)startrow; 113 if(this.startrow<=0)this.startrow=1; 114 } 115 116 /** set the value border 117 * Adds a border to the table. Use only when you specify the HTMLTable attribute for the table. 118 * @param border value to set 119 **/ 120 public void setBorder(boolean border) { 121 this.border=border; 122 } 123 124 /** set the value colheaders 125 * Displays headers for each column, as specified in the cfcol tag. 126 * @param colheaders value to set 127 **/ 128 public void setColheaders(boolean colheaders) { 129 this.colheaders=colheaders; 130 } 131 132 /** set the value colspacing 133 * Number of spaces to insert between columns 'default is 2'. 134 * @param colspacing value to set 135 **/ 136 public void setColspacing(double colspacing) { 137 this.colspacing=(int)colspacing; 138 } 139 140 /** set the value htmltable 141 * Renders the table as an HTML 3.0 table. 142 * @param htmltable value to set 143 **/ 144 public void setHtmltable(boolean htmltable) { 145 this.htmltable=htmltable; 146 } 147 148 /** set the value headerlines 149 * Number of lines to use for the table header. The default is 2, which leaves one line between 150 * the headers and the first row of the table. 151 * @param headerlines value to set 152 **/ 153 public void setHeaderlines(double headerlines) { 154 this.headerlines=(int)headerlines; 155 if(this.headerlines<2)this.headerlines=2; 156 } 157 158 159 /** 160 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 161 */ 162 public int doStartTag() throws PageException { 163 startNewRow=true; 164 initRow=query.getRecordcount(); 165 query.go(startrow); 166 pageContext.undefinedScope().addCollection(query); 167 return query.getRecordcount()>=startrow?EVAL_BODY_INCLUDE:SKIP_BODY; 168 } 169 170 /** 171 * @see javax.servlet.jsp.tagext.BodyTag#doInitBody() 172 */ 173 public void doInitBody() { 174 //if(htmltable) body.append("<tr>\n"); 175 } 176 177 /** 178 * @see javax.servlet.jsp.tagext.BodyTag#doAfterBody() 179 */ 180 public int doAfterBody() throws PageException { 181 if(htmltable) body.append("</tr>\n"); 182 else body.append('\n'); 183 startNewRow=true; 184 //print.out(query.getCurrentrow()+"-"+query.getRecordcount()); 185 return ++count<maxrows && query.next()?EVAL_BODY_AGAIN:SKIP_BODY; 186 } 187 188 /** 189 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 190 */ 191 public int doEndTag() throws PageException { 192 try { 193 _doEndTag(); 194 } catch (IOException e) { 195 throw Caster.toPageException(e); 196 } 197 return EVAL_PAGE; 198 } 199 private void _doEndTag() throws IOException { 200 if(htmltable) { 201 pageContext.forceWrite("<table colspacing=\""+colspacing+"\""); 202 if(border) { 203 pageContext.forceWrite(" border=\"1\""); 204 } 205 pageContext.forceWrite(">\n"); 206 if(header.length()>0) { 207 pageContext.forceWrite("<tr>\n"); 208 pageContext.forceWrite(header.toString()); 209 pageContext.forceWrite("</tr>\n"); 210 } 211 pageContext.forceWrite(body.toString()); 212 pageContext.forceWrite("</table>"); 213 } 214 else { 215 pageContext.forceWrite("<pre>"); 216 if(header.length()>0) { 217 pageContext.forceWrite(header.toString()); 218 pageContext.forceWrite(StringUtils.repeat("\n",headerlines-1)); 219 } 220 pageContext.forceWrite(body.toString()); 221 pageContext.forceWrite("</pre>"); 222 } 223 } 224 225 /** 226 * @see javax.servlet.jsp.tagext.TryCatchFinally#doFinally() 227 */ 228 public void doFinally() { 229 try { 230 pageContext.undefinedScope().removeCollection(); 231 if(query!=null)query.go(initRow); 232 } 233 catch (PageException e) { } 234 } 235 236 /** 237 * @param strHeader 238 * @param text 239 * @param align 240 * @param width 241 * @throws ExpressionException 242 */ 243 public void setCol(String strHeader, String text, short align, int width) throws ExpressionException { 244 // HTML 245 if(htmltable) { 246 if(colheaders && count==0 && strHeader.trim().length()>0) { 247 header.append("\t<th"); 248 addAlign(header,align); 249 addWidth(header,width); 250 header.append(">"); 251 header.append(strHeader); 252 header.append("</th>\n"); 253 } 254 if(htmltable && startNewRow) { 255 body.append("<tr>\n"); 256 startNewRow=false; 257 } 258 259 body.append("\t<td"); 260 addAlign(body,align); 261 addWidth(body,width); 262 body.append(">"); 263 body.append(text); 264 body.append("</td>\n"); 265 } 266 // PRE 267 else { 268 if(width<0) width=20; 269 if(colheaders && count==0 && strHeader.trim().length()>0) { 270 addPre(header,align,strHeader,width); 271 } 272 addPre(body,align,text,width); 273 274 } 275 } 276 277 private void addAlign(StringBuffer data,short align) { 278 data.append(" align=\""); 279 data.append(toStringAlign(align)); 280 data.append("\""); 281 } 282 283 private void addWidth(StringBuffer data,int width) { 284 if(width>=-1) { 285 data.append(" width=\""); 286 data.append(width); 287 data.append("%\""); 288 } 289 } 290 291 private void addPre(StringBuffer data,short align,String value, int length) throws ExpressionException { 292 if(align==ALIGN_RIGHT) data.append(RJustify.call(pageContext,value,length)); 293 else if(align==ALIGN_CENTER) data.append(CJustify.call(pageContext,value,length)); 294 else data.append(LJustify.call(pageContext,value,length)); 295 296 } 297 298 private String toStringAlign(short align) { 299 if(align==ALIGN_RIGHT) return "right"; 300 if(align==ALIGN_CENTER) return "center"; 301 return "left"; 302 } 303 }