/* $Id: wsPageGroup.cpp,v 1.3 2001/09/01 21:32:09 mike Exp $ *********************************************************************** * libwsmake - Core functionality library of wsmake * * Copyright (C) 1999,2000,2001 Michael Brownlow * * * * This program is free software; you can redistribute it and/or modify* * it under the terms of the GNU General Public License as published by* * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * * For questions and comments, please email the author at: * * mike@wsmake.org * ***********************************************************************/ #include "wsmake.h" #ifdef HAVE_GLOB_H #include #endif #include "wsPageGroup.h" #include "wsPagePart.h" #include "wsUtil.h" using namespace std; wsPageGroup::wsPageGroup(string config_path, ifstream *config, int times) : num_pages(0), database_format(DBA_DB_CSV), use_source_timestamp(false) { subtaggroup_list = new wsSubTagGroupList(); pagepart_list = new wsPageList(); pageorder_list = new wsPageOrderList(); theme_list = new wsThemeList(); page_list = new wsPageList(); depend_list = new wsDependList(); this->setConfigDir(config_path); this->setSourceDir("."); this->setOutputDir("."); this->setPartDir("."); this->setIncludeDir("."); this->setTimeFormat("%B %e, %Y"); this->setTimes(times); this->setSubTagFormat("%s"); this->load(config); DBGPRINT(("O:created: wsPageGroup\n")); } wsPageGroup::~wsPageGroup(void) { subtaggroup_list->free(); delete subtaggroup_list; pagepart_list->free(); delete pagepart_list; pageorder_list->free(); delete pageorder_list; theme_list->free(); delete theme_list; depend_list->free(); delete depend_list; // This is the master pagelist, a specific free must be called // which deletes the pages instead of using the pagelist destructor // This way other pagelists will not delete the pages when they // are destructed page_list->free(); // Now delete the master list delete page_list; DBGPRINT(("O:destroyed: wsPageGroup\n")); } int wsPageGroup::getPageGroupTagID(const string *tag) { if(strcmp(tag->c_str(), "lastmod_tagname") == 0) return TAG_LASTMOD_TAGNAME; else if(strcmp(tag->c_str(), "time_format") == 0) return TAG_TIME_FORMAT; else if(strcmp(tag->c_str(), "subtag_format") == 0) return TAG_SUBTAG_FORMAT; else if(strcmp(tag->c_str(), "wsmake_version_tagname") == 0) return TAG_WSMAKE_VERSION_TAGNAME; else if(strcmp(tag->c_str(), "web_path_tagname") == 0) return TAG_OUTPUT_PAGE_TAGNAME; else if(strcmp(tag->c_str(), "output_page_tagname") == 0) return TAG_OUTPUT_PAGE_TAGNAME; else if(strcmp(tag->c_str(), "source_dir") == 0) return TAG_SOURCE_DIR; else if(strcmp(tag->c_str(), "output_dir") == 0) return TAG_OUTPUT_DIR; else if(strcmp(tag->c_str(), "part_dir") == 0) return TAG_PART_DIR; else if(strcmp(tag->c_str(), "command") == 0) return TAG_COMMAND; else if(strcmp(tag->c_str(), "options") == 0) return TAG_OPTIONS; else if(strcmp(tag->c_str(), "source_tagname") == 0) return TAG_SOURCE_TAGNAME; else if(strcmp(tag->c_str(), "output_tagname") == 0) return TAG_OUTPUT_TAGNAME; else if(strcmp(tag->c_str(), "include_tagname") == 0) return TAG_INCLUDE_TAGNAME; else if(strcmp(tag->c_str(), "header_tagname") == 0) return TAG_HEADER_TAGNAME; else if(strcmp(tag->c_str(), "footer_tagname") == 0) return TAG_FOOTER_TAGNAME; else if(strcmp(tag->c_str(), "database_filename") == 0) return TAG_DATABASE_FILENAME; else if(strcmp(tag->c_str(), "database_format") == 0) return TAG_DATABASE_FORMAT; else if(strcmp(tag->c_str(), "depend") == 0) return TAG_DEPEND; else if(strcmp(tag->c_str(), "include_dir") == 0) return TAG_INCLUDE_DIR; else if(strcmp(tag->c_str(), "include") == 0) return TAG_INCLUDE; else if(strcmp(tag->c_str(), "PagePart") == 0) return SECTION_PAGEPART; else if(strcmp(tag->c_str(), "PageOrder") == 0) return SECTION_PAGEORDER; else if(strcmp(tag->c_str(), "SubTagGroup") == 0) return SECTION_SUBTAGGROUP; else if(strcmp(tag->c_str(), "Theme") == 0) return SECTION_THEME; else if(strcmp(tag->c_str(), "Page") == 0) return SECTION_PAGE; else if(strcmp(tag->c_str(), "Webpage") == 0) return SECTION_PAGE; return UNKNOWN; } int wsPageGroup::load(ifstream *input) { string buff; string tag; string value; int done = 0; int line = 0; unsigned x; // For include file parsing #ifdef HAVE_GLOB_H int err; unsigned i; static glob_t matches; #endif list< ifstream * > config; config.push_front(input); while(!done) { line = getNextConfigLine(config.front(), &buff); if(line == 0) { config.pop_front(); if(config.size() == 0) { done = 1; } } else { splitString(&tag, &value, &buff); if(tag.find("}") != string::npos) { done = 1; } else { switch(this->getPageGroupTagID(&tag)) { case TAG_LASTMOD_TAGNAME : chopQuotes(&value); lastmod_tagname.assign(value); break; case TAG_TIME_FORMAT : chopQuotes(&value); this->setTimeFormat(value); break; case TAG_SUBTAG_FORMAT : chopQuotes(&value); this->setSubTagFormat(value); break; case TAG_WSMAKE_VERSION_TAGNAME : chopQuotes(&value); wsmake_version_tagname.assign(value); break; case TAG_OUTPUT_PAGE_TAGNAME : chopQuotes(&value); output_page_tagname.assign(value); break; case TAG_SOURCE_DIR : chopQuotes(&value); this->setSourceDir(value); break; case TAG_OUTPUT_DIR : chopQuotes(&value); this->setOutputDir(value); break; case TAG_PART_DIR : chopQuotes(&value); this->setPartDir(value); break; case TAG_COMMAND : chopQuotes(&value); if(value[0] != '/') { value = this->getConfigDir() + "/" + value; } command.assign(value); break; case TAG_OPTIONS : chopQuotes(&value); options.assign(value); break; case TAG_SOURCE_TAGNAME : chopQuotes(&value); source_tagname.assign(value); break; case TAG_OUTPUT_TAGNAME : chopQuotes(&value); output_tagname.assign(value); break; case TAG_INCLUDE_TAGNAME : chopQuotes(&value); include_tagname.assign(value); x = include_tagname.find("%s"); if( x < string::npos ) { include_tagfront = include_tagname.substr(0,x); include_tagback = include_tagname.substr(x+2, include_tagname.length()); } break; case TAG_HEADER_TAGNAME : chopQuotes(&value); header_tagname.assign(value); break; case TAG_FOOTER_TAGNAME : chopQuotes(&value); footer_tagname.assign(value); break; case TAG_DATABASE_FILENAME : chopQuotes(&value); if(value[0] == '/') { database_filename.assign(collapsePath(value.c_str(), NULL)); } else { database_filename.assign(collapsePath ((config_dir + "/" + value).c_str(), NULL) ); } break; case TAG_DATABASE_FORMAT : chopQuotes(&value); if((value == "BerkeleyDB") || (value == "Berkeley DB") || (value == "DB")) { database_format = DBA_DB_DB; } else if(value == "CSV") { database_format = DBA_DB_CSV; } else if(value == "Timestamp") { database_format = DBA_DB_UNKNOWN; use_source_timestamp = true; this->setTimes(1); } else { __wsmake_print_warning ("don't know what type `%s' is. (line %d), using source timestamps\n" "for this run.\n", value.c_str(), line); __wsmake_print_warning("Valid formats:\n"); __wsmake_print_warning(" DB\n CSV\n Timestamp\n"); database_format = DBA_DB_UNKNOWN; use_source_timestamp = true; this->setTimes(1); } break; case TAG_DEPEND : chopQuotes(&value); if(value[0] != '/') { value.insert(0,"/"); value.insert(0, config_dir); } #ifdef HAVE_GLOB_H if((err=glob(value.c_str(), GLOB_NOCHECK, NULL, &matches)) == 0) { for(i=0; i<(unsigned)matches.gl_pathc; i++) { value.assign(matches.gl_pathv[i]); if(!depend_list->pushBackDepend (wsDepend::findOrCreate(config_dir, value, this))) { __wsmake_print_error("Error adding depend `%s' (line %d)\n", value.c_str(),line); } } } else { __wsmake_print_error("error with glob: %d (line %d)\n", err, line); } #endif break; case TAG_INCLUDE_DIR : chopQuotes(&value); if(value[0] != '/') { value.insert(0, "/"); value.insert(0, config_dir); } include_dir.assign(value); break; case TAG_INCLUDE : chopQuotes(&value); if(value[0] != '/') { value = this->getConfigDir() + "/" + value; } config.push_front(new ifstream(value.c_str(), ios::in)); break; case SECTION_PAGEPART : if(!pagepart_list->pushBackPage (new wsPagePart(this->getConfigDir(), config.front(), this))) { __wsmake_print_error("unable to add pagepart (line %d)\n", line); return 0; } break; case SECTION_PAGEORDER : if(!pageorder_list->pushBackPageOrder (new wsPageOrder(config.front(), pagepart_list))) { __wsmake_print_error("unable to add pageorder (line %d) \n", line); } break; case SECTION_SUBTAGGROUP : if(database_filename.length() == 0) { if(!subtaggroup_list->pushBackSubTagGroup (new wsSubTagGroup(config.front(), subtag_tagfront, subtag_tagback))) { __wsmake_print_error ("unable to add subtaggroup (line %d)\n", line); return 0; } } else { if(!subtaggroup_list->pushBackSubTagGroup (new wsSubTagGroup(config.front(), subtag_tagfront, subtag_tagback, database_filename, database_format))) { __wsmake_print_error ("unable to add subtaggroup (line %d)\n", line); return 0; } } break; case SECTION_THEME : if(database_filename.length() == 0) { if(!theme_list->pushBackTheme (new wsTheme(config.front(), this))) { __wsmake_print_error("unable to add theme (line %d)\n", line); } } else { if(!theme_list->pushBackTheme (new wsTheme(config.front(), this, database_filename, database_format))) { __wsmake_print_error("unable to add theme (line %d)\n", line); } } break; case SECTION_PAGE : if(!page_list->pushBackPage (new wsWebPage(this->getConfigDir(), config.front(), this))) { __wsmake_print_error("unable to add page (line %d)\n", line); } num_pages++; break; case UNKNOWN : default : __wsmake_print_error("unknown website section skipped (line %d): %s\n", line,tag.c_str()); return 0; break; }; } } } if((database_format == DBA_DB_UNKNOWN) && (!use_source_timestamp)) { __wsmake_print_error ( "a database format must be specified if no database filename given.\n" "*** Add something like the following to the pagegroup section:\n" "*** database_format \"DB_TYPE\"\n" "*** where DB_TYPE is one of:\n" "*** DB\n*** CSV\n*** Timestamp\n"); return 0; } if((database_format != DBA_DB_UNKNOWN) && (database_filename.length() == 0)) { __wsmake_print_error ("a database filename must be specified.\n" "*** Add something like the following to the pagegroup section:\n" "*** database_filename \"Your database filename here\"\n"); return 0; } if(source_dir.length() == 0) { __wsmake_print_error("a source directory must be specified.\n" "*** Add something like the following to the pagegroup section:\n" "*** source_dir \"source\"\n"); return 0; } if(output_dir.length() == 0) { __wsmake_print_error("a output directory must be specified.\n" "*** Add something like the following to the pagegroup section:\n" "*** output_dir \"output\"\n"); return 0; } if(part_dir.length() == 0) { __wsmake_print_error("warning: no part directory specified. " "using source directory.\n"); } return 1; } wsSubTagGroup *wsPageGroup::findSubTagGroupWithName(string name) { return subtaggroup_list->findSubTagGroupWithName(name); } wsPageOrder *wsPageGroup::findPageOrderWithName(string name) { return pageorder_list->findPageOrderWithName(name); } wsTheme *wsPageGroup::findThemeWithName(string name) { return theme_list->findThemeWithName(name); } int wsPageGroup::sync(int force) { if(database_format != DBA_DB_UNKNOWN) { depend_list->sync(force); // Check dependencies for this pagegroup first, then set a force if(depend_list->isUpdated()) { force = 1; } // Check subtaggroups for updates subtaggroup_list->sync(force); // This call tells both pageorders and pageorderpages to check if they // have been updated pageorder_list->sync(force); pageorder_list->printSyncs(); // Now check pages theme_list->sync(force); theme_list->printSyncs(); } // Check pages page_list->sync(force); return 1; } int wsPageGroup::make(void) { if(!page_list->make()) return 0; if(!theme_list->make()) return 0; if(!depend_list->make()) return 0; return 1; } int wsPageGroup::make(list< string > targets, int matchtype) { if(!page_list->make(targets, matchtype)) return 0; return 1; } int wsPageGroup::clean(void) { if(!page_list->clean()) return 0; return 1; } int wsPageGroup::clean(list< string > targets, int matchtype) { if(!page_list->clean(targets, matchtype)) return 0; return 1; } int wsPageGroup::parseSubtags(string *line) { if(use_page_list != NULL) { if(use_page_list->parse(line)) return 1; } if(use_group_list != NULL) { if(use_group_list->parse(line)) return 1; } if(use_theme_list != NULL) { if(use_theme_list->parse(line)) return 1; } if(use_internal_list != NULL) { if(use_internal_list->parse(line)) return 1; } return 0; } void wsPageGroup::useTags ( wsSubTagList *use_page_list, wsSubTagGroupList *use_group_list, wsThemeList *use_theme_list, wsSubTagList *use_internal_list) { this->use_page_list = use_page_list; this->use_group_list = use_group_list; this->use_theme_list = use_theme_list; this->use_internal_list = use_internal_list; } void wsPageGroup::setConfigDir(string config_dir) { this->config_dir.assign(config_dir); } int wsPageGroup::validIncludeTag() { // Test if string has %s, if not return 0 if(include_tagname.find("%s") == string::npos) return 0; // If include_tagfront or include_tagback has no value, we // return 0, maybe later we can make it work with only // one side if((include_tagfront.length() == 0)||(include_tagback.length() == 0)) return 0; return 1; } void wsPageGroup::setSubTagFormat(string subtag_format) { unsigned x; this->subtag_format.assign(subtag_format); x = subtag_format.find("%s"); if( x < string::npos ) { subtag_tagfront = subtag_format.substr(0, x); subtag_tagback = subtag_format.substr(x+2, subtag_format.length()); } } void wsPageGroup::printStatType(int stattype) { switch(stattype) { case STATTYPE_NOCHANGE : __wsmake_print(1,"--- "); break; case STATTYPE_ERROR : __wsmake_print(1,"Err "); break; case STATTYPE_NEWPAGE : __wsmake_print(1,"New "); break; case STATTYPE_FORCE : __wsmake_print(1,"Frc "); break; case STATTYPE_SOURCEUPDATED : __wsmake_print(1,"Upd "); break; case STATTYPE_NOOUTPUTPAGE : __wsmake_print(1,"NoO "); break; case STATTYPE_NOSOURCEPAGE : __wsmake_print(1,"NoS "); break; case STATTYPE_OLDOUTPUTPAGE : __wsmake_print(1,"Old "); break; case STATTYPE_PAGEORDERUPDATED : __wsmake_print(1,"PoU "); break; case STATTYPE_THEMEUPDATED : __wsmake_print(1,"ThU "); break; case STATTYPE_DEPENDUPDATED : __wsmake_print(1,"Dep "); break; case STATTYPE_SUBTAGUPDATED : __wsmake_print(1,"StU "); break; case STATTYPE_SUBTAGGROUPUPDATED : __wsmake_print(1,"SGU "); break; default : __wsmake_print(1,"Unk (%d) ", stattype); } } void wsPageGroup::print(void) const { __wsmake_print(3,"PageGroup\n"); __wsmake_print(3,"=========================\n"); __wsmake_print(3," Lastmod Tagname : %s\n", lastmod_tagname.c_str()); __wsmake_print(3," Wsmake Version Tagname: %s\n", wsmake_version_tagname.c_str()); __wsmake_print(3," Output Page Tagname : %s\n", output_page_tagname.c_str()); __wsmake_print(3," Source Tagname : %s\n", source_tagname.c_str()); __wsmake_print(3," Output Tagname : %s\n", output_tagname.c_str()); __wsmake_print(3," Include Tagname : %s\n", include_tagname.c_str()); __wsmake_print(3," Include Tagfront : %s\n", include_tagfront.c_str()); __wsmake_print(3," Include Tagback : %s\n", include_tagback.c_str()); __wsmake_print(3," Header Tagname : %s\n", header_tagname.c_str()); __wsmake_print(3," Footer Tagname : %s\n", footer_tagname.c_str()); __wsmake_print(3," Database Filename : %s\n", database_filename.c_str()); if(__wsmake_get_level() >= 3) { __wsmake_print(3," SubTagGroups : "); subtaggroup_list->printNames(); __wsmake_print(3,"\n"); __wsmake_print(3," PageOrder Pages : "); pagepart_list->printWebPaths(); __wsmake_print(3,"\n"); __wsmake_print(3," PageOrders : "); pageorder_list->printNames(); __wsmake_print(3,"\n"); __wsmake_print(3,"=========================\n"); __wsmake_print(3,"Page Orders\n"); pageorder_list->print(); __wsmake_print(3,"=========================\n"); } page_list->print(); }