00001 #ifndef LIST_BASE_HPP
00002 #define LIST_BASE_HPP
00003
00004 #include <iostream>
00005 #include <iomanip>
00006 #include "ocTypes.h"
00007 #include "ocString.h"
00008 #include "read_base.hpp"
00009 #include "cgiClass.h"
00010 #include "cgiTemplates.h"
00011 #include "cgiCookie.h"
00012
00013 #define DEBUGOUT
00014
00015 typedef map <string,string> courtesy_args;
00016
00017 class list_base: public read_base
00018 {
00019 protected:
00020 cgiTemplates listTemplate;
00021 cgiScript & webIO;
00022 cgiCookie cookie;
00023 courtesy_args crtsy_args;
00024 ocString td;
00025 public:
00026 bool opened;
00028 ocString editLink;
00030 int hotCol;
00031 int skipCol;
00032 string addedCriteria;
00033
00034
00035
00036
00037
00038 string courtesyFormFields( void )
00039 {
00040 string ret;
00041 courtesy_args::iterator pos;
00042 for( pos=crtsy_args.begin();pos!=crtsy_args.end();++pos)
00043 {
00044 ret+="<input type='hidden' name='";
00045 ret+=pos->first;
00046 ret+="' value='";
00047 ret+=pos->second;
00048 ret+="'>";
00049 }
00050 return ret;
00051 }
00052
00053
00054
00055
00056
00057
00058 string courtesyQueryString( string start = "" )
00059 {
00060 bool started=false;
00061 string ret = start;
00062 courtesy_args::iterator pos;
00063 for( pos=crtsy_args.begin();pos!=crtsy_args.end();++pos)
00064 {
00065 if(started) ret+="&";
00066 ret+=pos->first;
00067 ret+="=";
00068 ret+=pos->second;
00069 started = true;
00070 }
00071 if(!started) ret="";
00072 return ret;
00073 }
00074
00075
00076 string cookiePrefix;
00077 string filter, sort, direction;
00078 int listPg, itemsPerPg, recCount, colCount, pgCount, dsetCount;
00079
00080
00081
00082
00083
00084 void addCourtesyArg( string name, string value = "" )
00085 {
00086 crtsy_args[name] = value;
00087 }
00088 void setPage( cgiInput & args )
00089 {
00090 listPg = atol(cookie.get("lPg").c_str());
00091 if (args.count("Pg") )
00092 {
00093 listPg = (atol(args["Pg"].c_str())-1);
00094 }
00095 else if(args.count("navigate") )
00096 {
00097 if( args["navigate"] == "prev" ) listPg--;
00098 if( args["navigate"] == "next" ) listPg++;
00099 }
00100 if( listPg < 0 ) listPg = 0;
00101 }
00102 string limitClause( void )
00103 {
00104 int rowStart = listPg * itemsPerPg;
00105 ocString limit = " limit ";
00106 if( db.getProvider() == MySQL )
00107 {
00108 limit.append(rowStart);
00109 limit += ", ";
00110 limit.append(itemsPerPg);
00111 }
00112 else if( db.getProvider() == PostGresQL )
00113 {
00114 limit.append(itemsPerPg);
00115 limit += " offset ";
00116 limit.append(rowStart);
00117 }
00118 return limit;
00119 }
00120 void setSort( cgiInput & args )
00121 {
00122 direction = cookie.get("lDir");
00123 sort = cookie.get("lSort");
00124
00125 if (args.count("sort") )
00126 {
00127 if( sort == args["sort"].c_str() )
00128 {
00129
00130 direction = direction=="desc"?"asc":"desc";
00131 cookie.set("lDir",direction.c_str());
00132 }
00133 sort = args["sort"].c_str();
00134 cookie.set("lSort",sort.c_str());
00135 }
00136 }
00137
00138
00139
00140
00141
00142
00143 void reset( cgiInput & args )
00144 {
00145 if( args.count("init") )
00146 {
00147
00148 cookie.set("lFilter","");
00149 cookie.set("lDir","");
00150 cookie.set("lSort","");
00151 cookie.set("lPg","");
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160 void setFilter( cgiInput & args )
00161 {
00162 if( webIO.RequestMethod().upper() == "GET" )
00163 {
00164 filter = cookie.get("lFilter");
00165 }
00166 if( args.count("filter") )
00167 {
00168 filter = args["filter"].c_str();
00169 cookie.set("lFilter",filter.c_str());
00170 }
00171 }
00172
00173
00174
00175
00176 list_base(cgiScript&sc):read_base(),webIO(sc),opened(false),hotCol(0),skipCol(-1)
00177 ,listPg(0), itemsPerPg(20), recCount(0), colCount(0)
00178 ,pgCount(0), dsetCount(0)
00179 {
00180 cgiInput & args = sc.ClientArguments();
00181 reset( args );
00182
00183 setSort( args );
00184
00185 setFilter( args );
00186
00187 setPage( args );
00188 }
00189
00190 virtual ~list_base(){;}
00191
00192 bool loadListTemplates( string path )
00193 {
00194 return listTemplate.load(path.c_str());
00195 }
00196 list_base & copyListTemplates( const cgiTemplates & in )
00197 {
00198 listTemplate = in;
00199 return * this;
00200 }
00201 bool getData( string sql )
00202 {
00203 opened = rs.open(sql);
00204 if( opened ) recCount = rs.getRecordCount();
00205 return opened;
00206 }
00207
00208 string whereClause( ocString & filterTemplate )
00209 {
00210 string sql = "";
00211 if( filter.length() )
00212 {
00213 filterTemplate.parseInit();
00214 sql += " where ";
00215 ocString filterParts = filter;
00216 string filterPart = filterParts.parse("|");
00217 ocString filterTemp = filterTemplate.parse("|");
00218 do
00219 {
00220 sql += filterTemp.replace("$filter$", filterPart.c_str() );
00221 filterTemp = filterTemplate.parse("|");
00222 filterPart = filterParts.parse("|");
00223 if(sql.length()&&filterTemp.length()) sql += " and ";
00224 } while( !(filterTemplate.endOfParse() && filterTemp.length()==0) );
00225 }
00226 if( addedCriteria.length() )
00227 {
00228 sql += ( filter.length() ) ? " and " : " where ";
00229 sql += addedCriteria;
00230 }
00231 return sql;
00232 }
00233
00234 void maxPageFixup( void )
00235 {
00236 pgCount = (recCount/itemsPerPg)+1;
00237 if( listPg >= pgCount ) listPg = pgCount-1;
00238 }
00239 bool getFilteredData( string rows,
00240 string table,
00241 ocString filterTemplate,
00242 string defaultSort = "",
00243 string groupBy = "",
00244 string countTable = "" )
00245 {
00246
00247 string sql = "select count(*) from ";
00248 sql += countTable.length()?countTable:table;
00249 sql += whereClause( filterTemplate );
00250 #ifdef DEBUGOUT
00251 webIO << "<!--" << sql << "-->";
00252 #endif
00253 opened = rs.open(sql);
00254 if( opened )
00255 {
00256 recCount = atol(rs.getField(0).format().c_str());
00257 maxPageFixup();
00258 rs.close();
00259 }
00260
00261 sql = "select ";
00262 sql += rows;
00263 sql += " from ";
00264 sql += table;
00265 sql += whereClause( filterTemplate );
00266 if( groupBy.length() )
00267 {
00268 sql += " group by ";
00269 sql += groupBy;
00270 }
00271 if( sort.length() )
00272 {
00273 sql += " order by ";
00274 sql += sort;
00275 sql += " ";
00276 sql += direction;
00277 }
00278 else if ( defaultSort.length() )
00279 {
00280 sql += " order by ";
00281 sql += defaultSort;
00282 }
00283 sql += limitClause();
00284 #ifdef DEBUGOUT
00285 webIO << "<!--" << sql << "-->";
00286 #endif
00287 opened = rs.open(sql);
00288 if( opened )
00289 {
00290 dsetCount = rs.getRecordCount();
00291 }
00292 return opened;
00293 }
00294 list_base & emitFilter( string program, string label )
00295 {
00296 string value;
00297 if( webIO.ClientArguments().count("filter") )
00298 {
00299 value = webIO.ClientArguments()["filter"].c_str();
00300 }
00301 ocString filterform = listTemplate.getParagraph("list_filter");
00302 if( program.find("?") != string::npos )
00303 {
00304 filterform = filterform.replace("?","&");
00305 }
00306 webIO << filterform.replaceAll( "$location", program.c_str())
00307 .replaceAll("$label",label.c_str())
00308 .replace("$value", value.c_str() );
00309 }
00310
00311 list_base & emitFilters( string program, ocString labels )
00312 {
00313 ocString values;
00314 if( webIO.ClientArguments().count("filter") )
00315 {
00316 values = webIO.ClientArguments()["filter"].c_str();
00317 }
00318 ocString fstart = listTemplate.getParagraph("multi_filter_start");
00319 ocString fitem = listTemplate.getParagraph("multi_filter_item");
00320 ocString fend = listTemplate.getParagraph("multi_filter_end");
00321
00322 if( program.find("?") != string::npos )
00323 {
00324 fstart = fstart.replace("?","&");
00325 }
00326 webIO << fstart.replaceAll( "$location", program.c_str());
00327 ocString label = labels.parse("|");
00328 ocString nlabel = label.parse(":");
00329 string typeSection = label.parse(":");
00330 string value = values.parse("|");
00331 do
00332 {
00333
00334 if(typeSection.length())
00335 {
00336 ocString fAltItem = listTemplate.getParagraph(typeSection);
00337 webIO << fAltItem.replaceAll("$label",nlabel.c_str()).replace("$value", value.c_str() );
00338 }
00339 else
00340 {
00341 webIO << fitem.replaceAll("$label",label.c_str()).replace("$value", value.c_str() );
00342 }
00343 value = values.parse("|");
00344 label = labels.parse("|");
00345 nlabel = label.parse(":");
00346 typeSection = label.parse(":");
00347 } while ( ! (labels.endOfParse() && label.length()==0) );
00348
00349 webIO << fend.replaceAll( "$location", program.c_str());
00350 }
00351 list_base & emitHeadings( string pipedelimited )
00352 {
00353 ocString headings(pipedelimited);
00354 string list_begin = listTemplate.getParagraph("list_begin");
00355 string tr = listTemplate.getParagraph("tr");
00356 ocString th = listTemplate.getParagraph("th");
00357 string end_tr = listTemplate.getParagraph("end_tr");
00358 webIO << list_begin << tr;
00359 while( ! headings.endOfParse() )
00360 {
00361 colCount++;
00362 string heading = headings.parse("|");
00363 webIO << th.replace( "$data$", heading.c_str() );
00364 }
00365 webIO << end_tr;
00366 return * this;
00367 }
00368 list_base & emitNavigation( string program )
00369 {
00370 ocString numcols, curPage, numPages,datasetCount,recordCount;
00371 numcols.append(colCount);
00372 curPage.append(listPg+1);
00373 numPages.append(pgCount);
00374 datasetCount.append(dsetCount);
00375 recordCount.append(recCount);
00376
00377 ocString nav = listTemplate.getParagraph("list_nav");
00378 if( program.find("?") == string::npos )
00379 {
00380 nav = nav.replaceAll("$cols",numcols.c_str())
00381 .replaceAll("$location",program.c_str())
00382 .replace("$Page",curPage.c_str())
00383 .replace("$total$",numPages.c_str())
00384 .replace("$dsetCount", datasetCount.c_str())
00385 .replace("$recCount", recordCount.c_str());
00386 }
00387 else
00388 {
00389 program += "&";
00390 nav = nav.replaceAll("$cols",numcols.c_str())
00391 .replaceAll("$location?",program.c_str())
00392 .replace("$Page",curPage.c_str())
00393 .replace("$total$",numPages.c_str())
00394 .replace("$dsetCount", datasetCount.c_str())
00395 .replace("$recCount", recordCount.c_str());
00396 }
00397 if( crtsy_args.size() )
00398 {
00399 string qryRep = courtesyQueryString( "prev&" );
00400 nav = nav.replace( "prev", qryRep.c_str() );
00401 qryRep = courtesyFormFields();
00402 nav = nav.replace("<!--hiddenfields-->",qryRep.c_str() );
00403 qryRep = courtesyQueryString( "next&" );
00404 nav = nav.replace( "next", qryRep.c_str() );
00405 }
00406 webIO << nav;
00407 return * this;
00408 }
00409
00410 list_base & emitEnd( void )
00411 {
00412 ocString list_end = listTemplate.getParagraph("list_end");
00413 ocString lPg;
00414 lPg.append(listPg);
00415 webIO << list_end.replace("$lpg",lPg.c_str());
00416 return * this;
00417 }
00418
00419 void setColFormat( string fmt, int pos )
00420 {
00421 if( pos < rs.getFieldCount() )
00422 {
00423 rs.getField(pos).setFormatMask(fmt);
00424 }
00425 }
00426
00427 list_base & emitData( void )
00428 {
00429 bool more_data = opened;
00430 string tr = listTemplate.getParagraph("tr");
00431 td = listTemplate.getParagraph("td");
00432 string end_tr = listTemplate.getParagraph("end_tr");
00433 int fieldCount;
00434 if( opened ) fieldCount = rs.getFieldCount();
00435 derived_commence_event();
00436 while( more_data )
00437 {
00438 if( derived_predata_event() )
00439 {
00440 webIO << tr;
00441 for( int i=0; i < fieldCount; ++i )
00442 {
00443 if( i == hotCol || hotCol == -2 )
00444 {
00445 sendHotField(i, td );
00446 }
00447 else if( i != skipCol )
00448 {
00449 sendField(i, td );
00450 }
00451 }
00452 webIO << end_tr;
00453 }
00454 derived_data_event();
00455 more_data = rs.next();
00456 }
00457 dsetCount = rs.getRecordCount();
00458 derived_complete_event();
00459 return * this;
00460 }
00461
00462
00463 virtual void sendField( int iField, ocString & td )
00464 {
00465 webIO << td.replace( "$data$", rs.getField(iField).format().c_str() );
00466 }
00467
00468
00469 virtual void sendHotField( int iField, ocString & td )
00470 {
00471 webIO << td.replace( "$data$",
00472 editLink.replaceAll( "$key$",rs.getField(0).format().c_str())
00473 .replaceAll( "$col$",rs.getField(iField).format().c_str()).c_str());
00474 }
00475
00476
00477 virtual void derived_commence_event( void ){;}
00478 virtual bool derived_predata_event( void ){ return true; }
00479 virtual void derived_data_event( void ){;}
00480 virtual void derived_complete_event( void ){;}
00481 };
00482
00483 #endif