COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_core/Patcher.cpp
Go to the documentation of this file.
00001 #include <coopy/Patcher.h>
00002 #include <coopy/MergeOutputSqlDiff.h>
00003 #include <coopy/MergeOutputHumanDiff.h>
00004 #include <coopy/MergeOutputVerboseDiff.h>
00005 #include <coopy/MergeOutputCsvDiff.h>
00006 #include <coopy/MergeOutputTdiff.h>
00007 #include <coopy/MergeOutputPatch.h>
00008 #include <coopy/MergeOutputIndex.h>
00009 #include <coopy/MergeOutputRowOps.h>
00010 #include <coopy/MergeOutputStats.h>
00011 #include <coopy/MergeOutputNovel.h>
00012 #include <coopy/MergeOutputEditList.h>
00013 #include <coopy/SheetPatcher.h>
00014 
00015 #include <algorithm>
00016 
00017 using namespace std;
00018 using namespace coopy::cmp;
00019 using namespace coopy::store;
00020 
00021 
00022 void RowChange::copy(const RowChange& alt) {
00023   mode = alt.mode;
00024   cond = alt.cond;
00025   val = alt.val;
00026   conflictingVal = alt.conflictingVal;
00027   conflictingParentVal = alt.conflictingParentVal;
00028   names = alt.names;
00029   allNames = alt.allNames;
00030   indexes = alt.indexes;
00031   sequential = alt.sequential;
00032   conflicted = alt.conflicted;
00033   pRow = alt.pRow;
00034   lRow = alt.lRow;
00035   rRow = alt.rRow;
00036 }
00037 
00038 int OrderChange::identityToIndex(int id) const {
00039   //if (id==-1) return -1;
00040   vector<int>::const_iterator it = find(indicesBefore.begin(),
00041                                         indicesBefore.end(),id);
00042   if (it == indicesBefore.end()) { return -1; }
00043   return it-indicesBefore.begin();
00044 }
00045 
00046 int OrderChange::identityToIndexAfter(int id) const {
00047   //if (id==-1) return -1;
00048   vector<int>::const_iterator it = find(indicesAfter.begin(),
00049                                         indicesAfter.end(),id);
00050   if (it == indicesAfter.end()) { return -1; }
00051   return it-indicesAfter.begin();
00052 }
00053 
00054 Patcher *Patcher::createByName(const char *name, const char *version) {
00055   string mode(name);
00056   string _version;
00057   if (version!=NULL) _version = version;
00058   Patcher *result = NULL;
00059 #ifndef JUST_HIGHLIGHT
00060   if (mode=="sql") {
00061     result = new MergeOutputSqlDiff;
00062   } else if (mode=="human") {
00063     result = new MergeOutputHumanDiff;
00064   } else if (mode=="raw") {
00065     result = new MergeOutputVerboseDiff;
00066   } else if (mode=="tdiff"||mode=="default") {
00067     result = new MergeOutputTdiff;
00068   } else if (mode=="csv") {
00069     if (_version=="0.2") {
00070       result = new MergeOutputCsvDiffV0p2;
00071     } else if (_version=="0.4"||_version=="0.5"||_version=="") {
00072       result = new MergeOutputCsvDiff;
00073     }
00074   } else if (mode=="csv0") {
00075     result = new MergeOutputPatch;
00076   } else if (mode=="index") {
00077     result = new MergeOutputIndex;
00078   } else if (mode=="ops") {
00079     result = new MergeOutputRowOps;
00080   } else if (mode=="stats") {
00081     result = new MergeOutputStats;
00082   } else if (mode=="novel") {
00083     result = new MergeOutputNovel;
00084   } else if (mode=="edit") {
00085     result = new MergeOutputEditList;
00086   } else 
00087 #endif
00088   if (mode=="apply") {
00089     result = SheetPatcher::createForApply();
00090   } else if (mode=="sheet"||mode=="color"||mode=="hilite"||mode=="highlight"||mode=="hiliter"||mode=="highlighter"||mode=="default") {
00091     result = SheetPatcher::createForDescription();
00092   } else if (mode=="review") {
00093     result = SheetPatcher::createForReview();
00094   } else if (mode=="merge") {
00095     result = SheetPatcher::createForMerge();
00096   } else {
00097     fprintf(stderr, "Format %s?\n", mode.c_str());
00098   }
00099   return result;
00100 }
00101 
00102 
00103 
00104 bool Patcher::startOutput(const std::string& output, CompareFlags& flags) {
00105   if (needOutputBook()) return true;
00106   if (output=="" || output=="-") {
00107     flags.out = stdout;
00108     return true;
00109   }
00110   FILE *fout = fopen(output.c_str(),"wb");
00111   if (fout==NULL) {
00112     fprintf(stderr,"Could not open %s for writing\n", output.c_str());
00113     exit(1);
00114     return false;
00115   }
00116   flags.out = fout;
00117   return true;
00118 }
00119 
00120 bool Patcher::stopOutput(const std::string& output, CompareFlags& flags) {
00121   if (needOutputBook()) return true;
00122   if (flags.out!=stdout) {
00123     fclose(flags.out);
00124     flags.out = stdout;
00125   }
00126   return true;
00127 }
00128 
00129 
00130 bool Patcher::copyFile(const char *src, const char *dest) {
00131   FILE *fin = NULL;
00132   FILE *fout = NULL;
00133   fin = fopen(src,"rb");
00134   if (fin==NULL) return false;
00135   fout = fopen(dest,"wb");
00136   if (fout==NULL) {
00137     fclose(fin);
00138     return false;
00139   }
00140   char buf[32768];
00141   int bytes_read = 0;
00142   while ((bytes_read=fread(buf,1,sizeof(buf),fin))>0) {
00143     fwrite(buf,1,bytes_read,fout);
00144   }
00145   fclose(fout);
00146   fclose(fin);
00147   return true;
00148 }
00149 
00150 bool Patcher::setFlags(const CompareFlags& flags) {
00151   this->flags = flags;
00152   out = flags.out;
00153   return true;
00154 }
00155 
00156 void Patcher::attachBook(coopy::store::TextBook& book) {
00157   patch_book = &book;
00158   pending  = true;
00159 }
00160 
00161 coopy::store::PolySheet Patcher::getSheetBase() {
00162   if (pending) {
00163     pending = false;
00164     coopy::store::TextBook *pbook = getBook();
00165     if (pbook) {
00166       if (flags.tables.size()>0) {
00167         attachSheet(pbook->readSheet(flags.ordered_tables[0]));
00168       } else {
00169         attachSheet(pbook->readSheetByIndex(0));
00170       }
00171     }
00172   }
00173   return patch_sheet;
00174 }
00175 
00176 
00177 coopy::store::PolySheet Patcher::getSheet() {
00178   PolySheet sheet = getSheetBase();
00179   if (!sheet.isValid()) return sheet;
00180   if (!active_sheet.isValid()) {
00181     active_sheet = sheet;
00182   }
00183   if (&sheet.dataTail()!=&active_sheet.dataTail()) {
00184     active_sheet = sheet;
00185   }
00186   if (!getFlags().assume_header) {
00187     active_sheet.forbidSchema();
00188   }
00189   return active_sheet;
00190 }
00191 
00192 
00193 bool Patcher::metaHint(const DataSheet& sheet) {
00194   getSheet();
00195   if (!active_sheet.isValid()) return false;
00196 
00197   if (!active_sheet.getMeta()) {
00198     if (sheet.getMeta()) {
00199       bool done = false;
00200       if (active_sheet.getSchema()) {
00201         dbg_printf("*** meta hint - was %s\n", 
00202                active_sheet.getSchema()->toString().c_str());
00203         done = active_sheet.getSchema()->copy(*sheet.getMeta());
00204       }
00205       if (!done) {
00206         active_sheet.setSchema(sheet.getMeta()->clone(),true);
00207       }
00208       dbg_printf("*** meta hint - is now %s\n", 
00209                  active_sheet.getSchema()->toString().c_str());
00210       if (sheet.hasRowOffset()&&!active_sheet.hasRowOffset()) {
00211         if (sheet.height()==active_sheet.height()) {
00212           active_sheet.getSchema()->setHeaderHeight(0);
00213         }
00214       }
00215       /*
00216       if (sheet.height()!=active_sheet.height()) {
00217         dbg_printf("Height mismatch? %d v %d\n", sheet.height(), active_sheet.height());
00218         active_sheet.mustHaveSchema();
00219         active_sheet.hideHeaders();
00220         if (sheet.height()!=active_sheet.height()) {
00221           dbg_printf("Height mismatch persists\n");
00222         }
00223       }
00224       */
00225       setNames(true);
00226     }
00227   }
00228   return true;
00229 }
00230 
00231 
00232 bool Patcher::applyPool(const PoolChange& change) {
00233   if (flags.pool==NULL) {
00234     fprintf(stderr,"No storage available for pool information.\n");
00235     return false;
00236   }
00237   std::string poolName = change.poolName;
00238   std::string tableName = change.tableName;
00239   for (std::vector<coopy::cmp::TableField>::const_iterator it=change.pool.begin(); it!=change.pool.end(); it++) {
00240     flags.pool->create(poolName,(it->tableName=="")?tableName:(it->tableName),it->fieldName,it->invented);
00241   }
00242   return true;
00243 }
00244 
00245 
00246 
00247 void RowChange::show() {
00248   MergeOutputVerboseDiff diff;
00249   diff.changeRow(*this);
00250 }
00251 
00252 
00253 
00254 
00255 bool Patcher::addPoolsFromFlags(const DataSheet& sheet, bool msg) {
00256   if (flags.coined.size()>0) {
00257 
00258     SheetSchema *ss = sheet.getSchema();
00259     if (!ss) return false;
00260 
00261     string name = ss->getSheetName();
00262 
00263     for (int j=0; j<(int)flags.coined.size(); j++) {
00264       string field = flags.coined[j];
00265       for (int i=0; i<ss->getColumnCount(); i++) {
00266         string field2 = ss->getColumnInfo(i).getName();
00267         if (field==field2) {
00268           PoolChange pc;
00269           pc.poolName = name;
00270           pc.tableName = name;
00271           pc.pool.push_back(TableField("",field,true));
00272           changePool(pc);
00273         }
00274       }
00275     }
00276   } else {
00277     if (flags.pool!=NULL) {
00278       SheetSchema *ss = sheet.getSchema();
00279       if (!ss) return false;
00280       string name = ss->getSheetName();
00281       for (int i=0; i<ss->getColumnCount(); i++) {
00282         string field2 = ss->getColumnInfo(i).getName();
00283         PoolColumnLink link = flags.pool->lookup(name,field2);
00284         if (link.isValid()) {
00285           PoolChange pc;
00286           pc.poolName = link.getPoolName();
00287           pc.tableName = link.getTableName();
00288           pc.pool.push_back(TableField("",link.getColumnName(),link.isInventor()));
00289           if (msg) {
00290             changePool(pc);
00291           } else {
00292             applyPool(pc);
00293           }
00294         }
00295       }
00296     }
00297   }
00298   return true;
00299 }
00300 
00301 
00302 bool Patcher::addPoolsFromSchema(const coopy::store::DataSheet& sheet,
00303                                  const coopy::store::NameSniffer& sniffer,
00304                                  const std::string& sheetName,
00305                                  bool msg) {
00306   const CompareFlags& flags = getFlags();
00307   bool addedAuto = false;
00308   for (int i=0; i<sheet.width(); i++) {
00309     string name = sniffer.suggestColumnName(i);
00310     PoolColumnLink pc = flags.pool->lookup(sheetName,name);
00311     if (!pc.isValid()) {
00312       ColumnType t = sniffer.suggestColumnType(i);
00313       if (t.autoIncrement&&!addedAuto) {
00314         flags.pool->create(sheetName,sheetName,name,true);
00315         pc = flags.pool->lookup(sheetName,name);
00316         addedAuto = true;
00317       }
00318       if (t.foreignKey!="") {
00319         flags.pool->create(t.foreignTable,sheetName,name,false);
00320         pc = flags.pool->lookup(sheetName,name);
00321       }
00322     }
00323     if (pc.isValid()) {
00324       PoolChange c;
00325       c.poolName = pc.getPoolName();
00326       c.tableName = pc.getTableName();
00327       c.pool.push_back(TableField("",pc.getColumnName(),pc.isInventor()));
00328       if (msg) {
00329         changePool(c);
00330       } else {
00331         applyPool(c);
00332       }
00333     }
00334   }
00335   return addedAuto;
00336 }
00337 
00338 
00339 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines